Compare commits

...
Author SHA1 Message Date
Benjamin Doherty e9f4433324 OpenGL: handle glFenceSync returning null 2025-02-06 10:25:32 -08:00
Ben Doherty 05cdeccc27 Stop precaching stereo depth variants on non-supported platforms (#8413) 2025-02-05 11:05:03 -08:00
Mathias Agopian ad4f349f00 Improve external texture image API
The current API used a void* in Texture::setExternalImage to pass
the platform specific image. This was a problem because on some
platform like Android, there could be several types (EGLImageKHR and
AHardwareBuffer), and with the void* there was no way to distinguish
them on the backend / platform side.

We now have a new Texture API which takes a
Platform::ExternalImageHandle, which is a reference-counted handle
to a Platform::ExternalImage. Platform::ExternalImage is an opaque
type only known by the platform.

This type must be created using a concrete Platform specific API, such
as:

PlatformEGL::createExternalImage
PlatformEGLAndroid::createExternalImage
PlatformCocoaGL::createExternalImage
PlatformCocoaTouchGL::createExternalImage

New types can easily be added in the future.

There is no "destroy" call because the Platform::ExternalImageHandle is
reference-counted and the client can let go of it as soon as it
doesn't need it any longer (typically after calling
Texture::setExternalImage). Platform::ExternalImage is a small
structure that just anonymously wraps the concrete types.

New internal driver APIs have been added to handle this functionality.
2025-02-04 13:16:56 -08:00
Mathias Agopian 06a2def85f make sure FXAA resets alpha channel when it's the last postfx (#8412)
If FXAA is the last post process effect (i.e. no upscaling), and
color grading produced a luma channel, then FXAA needs to reset the
alpha channel to 1.
2025-02-04 19:52:37 +00:00
Powei Feng a04019937e Add feature flag for material/instance destroy assert (#8411)
This will allow a more lenient rollout of the assertion, which
otherwise will increase crashes for current clients.

We also disable features.engine.debug.assert_material_instance_in_use
by default (it was enabled for debug builds).
2025-02-04 19:30:40 +00:00
Ben Doherty fff7bd2b28 Combine and install Abseil (#8387) 2025-02-04 09:32:49 -08:00
Powei Feng 3c4591df17 java: must use return var in Engine (#8409) 2025-02-03 22:53:44 -08:00
31 changed files with 703 additions and 160 deletions
+17 -10
View File
@@ -667,10 +667,6 @@ function(list_licenses OUTPUT MODULES)
endfunction()
set(COMBINE_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/build/linux/combine-static-libs.sh")
if (WIN32)
set(COMBINE_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/build/windows/combine-static-libs.bat")
set(CMAKE_AR "lib.exe")
endif()
# Add a custom command to TARGET that combines the static libraries in DEPS into a single archive.
function(combine_static_libs TARGET OUTPUT DEPS)
@@ -685,12 +681,22 @@ function(combine_static_libs TARGET OUTPUT DEPS)
endif()
endforeach()
add_custom_command(
TARGET ${TARGET} POST_BUILD
COMMAND "${COMBINE_SCRIPT}" "${CMAKE_AR}" "${OUTPUT}" ${DEPS_FILES}
COMMENT "Combining ${target} dependencies into single shared library"
VERBATIM
)
if (WIN32)
add_custom_command(
TARGET ${TARGET} POST_BUILD
COMMAND lib.exe /nologo /out:temp.lib ${DEPS_FILES}
COMMAND "${CMAKE_COMMAND}" -E rename temp.lib ${OUTPUT}
COMMENT "Combining ${target} dependencies into single shared library"
VERBATIM
)
else()
add_custom_command(
TARGET ${TARGET} POST_BUILD
COMMAND "${COMBINE_SCRIPT}" "${CMAKE_AR}" "${OUTPUT}" ${DEPS_FILES}
COMMENT "Combining ${target} dependencies into single shared library"
VERBATIM
)
endif()
endfunction()
# ==================================================================================================
@@ -761,6 +767,7 @@ add_subdirectory(${LIBRARIES}/utils)
add_subdirectory(${LIBRARIES}/viewer)
add_subdirectory(${FILAMENT}/filament)
add_subdirectory(${FILAMENT}/shaders)
add_subdirectory(${EXTERNAL}/abseil/tnt)
add_subdirectory(${EXTERNAL}/basisu/tnt)
add_subdirectory(${EXTERNAL}/civetweb/tnt)
add_subdirectory(${EXTERNAL}/imgui/tnt)
+1
View File
@@ -9,3 +9,4 @@ appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
## Release notes for next branch cut
- matdbg: Add support for debugging ESSL 1.0 shaders
- backend: New platform API to better handle external textures [⚠️ **New Material Version**]
@@ -1271,7 +1271,7 @@ public class Engine {
* {@link android.view.SurfaceHolder.Callback#surfaceDestroyed surfaceDestroyed}.</p>
*/
public void flushAndWait() {
flushAndWait(Fence.WAIT_FOR_EVER);
boolean unused = flushAndWait(Fence.WAIT_FOR_EVER);
}
/**
-39
View File
@@ -1,39 +0,0 @@
@echo off
set selfName=%0
:: Check that we have at least 3 arguments.
set argC=0
for %%x in (%*) do Set /A argC+=1
if %argC% LSS 3 goto :print_help
set AR_TOOL=%1
shift
set OUTPUT_PATH=%1
shift
set ARCHIVES=
:loop
if [%1]==[] goto :finished
set ARCHIVES=%ARCHIVES% %1
shift
goto :loop
:finished
%AR_TOOL% /nologo /out:%OUTPUT_PATH% %ARCHIVES% || goto :error
exit /B %ERRORLEVEL%
:print_help
echo %selfName%. Combine multiple static libraries using an archiver tool.
echo;
echo Usage:
echo %selfName% ^<path-to-ar^> ^<output-archive^> ^<archives^>...
echo;
echo Notes:
echo ^<archives^> must be a list of absolute paths to static library archives.
echo This script creates a temporary working directory inside the current directory.
exit /B 1
:error
exit /B %ERRORLEVEL%
@@ -25,6 +25,8 @@
#include <stddef.h>
#include <stdint.h>
#include <atomic>
namespace filament::backend {
class Driver;
@@ -41,6 +43,46 @@ public:
struct Fence {};
struct Stream {};
class ExternalImageHandle;
class ExternalImage {
friend class ExternalImageHandle;
std::atomic_uint32_t mRefCount{0};
protected:
virtual ~ExternalImage() noexcept;
};
class ExternalImageHandle {
ExternalImage* UTILS_NULLABLE mTarget = nullptr;
static void incref(ExternalImage* UTILS_NULLABLE p) noexcept;
static void decref(ExternalImage* UTILS_NULLABLE p) noexcept;
public:
ExternalImageHandle() noexcept;
~ExternalImageHandle() noexcept;
explicit ExternalImageHandle(ExternalImage* UTILS_NULLABLE p) noexcept;
ExternalImageHandle(ExternalImageHandle const& rhs) noexcept;
ExternalImageHandle(ExternalImageHandle&& rhs) noexcept;
ExternalImageHandle& operator=(ExternalImageHandle const& rhs) noexcept;
ExternalImageHandle& operator=(ExternalImageHandle&& rhs) noexcept;
explicit operator bool() const noexcept { return mTarget != nullptr; }
ExternalImage* UTILS_NULLABLE get() noexcept { return mTarget; }
ExternalImage const* UTILS_NULLABLE get() const noexcept { return mTarget; }
ExternalImage* UTILS_NULLABLE operator->() noexcept { return mTarget; }
ExternalImage const* UTILS_NULLABLE operator->() const noexcept { return mTarget; }
ExternalImage& operator*() noexcept { return *mTarget; }
ExternalImage const& operator*() const noexcept { return *mTarget; }
void clear() noexcept;
void reset(ExternalImage* UTILS_NULLABLE p) noexcept;
};
using ExternalImageHandleRef = ExternalImageHandle const&;
/**
* The type of technique for stereoscopic rendering. (Note that the materials used will need to
* be compatible with the chosen technique.)
@@ -51,10 +51,9 @@ protected:
~OpenGLPlatform() noexcept override;
public:
struct ExternalTexture {
unsigned int target; // GLenum target
unsigned int id; // GLuint id
unsigned int target; // GLenum target
unsigned int id; // GLuint id
};
/**
@@ -324,36 +323,45 @@ public:
* Destroys an external texture handle and associated data.
* @param texture a pointer to the handle to destroy.
*/
virtual void destroyExternalImage(ExternalTexture* UTILS_NONNULL texture) noexcept;
virtual void destroyExternalImageTexture(ExternalTexture* UTILS_NONNULL texture) noexcept;
// called on the application thread to allow Filament to take ownership of the image
/**
* Takes ownership of the externalImage. The externalImage parameter depends on the Platform's
* concrete implementation. Ownership is released when destroyExternalImage() is called.
* concrete implementation. Ownership is released when destroyExternalImageTexture() is called.
*
* WARNING: This is called synchronously from the application thread (NOT the Driver thread)
*
* @param externalImage A token representing the platform's external image.
* @see destroyExternalImage
* @{
*/
virtual void retainExternalImage(void* UTILS_NONNULL externalImage) noexcept;
virtual void retainExternalImage(ExternalImageHandleRef externalImage) noexcept;
/** @}*/
/**
* Called to bind the platform-specific externalImage to an ExternalTexture.
* ExternalTexture::id is guaranteed to be bound when this method is called and ExternalTexture
* is updated with new values for id/target if necessary.
*
* WARNING: this method is not allowed to change the bound texture, or must restore the previous
* binding upon return. This is to avoid problem with a backend doing state caching.
* binding upon return. This is to avoid a problem with a backend doing state caching.
*
* @param externalImage The platform-specific external image.
* @param texture an in/out pointer to ExternalTexture, id and target can be updated if necessary.
* @return true on success, false on error.
* @{
*/
virtual bool setExternalImage(void* UTILS_NONNULL externalImage,
ExternalTexture* UTILS_NONNULL texture) noexcept;
virtual bool setExternalImage(ExternalImageHandleRef externalImage,
ExternalTexture* UTILS_NONNULL texture) noexcept;
/** @}*/
/**
* The method allows platforms to convert a user-supplied external image object into a new type
* (e.g. HardwareBuffer => EGLImage). The default implementation returns source.
@@ -34,12 +34,14 @@ public:
PlatformCocoaGL();
~PlatformCocoaGL() noexcept override;
ExternalImageHandle createExternalImage(void* cvPixelBuffer) noexcept;
protected:
// --------------------------------------------------------------------------------------------
// Platform Interface
Driver* createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) noexcept override;
const DriverConfig& driverConfig) noexcept override;
// Currently returns 0
int getOSVersion() const noexcept override;
@@ -59,10 +61,12 @@ protected:
void destroySwapChain(SwapChain* swapChain) noexcept override;
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;
void destroyExternalImage(ExternalTexture* texture) noexcept override;
ExternalTexture* createExternalImageTexture() noexcept override;
void destroyExternalImageTexture(ExternalTexture* texture) noexcept override;
void retainExternalImage(void* externalImage) noexcept override;
bool setExternalImage(void* externalImage, ExternalTexture* texture) noexcept override;
void retainExternalImage(ExternalImageHandleRef externalImage) noexcept override;
bool setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept override;
private:
PlatformCocoaGLImpl* pImpl = nullptr;
@@ -32,11 +32,13 @@ public:
PlatformCocoaTouchGL();
~PlatformCocoaTouchGL() noexcept override;
ExternalImageHandle createExternalImage(void* cvPixelBuffer) noexcept;
// --------------------------------------------------------------------------------------------
// Platform Interface
Driver* createDriver(void* sharedGLContext,
const Platform::DriverConfig& driverConfig) noexcept override;
const DriverConfig& driverConfig) noexcept override;
int getOSVersion() const noexcept final { return 0; }
@@ -56,10 +58,12 @@ public:
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;
void destroyExternalImage(ExternalTexture* texture) noexcept override;
ExternalTexture* createExternalImageTexture() noexcept override;
void destroyExternalImageTexture(ExternalTexture* texture) noexcept override;
void retainExternalImage(void* externalImage) noexcept override;
bool setExternalImage(void* externalImage, ExternalTexture* texture) noexcept override;
void retainExternalImage(ExternalImageHandleRef externalImage) noexcept override;
bool setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept override;
private:
PlatformCocoaTouchGLImpl* pImpl = nullptr;
@@ -47,6 +47,11 @@ public:
// Return true if we're on an OpenGL platform (as opposed to OpenGL ES). false by default.
virtual bool isOpenGL() const noexcept;
/**
* Creates an ExternalImage from a EGLImageKHR
*/
ExternalImageHandle createExternalImage(EGLImageKHR eglImage) noexcept;
protected:
// --------------------------------------------------------------------------------------------
// Helper for EGL configs and attributes parameters
@@ -118,9 +123,10 @@ protected:
void destroyFence(Fence* fence) noexcept override;
FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept override;
OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;
void destroyExternalImage(ExternalTexture* texture) noexcept override;
ExternalTexture* createExternalImageTexture() noexcept override;
void destroyExternalImageTexture(ExternalTexture* texture) noexcept override;
bool setExternalImage(void* externalImage, ExternalTexture* texture) noexcept override;
bool setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept override;
/**
* Logs glGetError() to slog.e
@@ -188,6 +194,12 @@ protected:
void initializeGlExtensions() noexcept;
struct ExternalImageEGL : public ExternalImage {
EGLImageKHR eglImage = EGL_NO_IMAGE;
protected:
~ExternalImageEGL() override;
};
protected:
EGLConfig findSwapChainConfig(uint64_t flags, bool window, bool pbuffer) const;
@@ -57,6 +57,11 @@ protected:
Driver* createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) noexcept override;
/**
* Creates an ExternalImage from a EGLImageKHR
*/
ExternalImageHandle createExternalImage(AHardwareBuffer const *buffer, bool sRGB) noexcept;
// --------------------------------------------------------------------------------------------
// OpenGLPlatform Interface
@@ -89,6 +94,15 @@ protected:
*/
AcquiredImage transformAcquiredImage(AcquiredImage source) noexcept override;
bool setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept override;
struct ExternalImageEGLAndroid : public ExternalImageEGL {
AHardwareBuffer* aHardwareBuffer = nullptr;
bool sRGB = false;
protected:
~ExternalImageEGLAndroid() override;
};
protected:
bool makeCurrent(ContextType type,
SwapChain* drawSwapChain,
@@ -215,6 +215,14 @@ DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureViewSwizzle,
backend::TextureSwizzle, b,
backend::TextureSwizzle, a)
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureExternalImage2,
backend::SamplerType, target,
backend::TextureFormat, format,
uint32_t, width,
uint32_t, height,
backend::TextureUsage, usage,
backend::Platform::ExternalImageHandleRef, image)
DECL_DRIVER_API_R_N(backend::TextureHandle, createTextureExternalImage,
backend::SamplerType, target,
backend::TextureFormat, format,
@@ -355,6 +363,7 @@ DECL_DRIVER_API_SYNCHRONOUS_0(bool, isDepthClampSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(uint8_t, getMaxDrawBuffers)
DECL_DRIVER_API_SYNCHRONOUS_0(size_t, getMaxUniformBufferSize)
DECL_DRIVER_API_SYNCHRONOUS_0(math::float2, getClipSpaceParams)
DECL_DRIVER_API_SYNCHRONOUS_N(void, setupExternalImage2, backend::Platform::ExternalImageHandleRef, image)
DECL_DRIVER_API_SYNCHRONOUS_N(void, setupExternalImage, void*, image)
DECL_DRIVER_API_SYNCHRONOUS_N(backend::TimerQueryResult, getTimerQueryValue, backend::TimerQueryHandle, query, uint64_t*, elapsedTime)
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isWorkaroundNeeded, backend::Workaround, workaround)
+85
View File
@@ -16,8 +16,93 @@
#include <backend/Platform.h>
#include <utils/compiler.h>
#include <atomic>
#include <utility>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
void Platform::ExternalImageHandle::incref(ExternalImage* p) noexcept {
if (p) {
// incrementing the ref-count doesn't acquire or release anything
p->mRefCount.fetch_add(1, std::memory_order_relaxed);
}
}
void Platform::ExternalImageHandle::decref(ExternalImage* p) noexcept {
if (p) {
// When decrementing the ref-count, unless it reaches zero, there is no need to acquire data; we need to
// release all previous writes though so they can be visible to the thread that will actually delete the
// object.
if (p->mRefCount.fetch_sub(1, std::memory_order_release) == 1) {
// if we reach zero, we're about to delete the object, we need to acquire all previous writes from other
// threads (i.e.: the memory from other threads prior to the decref() need to be visible now.
std::atomic_thread_fence(std::memory_order_acquire);
delete p;
}
}
}
Platform::ExternalImageHandle::ExternalImageHandle() noexcept = default;
Platform::ExternalImageHandle::~ExternalImageHandle() noexcept {
decref(mTarget);
}
Platform::ExternalImageHandle::ExternalImageHandle(ExternalImage* p) noexcept
: mTarget(p) {
incref(mTarget);
}
Platform::ExternalImageHandle::ExternalImageHandle(ExternalImageHandle const& rhs) noexcept
: mTarget(rhs.mTarget) {
incref(mTarget);
}
Platform::ExternalImageHandle::ExternalImageHandle(ExternalImageHandle&& rhs) noexcept
: mTarget(rhs.mTarget) {
rhs.mTarget = nullptr;
}
Platform::ExternalImageHandle& Platform::ExternalImageHandle::operator=(ExternalImageHandle const& rhs) noexcept {
if (UTILS_LIKELY(this != &rhs)) {
incref(rhs.mTarget);
decref(mTarget);
mTarget = rhs.mTarget;
}
return *this;
}
Platform::ExternalImageHandle& Platform::ExternalImageHandle::operator=(ExternalImageHandle&& rhs) noexcept {
if (UTILS_LIKELY(this != &rhs)) {
decref(mTarget);
mTarget = rhs.mTarget;
rhs.mTarget = nullptr;
}
return *this;
}
void Platform::ExternalImageHandle::clear() noexcept {
decref(mTarget);
mTarget = nullptr;
}
void Platform::ExternalImageHandle::reset(ExternalImage* p) noexcept {
incref(p);
decref(mTarget);
mTarget = p;
}
// --------------------------------------------------------------------------------------------------------------------
Platform::ExternalImage::~ExternalImage() noexcept = default;
// --------------------------------------------------------------------------------------------------------------------
Platform::Platform() noexcept = default;
// this generates the vtable in this translation unit
+16
View File
@@ -513,6 +513,14 @@ void MetalDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTextu
mContext->textures.insert(construct_handle<MetalTexture>(th, *mContext, src, r, g, b, a));
}
void MetalDriver::createTextureExternalImage2R(Handle<HwTexture> th,
backend::SamplerType target,
backend::TextureFormat format,
uint32_t width, uint32_t height, backend::TextureUsage usage,
Platform::ExternalImageHandleRef image) {
// FIXME: implement createTextureExternalImage2R
}
void MetalDriver::createTextureExternalImageR(Handle<HwTexture> th,
backend::SamplerType target,
backend::TextureFormat format,
@@ -747,6 +755,10 @@ Handle<HwTexture> MetalDriver::createTextureViewSwizzleS() noexcept {
return alloc_handle<MetalTexture>();
}
Handle<HwTexture> MetalDriver::createTextureExternalImage2S() noexcept {
return alloc_handle<MetalTexture>();
}
Handle<HwTexture> MetalDriver::createTextureExternalImageS() noexcept {
return alloc_handle<MetalTexture>();
}
@@ -1218,6 +1230,10 @@ void MetalDriver::update3DImage(Handle<HwTexture> th, uint32_t level,
th.getId(), level, xoffset, yoffset, zoffset, width, height, depth);
}
void MetalDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
// FIXME: implement setupExternalImage2
}
void MetalDriver::setupExternalImage(void* image) {
// setupExternalImage is called on the Filament thread when creating a Texture or SwapChain from
// a CVPixelBuffer external image. Here we take ownership of the passed in buffer by calling
+7
View File
@@ -17,6 +17,10 @@
#include "noop/NoopDriver.h"
#include "CommandStreamDispatcher.h"
#include <backend/Handle.h>
#include <stdint.h>
namespace filament::backend {
Driver* NoopDriver::create() {
@@ -262,6 +266,9 @@ void NoopDriver::update3DImage(Handle<HwTexture> th,
scheduleDestroy(std::move(data));
}
void NoopDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
}
void NoopDriver::setupExternalImage(void* image) {
}
+44 -23
View File
@@ -18,6 +18,7 @@
#define TNT_FILAMENT_BACKEND_OPENGL_GLUTILS_H
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/Log.h>
#include <backend/DriverEnums.h>
@@ -25,6 +26,8 @@
#include <string_view>
#include <unordered_set>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "gl_headers.h"
@@ -50,7 +53,7 @@ void assertFramebufferStatus(utils::io::ostream& out, GLenum target, const char*
# define CHECK_GL_FRAMEBUFFER_STATUS(out, target) { GLUtils::checkFramebufferStatus(out, target, __func__, __LINE__); }
#endif
constexpr inline GLuint getComponentCount(ElementType type) noexcept {
constexpr GLuint getComponentCount(ElementType type) noexcept {
using ElementType = ElementType;
switch (type) {
case ElementType::BYTE:
@@ -90,7 +93,7 @@ constexpr inline GLuint getComponentCount(ElementType type) noexcept {
// Our enums to GLenum conversions
// ------------------------------------------------------------------------------------------------
constexpr inline GLbitfield getAttachmentBitfield(TargetBufferFlags flags) noexcept {
constexpr GLbitfield getAttachmentBitfield(TargetBufferFlags flags) noexcept {
GLbitfield mask = 0;
if (any(flags & TargetBufferFlags::COLOR_ALL)) {
mask |= (GLbitfield)GL_COLOR_BUFFER_BIT;
@@ -104,7 +107,7 @@ constexpr inline GLbitfield getAttachmentBitfield(TargetBufferFlags flags) noexc
return mask;
}
constexpr inline GLenum getBufferUsage(BufferUsage usage) noexcept {
constexpr GLenum getBufferUsage(BufferUsage usage) noexcept {
switch (usage) {
case BufferUsage::STATIC:
return GL_STATIC_DRAW;
@@ -113,7 +116,7 @@ constexpr inline GLenum getBufferUsage(BufferUsage usage) noexcept {
}
}
constexpr inline GLenum getBufferBindingType(BufferObjectBinding bindingType) noexcept {
constexpr GLenum getBufferBindingType(BufferObjectBinding bindingType) noexcept {
switch (bindingType) {
case BufferObjectBinding::VERTEX:
return GL_ARRAY_BUFFER;
@@ -134,11 +137,11 @@ constexpr inline GLenum getBufferBindingType(BufferObjectBinding bindingType) no
}
}
constexpr inline GLboolean getNormalization(bool normalized) noexcept {
constexpr GLboolean getNormalization(bool normalized) noexcept {
return GLboolean(normalized ? GL_TRUE : GL_FALSE);
}
constexpr inline GLenum getComponentType(ElementType type) noexcept {
constexpr GLenum getComponentType(ElementType type) noexcept {
using ElementType = ElementType;
switch (type) {
case ElementType::BYTE:
@@ -183,12 +186,30 @@ constexpr inline GLenum getComponentType(ElementType type) noexcept {
}
}
constexpr inline GLenum getCubemapTarget(uint16_t layer) noexcept {
constexpr GLenum getTextureTargetNotExternal(SamplerType target) noexcept {
switch (target) {
case SamplerType::SAMPLER_2D:
return GL_TEXTURE_2D;
case SamplerType::SAMPLER_3D:
return GL_TEXTURE_3D;
case SamplerType::SAMPLER_2D_ARRAY:
return GL_TEXTURE_2D_ARRAY;
case SamplerType::SAMPLER_CUBEMAP:
return GL_TEXTURE_CUBE_MAP;
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
return GL_TEXTURE_CUBE_MAP_ARRAY;
case SamplerType::SAMPLER_EXTERNAL:
// we should never be here
return GL_TEXTURE_2D;
}
}
constexpr GLenum getCubemapTarget(uint16_t layer) noexcept {
assert_invariant(layer <= 5);
return GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
}
constexpr inline GLenum getWrapMode(SamplerWrapMode mode) noexcept {
constexpr GLenum getWrapMode(SamplerWrapMode mode) noexcept {
using SamplerWrapMode = SamplerWrapMode;
switch (mode) {
case SamplerWrapMode::REPEAT:
@@ -200,7 +221,7 @@ constexpr inline GLenum getWrapMode(SamplerWrapMode mode) noexcept {
}
}
constexpr inline GLenum getTextureFilter(SamplerMinFilter filter) noexcept {
constexpr GLenum getTextureFilter(SamplerMinFilter filter) noexcept {
using SamplerMinFilter = SamplerMinFilter;
switch (filter) {
case SamplerMinFilter::NEAREST:
@@ -215,12 +236,12 @@ constexpr inline GLenum getTextureFilter(SamplerMinFilter filter) noexcept {
}
}
constexpr inline GLenum getTextureFilter(SamplerMagFilter filter) noexcept {
constexpr GLenum getTextureFilter(SamplerMagFilter filter) noexcept {
return GL_NEAREST + GLenum(filter);
}
constexpr inline GLenum getBlendEquationMode(BlendEquation mode) noexcept {
constexpr GLenum getBlendEquationMode(BlendEquation mode) noexcept {
using BlendEquation = BlendEquation;
switch (mode) {
case BlendEquation::ADD: return GL_FUNC_ADD;
@@ -231,7 +252,7 @@ constexpr inline GLenum getBlendEquationMode(BlendEquation mode) noexcept {
}
}
constexpr inline GLenum getBlendFunctionMode(BlendFunction mode) noexcept {
constexpr GLenum getBlendFunctionMode(BlendFunction mode) noexcept {
using BlendFunction = BlendFunction;
switch (mode) {
case BlendFunction::ZERO: return GL_ZERO;
@@ -248,7 +269,7 @@ constexpr inline GLenum getBlendFunctionMode(BlendFunction mode) noexcept {
}
}
constexpr inline GLenum getCompareFunc(SamplerCompareFunc func) noexcept {
constexpr GLenum getCompareFunc(SamplerCompareFunc func) noexcept {
switch (func) {
case SamplerCompareFunc::LE: return GL_LEQUAL;
case SamplerCompareFunc::GE: return GL_GEQUAL;
@@ -262,25 +283,25 @@ constexpr inline GLenum getCompareFunc(SamplerCompareFunc func) noexcept {
}
#ifndef FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
constexpr inline GLenum getTextureCompareMode(SamplerCompareMode mode) noexcept {
constexpr GLenum getTextureCompareMode(SamplerCompareMode mode) noexcept {
return mode == SamplerCompareMode::NONE ?
GL_NONE : GL_COMPARE_REF_TO_TEXTURE;
}
constexpr inline GLenum getTextureCompareFunc(SamplerCompareFunc func) noexcept {
constexpr GLenum getTextureCompareFunc(SamplerCompareFunc func) noexcept {
return getCompareFunc(func);
}
#endif
constexpr inline GLenum getDepthFunc(SamplerCompareFunc func) noexcept {
constexpr GLenum getDepthFunc(SamplerCompareFunc func) noexcept {
return getCompareFunc(func);
}
constexpr inline GLenum getStencilFunc(SamplerCompareFunc func) noexcept {
constexpr GLenum getStencilFunc(SamplerCompareFunc func) noexcept {
return getCompareFunc(func);
}
constexpr inline GLenum getStencilOp(StencilOperation op) noexcept {
constexpr GLenum getStencilOp(StencilOperation op) noexcept {
switch (op) {
case StencilOperation::KEEP: return GL_KEEP;
case StencilOperation::ZERO: return GL_ZERO;
@@ -293,7 +314,7 @@ constexpr inline GLenum getStencilOp(StencilOperation op) noexcept {
}
}
constexpr inline GLenum getFormat(PixelDataFormat format) noexcept {
constexpr GLenum getFormat(PixelDataFormat format) noexcept {
using PixelDataFormat = PixelDataFormat;
switch (format) {
case PixelDataFormat::RGB: return GL_RGB;
@@ -317,7 +338,7 @@ constexpr inline GLenum getFormat(PixelDataFormat format) noexcept {
}
}
constexpr inline GLenum getType(PixelDataType type) noexcept {
constexpr GLenum getType(PixelDataType type) noexcept {
using PixelDataType = PixelDataType;
switch (type) {
case PixelDataType::UBYTE: return GL_UNSIGNED_BYTE;
@@ -342,7 +363,7 @@ constexpr inline GLenum getType(PixelDataType type) noexcept {
}
#if !defined(__EMSCRIPTEN__) && !defined(FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2)
constexpr inline GLenum getSwizzleChannel(TextureSwizzle c) noexcept {
constexpr GLenum getSwizzleChannel(TextureSwizzle c) noexcept {
using TextureSwizzle = TextureSwizzle;
switch (c) {
case TextureSwizzle::SUBSTITUTE_ZERO: return GL_ZERO;
@@ -355,7 +376,7 @@ constexpr inline GLenum getSwizzleChannel(TextureSwizzle c) noexcept {
}
#endif
constexpr inline GLenum getCullingMode(CullingMode mode) noexcept {
constexpr GLenum getCullingMode(CullingMode mode) noexcept {
switch (mode) {
case CullingMode::NONE:
// should never happen
@@ -370,7 +391,7 @@ constexpr inline GLenum getCullingMode(CullingMode mode) noexcept {
}
// ES2 supported internal formats for texturing and how they map to a format/type
constexpr inline std::pair<GLenum, GLenum> textureFormatToFormatAndType(
constexpr std::pair<GLenum, GLenum> textureFormatToFormatAndType(
TextureFormat format) noexcept {
switch (format) {
case TextureFormat::R8: return { 0x1909 /*GL_LUMINANCE*/, GL_UNSIGNED_BYTE };
+80 -22
View File
@@ -582,6 +582,10 @@ Handle<HwTexture> OpenGLDriver::createTextureViewSwizzleS() noexcept {
return initHandle<GLTexture>();
}
Handle<HwTexture> OpenGLDriver::createTextureExternalImage2S() noexcept {
return initHandle<GLTexture>();
}
Handle<HwTexture> OpenGLDriver::createTextureExternalImageS() noexcept {
return initHandle<GLTexture>();
}
@@ -903,25 +907,7 @@ void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
t->gl.internalFormat = internalFormat;
switch (target) {
case SamplerType::SAMPLER_EXTERNAL:
// we can't be here -- doesn't matter what we do
case SamplerType::SAMPLER_2D:
t->gl.target = GL_TEXTURE_2D;
break;
case SamplerType::SAMPLER_3D:
t->gl.target = GL_TEXTURE_3D;
break;
case SamplerType::SAMPLER_2D_ARRAY:
t->gl.target = GL_TEXTURE_2D_ARRAY;
break;
case SamplerType::SAMPLER_CUBEMAP:
t->gl.target = GL_TEXTURE_CUBE_MAP;
break;
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
t->gl.target = GL_TEXTURE_CUBE_MAP_ARRAY;
break;
}
t->gl.target = getTextureTargetNotExternal(target);
if (t->samples > 1) {
// Note: we can't be here in practice because filament's user API doesn't
@@ -995,8 +981,7 @@ void OpenGLDriver::createTextureViewR(Handle<HwTexture> th,
}
void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
backend::TextureSwizzle r, backend::TextureSwizzle g, backend::TextureSwizzle b,
backend::TextureSwizzle a) {
TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a) {
DEBUG_MARKER()
GLTexture const* const src = handle_cast<GLTexture const*>(srch);
@@ -1058,6 +1043,57 @@ void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwText
CHECK_GL_ERROR(utils::slog.e)
}
void OpenGLDriver::createTextureExternalImage2R(Handle<HwTexture> th, SamplerType target,
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage,
Platform::ExternalImageHandleRef image) {
DEBUG_MARKER()
usage |= TextureUsage::SAMPLEABLE;
usage &= ~TextureUsage::UPLOADABLE;
auto& gl = mContext;
GLenum internalFormat = getInternalFormat(format);
if (UTILS_UNLIKELY(gl.isES2())) {
// on ES2, format and internal format must match
// FIXME: handle compressed texture format
internalFormat = textureFormatToFormatAndType(format).first;
}
assert_invariant(internalFormat);
GLTexture* const t = construct<GLTexture>(th, target, 1, 1, width, height, 1, format, usage);
assert_invariant(t);
t->externalTexture = mPlatform.createExternalImageTexture();
if (t->externalTexture) {
if (target == SamplerType::SAMPLER_EXTERNAL) {
if (UTILS_LIKELY(gl.ext.OES_EGL_image_external_essl3)) {
t->externalTexture->target = GL_TEXTURE_EXTERNAL_OES;
} else {
// revert to texture 2D if external is not supported; what else can we do?
t->externalTexture->target = GL_TEXTURE_2D;
}
} else {
t->externalTexture->target = getTextureTargetNotExternal(target);
}
t->gl.target = t->externalTexture->target;
t->gl.id = t->externalTexture->id;
// internalFormat actually depends on the external image, but it doesn't matter
// because it's not used anywhere for anything important.
t->gl.internalFormat = internalFormat;
t->gl.baseLevel = 0;
t->gl.maxLevel = 0;
t->gl.external = true; // forces bindTexture() call (they're never cached)
}
bindTexture(OpenGLContext::DUMMY_TEXTURE_BINDING, t);
if (mPlatform.setExternalImage(image, t->externalTexture)) {
// the target and id can be reset each time
t->gl.target = t->externalTexture->target;
t->gl.id = t->externalTexture->id;
}
}
void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, SamplerType target,
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage, void* image) {
DEBUG_MARKER()
@@ -1079,6 +1115,16 @@ void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, SamplerType
t->externalTexture = mPlatform.createExternalImageTexture();
if (t->externalTexture) {
if (target == SamplerType::SAMPLER_EXTERNAL) {
if (UTILS_LIKELY(gl.ext.OES_EGL_image_external_essl3)) {
t->externalTexture->target = GL_TEXTURE_EXTERNAL_OES;
} else {
// revert to texture 2D if external is not supported; what else can we do?
t->externalTexture->target = GL_TEXTURE_2D;
}
} else {
t->externalTexture->target = getTextureTargetNotExternal(target);
}
t->gl.target = t->externalTexture->target;
t->gl.id = t->externalTexture->id;
// internalFormat actually depends on the external image, but it doesn't matter
@@ -1870,7 +1916,7 @@ void OpenGLDriver::destroyTexture(Handle<HwTexture> th) {
detachStream(t);
}
if (UTILS_UNLIKELY(t->target == SamplerType::SAMPLER_EXTERNAL)) {
mPlatform.destroyExternalImage(t->externalTexture);
mPlatform.destroyExternalImageTexture(t->externalTexture);
} else {
glDeleteTextures(1, &t->gl.id);
}
@@ -2809,6 +2855,10 @@ void OpenGLDriver::setCompressedTextureData(GLTexture* t, uint32_t level,
CHECK_GL_ERROR(utils::slog.e)
}
void OpenGLDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
mPlatform.retainExternalImage(image);
}
void OpenGLDriver::setupExternalImage(void* image) {
mPlatform.retainExternalImage(image);
}
@@ -3439,6 +3489,14 @@ void OpenGLDriver::whenFrameComplete(const std::function<void()>& fn) noexcept {
void OpenGLDriver::whenGpuCommandsComplete(const std::function<void()>& fn) noexcept {
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
// glFenceSync can return 0 in certain situations. For example, we've seen this happen on Web
// when the GL context has been lost.
// Unfortunately, there's not much we can do here. The fn callback will never execute, which
// could cause issues. If we've lost the WebGL context though, Filament is most likely shutting
// down anyway, so in practice this might not be a big problem.
if (!sync) {
return;
}
mGpuCommandCompleteOps.emplace_back(sync, fn);
CHECK_GL_ERROR(utils::slog.e)
}
+11 -1
View File
@@ -121,14 +121,24 @@ OpenGLPlatform::ExternalTexture* OpenGLPlatform::createExternalImageTexture() no
return nullptr;
}
void OpenGLPlatform::destroyExternalImage(
void OpenGLPlatform::destroyExternalImageTexture(
UTILS_UNUSED ExternalTexture* texture) noexcept {
}
void OpenGLPlatform::retainExternalImage(
UTILS_UNUSED ExternalImageHandleRef externalImage) noexcept {
}
void OpenGLPlatform::retainExternalImage(
UTILS_UNUSED void* externalImage) noexcept {
}
bool OpenGLPlatform::setExternalImage(
UTILS_UNUSED ExternalImageHandleRef externalImage,
UTILS_UNUSED ExternalTexture* texture) noexcept {
return false;
}
bool OpenGLPlatform::setExternalImage(
UTILS_UNUSED void* externalImage,
UTILS_UNUSED ExternalTexture* texture) noexcept {
@@ -54,8 +54,15 @@ struct PlatformCocoaGLImpl {
CVOpenGLTextureCacheRef mTextureCache = nullptr;
std::unique_ptr<CocoaExternalImage::SharedGl> mExternalImageSharedGl;
void updateOpenGLContext(NSView *nsView, bool resetView, bool clearView);
struct ExternalImageCocoaGL : public Platform::ExternalImage {
CVPixelBufferRef cvBuffer;
protected:
~ExternalImageCocoaGL() noexcept final;
};
};
PlatformCocoaGLImpl::ExternalImageCocoaGL::~ExternalImageCocoaGL() noexcept = default;
CocoaGLSwapChain::CocoaGLSwapChain( NSView* inView )
: view(inView)
, previousBounds(NSZeroRect)
@@ -309,17 +316,12 @@ OpenGLPlatform::ExternalTexture* PlatformCocoaGL::createExternalImageTexture() n
if (!pImpl->mExternalImageSharedGl) {
pImpl->mExternalImageSharedGl = std::make_unique<CocoaExternalImage::SharedGl>();
}
ExternalTexture* outTexture = new CocoaExternalImage(pImpl->mTextureCache,
*pImpl->mExternalImageSharedGl);
// the actual id/target will be set in setExternalImage.
outTexture->id = 0;
outTexture->target = GL_TEXTURE_2D;
return outTexture;
}
void PlatformCocoaGL::destroyExternalImage(ExternalTexture* texture) noexcept {
void PlatformCocoaGL::destroyExternalImageTexture(ExternalTexture* texture) noexcept {
auto* p = static_cast<CocoaExternalImage*>(texture);
delete p;
}
@@ -344,6 +346,36 @@ bool PlatformCocoaGL::setExternalImage(void* externalImage, ExternalTexture* tex
return true;
}
Platform::ExternalImageHandle PlatformCocoaGL::createExternalImage(void* cvPixelBuffer) noexcept {
auto* p = new(std::nothrow) PlatformCocoaGLImpl::ExternalImageCocoaGL;
p->cvBuffer = (CVPixelBufferRef) cvPixelBuffer;
return ExternalImageHandle{ p };
}
void PlatformCocoaGL::retainExternalImage(ExternalImageHandleRef externalImage) noexcept {
auto const* const cocoaGlExternalImage
= static_cast<PlatformCocoaGLImpl::ExternalImageCocoaGL const*>(externalImage.get());
// Take ownership of the passed in buffer. It will be released the next time
// setExternalImage is called, or when the texture is destroyed.
CVPixelBufferRef pixelBuffer = cocoaGlExternalImage->cvBuffer;
CVPixelBufferRetain(pixelBuffer);
}
bool PlatformCocoaGL::setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept {
auto const* const cocoaGlExternalImage
= static_cast<PlatformCocoaGLImpl::ExternalImageCocoaGL const*>(externalImage.get());
CVPixelBufferRef cvPixelBuffer = cocoaGlExternalImage->cvBuffer;
CocoaExternalImage* cocoaExternalImage = static_cast<CocoaExternalImage*>(texture);
if (!cocoaExternalImage->set(cvPixelBuffer)) {
return false;
}
texture->target = cocoaExternalImage->getTarget();
texture->id = cocoaExternalImage->getGlTexture();
// we used to set the internalFormat, but it's not used anywhere on the gl backend side
// cocoaExternalImage->getInternalFormat();
return true;
}
void PlatformCocoaGLImpl::updateOpenGLContext(NSView *nsView, bool resetView,
bool clearView) {
NSOpenGLContext* glContext = mGLContext;
@@ -47,8 +47,15 @@ struct PlatformCocoaTouchGLImpl {
GLuint mDefaultDepthbuffer = 0;
CVOpenGLESTextureCacheRef mTextureCache = nullptr;
CocoaTouchExternalImage::SharedGl* mExternalImageSharedGl = nullptr;
struct ExternalImageCocoaTouchGL : public Platform::ExternalImage {
CVPixelBufferRef cvBuffer;
protected:
~ExternalImageCocoaTouchGL() noexcept final;
};
};
PlatformCocoaTouchGLImpl::ExternalImageCocoaTouchGL::~ExternalImageCocoaTouchGL() noexcept = default;
PlatformCocoaTouchGL::PlatformCocoaTouchGL()
: pImpl(new PlatformCocoaTouchGLImpl) {
}
@@ -198,13 +205,10 @@ void PlatformCocoaTouchGL::commit(Platform::SwapChain* swapChain) noexcept {
OpenGLPlatform::ExternalTexture* PlatformCocoaTouchGL::createExternalImageTexture() noexcept {
ExternalTexture* outTexture = new CocoaTouchExternalImage(pImpl->mTextureCache,
*pImpl->mExternalImageSharedGl);
// the actual id/target will be set in setExternalImage*(
outTexture->id = 0;
outTexture->target = GL_TEXTURE_2D;
return outTexture;
}
void PlatformCocoaTouchGL::destroyExternalImage(ExternalTexture* texture) noexcept {
void PlatformCocoaTouchGL::destroyExternalImageTexture(ExternalTexture* texture) noexcept {
auto* p = static_cast<CocoaTouchExternalImage*>(texture);
delete p;
}
@@ -229,4 +233,35 @@ bool PlatformCocoaTouchGL::setExternalImage(void* externalImage, ExternalTexture
return true;
}
Platform::ExternalImageHandle PlatformCocoaTouchGL::createExternalImage(void* cvPixelBuffer) noexcept {
auto* p = new(std::nothrow) PlatformCocoaTouchGLImpl::ExternalImageCocoaTouchGL;
p->cvBuffer = (CVPixelBufferRef) cvPixelBuffer;
return ExternalImageHandle{ p };
}
void PlatformCocoaTouchGL::retainExternalImage(ExternalImageHandleRef externalImage) noexcept {
auto const* const cocoaTouchGlExternalImage
= static_cast<PlatformCocoaTouchGLImpl::ExternalImageCocoaTouchGL const*>(externalImage.get());
// Take ownership of the passed in buffer. It will be released the next time
// setExternalImage is called, or when the texture is destroyed.
CVPixelBufferRef pixelBuffer = cocoaTouchGlExternalImage->cvBuffer;
CVPixelBufferRetain(pixelBuffer);
}
bool PlatformCocoaTouchGL::setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept {
auto const* const cocoaTouchGlExternalImage
= static_cast<PlatformCocoaTouchGLImpl::ExternalImageCocoaTouchGL const*>(externalImage.get());
CVPixelBufferRef cvPixelBuffer = cocoaTouchGlExternalImage->cvBuffer;
CocoaTouchExternalImage* cocoaExternalImage = static_cast<CocoaTouchExternalImage*>(texture);
if (!cocoaExternalImage->set(cvPixelBuffer)) {
return false;
}
texture->target = cocoaExternalImage->getTarget();
texture->id = cocoaExternalImage->getGlTexture();
// we used to set the internalFormat, but it's not used anywhere on the gl backend side
// cocoaExternalImage->getInternalFormat();
return true;
}
} // namespace filament::backend
@@ -117,7 +117,9 @@ bool PlatformEGL::isOpenGL() const noexcept {
return false;
}
Driver* PlatformEGL::createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept {
PlatformEGL::ExternalImageEGL::~ExternalImageEGL() = default;
Driver* PlatformEGL::createDriver(void* sharedContext, const DriverConfig& driverConfig) noexcept {
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
assert_invariant(mEGLDisplay != EGL_NO_DISPLAY);
@@ -699,16 +701,10 @@ FenceStatus PlatformEGL::waitFence(
OpenGLPlatform::ExternalTexture* PlatformEGL::createExternalImageTexture() noexcept {
ExternalTexture* outTexture = new(std::nothrow) ExternalTexture{};
glGenTextures(1, &outTexture->id);
if (UTILS_LIKELY(ext.gl.OES_EGL_image_external_essl3)) {
outTexture->target = GL_TEXTURE_EXTERNAL_OES;
} else {
// if texture external is not supported, revert to texture 2d
outTexture->target = GL_TEXTURE_2D;
}
return outTexture;
}
void PlatformEGL::destroyExternalImage(ExternalTexture* texture) noexcept {
void PlatformEGL::destroyExternalImageTexture(ExternalTexture* texture) noexcept {
glDeleteTextures(1, &texture->id);
delete texture;
}
@@ -728,6 +724,18 @@ bool PlatformEGL::setExternalImage(void* externalImage,
return true;
}
Platform::ExternalImageHandle PlatformEGL::createExternalImage(EGLImageKHR eglImage) noexcept {
auto* const p = new(std::nothrow) ExternalImageEGL;
p->eglImage = eglImage;
return ExternalImageHandle{p};
}
bool PlatformEGL::setExternalImage(ExternalImageHandleRef externalImage,
UTILS_UNUSED_IN_RELEASE ExternalTexture* texture) noexcept {
auto const* const eglExternalImage = static_cast<ExternalImageEGL const*>(externalImage.get());
return setExternalImage(eglExternalImage->eglImage, texture);
}
// -----------------------------------------------------------------------------------------------
void PlatformEGL::initializeGlExtensions() noexcept {
@@ -231,6 +231,26 @@ Driver* PlatformEGLAndroid::createDriver(void* sharedContext,
return driver;
}
PlatformEGLAndroid::ExternalImageEGLAndroid::~ExternalImageEGLAndroid() = default;
Platform::ExternalImageHandle PlatformEGLAndroid::createExternalImage(AHardwareBuffer const* buffer, bool sRGB) noexcept {
auto* const p = new(std::nothrow) ExternalImageEGLAndroid;
p->aHardwareBuffer = const_cast<AHardwareBuffer*>(buffer);
p->sRGB = sRGB;
return ExternalImageHandle{ p };
}
bool PlatformEGLAndroid::setExternalImage(ExternalImageHandleRef externalImage,
UTILS_UNUSED_IN_RELEASE ExternalTexture* texture) noexcept {
auto const* const eglExternalImage = static_cast<ExternalImageEGLAndroid const*>(externalImage.get());
if (eglExternalImage->aHardwareBuffer) {
// TODO: implement PlatformEGLAndroid::setExternalImage w/ AHardwareBuffer
return true;
}
// not a AHardwareBuffer, fallback to the inherited version
return PlatformEGL::setExternalImage(externalImage, texture);
}
void PlatformEGLAndroid::setPresentationTime(int64_t presentationTimeInNanosecond) noexcept {
EGLSurface currentDrawSurface = eglGetCurrentSurface(EGL_DRAW);
if (currentDrawSurface != EGL_NO_SURFACE) {
@@ -552,6 +552,15 @@ void VulkanDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwText
texture.inc();
}
void VulkanDriver::createTextureExternalImage2R(Handle<HwTexture> th,
backend::SamplerType target, backend::TextureFormat format,
uint32_t width, uint32_t height, backend::TextureUsage usage,
Platform::ExternalImageHandleRef externalImage) {
FVK_SYSTRACE_SCOPE();
// FIXME: implement createTextureExternalImage2R
}
void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::SamplerType target,
backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
void* externalImage) {
@@ -792,6 +801,10 @@ Handle<HwTexture> VulkanDriver::createTextureViewSwizzleS() noexcept {
return mResourceManager.allocHandle<VulkanTexture>();
}
Handle<HwTexture> VulkanDriver::createTextureExternalImage2S() noexcept {
return mResourceManager.allocHandle<VulkanTexture>();
}
Handle<HwTexture> VulkanDriver::createTextureExternalImageS() noexcept {
return mResourceManager.allocHandle<VulkanTexture>();
}
@@ -1171,6 +1184,9 @@ void VulkanDriver::update3DImage(Handle<HwTexture> th, uint32_t level, uint32_t
scheduleDestroy(std::move(data));
}
void VulkanDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
}
void VulkanDriver::setupExternalImage(void* image) {
}
+47 -22
View File
@@ -23,6 +23,7 @@
#include <backend/DriverEnums.h>
#include <backend/PixelBufferDescriptor.h>
#include <backend/Platform.h>
#include <utils/compiler.h>
@@ -70,7 +71,7 @@ class UTILS_PUBLIC Texture : public FilamentAPI {
struct BuilderDetails;
public:
static constexpr const size_t BASE_LEVEL = 0;
static constexpr size_t BASE_LEVEL = 0;
//! Face offsets for all faces of a cubemap
struct FaceOffsets;
@@ -84,14 +85,16 @@ public:
using CompressedType = backend::CompressedPixelDataType; //!< Compressed pixel data format
using Usage = backend::TextureUsage; //!< Usage affects texel layout
using Swizzle = backend::TextureSwizzle; //!< Texture swizzle
using ExternalImageHandle = backend::Platform::ExternalImageHandle;
using ExternalImageHandleRef = backend::Platform::ExternalImageHandleRef;
/** @return whether a backend supports a particular format. */
/** @return Whether a backend supports a particular format. */
static bool isTextureFormatSupported(Engine& engine, InternalFormat format) noexcept;
/** @return whether this backend supports protected textures. */
/** @return Whether this backend supports protected textures. */
static bool isProtectedTexturesSupported(Engine& engine) noexcept;
/** @return whether a backend supports texture swizzling. */
/** @return Whether a backend supports texture swizzling. */
static bool isTextureSwizzleSupported(Engine& engine) noexcept;
static size_t computeTextureDataSize(Format format, Type type,
@@ -217,6 +220,18 @@ public:
*/
Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept;
/**
* Creates an external texture. The content must be set using setExternalImage().
* The sampler can be SAMPLER_EXTERNAL or SAMPLER_2D depending on the format. Generally
* YUV formats must use SAMPLER_EXTERNAL. This depends on the backend features and is not
* validated.
*
* If the Sampler is set to SAMPLER_EXTERNAL, external() is implied.
*
* @return
*/
Builder& external() noexcept;
/**
* Creates the Texture object and returns a pointer to it.
*
@@ -261,18 +276,6 @@ public:
*/
Builder& import(intptr_t id) noexcept;
/**
* Creates an external texture. The content must be set using setExternalImage().
* The sampler can be SAMPLER_EXTERNAL or SAMPLER_2D depending on the format. Generally
* YUV formats must use SAMPLER_EXTERNAL. This depends on the backend features and is not
* validated.
*
* If the Sampler is set to SAMPLER_EXTERNAL, external() is implied.
*
* @return
*/
Builder& external() noexcept;
private:
friend class FTexture;
};
@@ -359,7 +362,7 @@ public:
* uint32_t width, uint32_t height, uint32_t depth,
* PixelBufferDescriptor&& buffer)
*/
inline void setImage(Engine& engine, size_t level, PixelBufferDescriptor&& buffer) const {
void setImage(Engine& engine, size_t level, PixelBufferDescriptor&& buffer) const {
setImage(engine, level, 0, 0, 0,
uint32_t(getWidth(level)), uint32_t(getHeight(level)), 1, std::move(buffer));
}
@@ -372,7 +375,7 @@ public:
* uint32_t width, uint32_t height, uint32_t depth,
* PixelBufferDescriptor&& buffer)
*/
inline void setImage(Engine& engine, size_t level,
void setImage(Engine& engine, size_t level,
uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
PixelBufferDescriptor&& buffer) const {
setImage(engine, level, xoffset, yoffset, 0, width, height, 1, std::move(buffer));
@@ -406,6 +409,26 @@ public:
PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets) const;
/**
* Specify the external image to associate with this Texture. Typically, the external
* image is OS specific, and can be a video or camera frame.
* There are many restrictions when using an external image as a texture, such as:
* - only the level of detail (lod) 0 can be specified
* - only nearest or linear filtering is supported
* - the size and format of the texture is defined by the external image
* - only the CLAMP_TO_EDGE wrap mode is supported
*
* @param engine Engine this texture is associated to.
* @param image An opaque handle to a platform specific image. It must be created using Platform
* specific APIs. For example PlatformEGL::createExternalImage(EGLImageKHR eglImage)
*
* @see PlatformEGL::createExternalImage
* @see PlatformEGLAndroid::createExternalImage
* @see PlatformCocoaGL::createExternalImage
* @see PlatformCocoaTouchGL::createExternalImage
*/
void setExternalImage(Engine& engine, ExternalImageHandleRef image) noexcept;
/**
* Specify the external image to associate with this Texture. Typically, the external
* image is OS specific, and can be a video or camera frame.
@@ -428,7 +451,9 @@ public:
*
* @see Builder::sampler()
*
* @deprecated Instead, use setExternalImage(Engine& engine, ExternalImageHandleRef image)
*/
UTILS_DEPRECATED
void setExternalImage(Engine& engine, void* UTILS_NONNULL image) noexcept;
/**
@@ -463,7 +488,7 @@ public:
void setExternalImage(Engine& engine, void* UTILS_NONNULL image, size_t plane) noexcept;
/**
* Specify the external stream to associate with this Texture. Typically the external
* Specify the external stream to associate with this Texture. Typically, the external
* stream is OS specific, and can be a video or camera stream.
* There are many restrictions when using an external stream as a texture, such as:
* - only the level of detail (lod) 0 can be specified
@@ -474,7 +499,7 @@ public:
* @param stream A Stream object
*
* @attention \p engine must be the instance passed to Builder::build()
* @attention This Texture instance must use Sampler::SAMPLER_EXTERNAL or it has no effect
* @attention This Texture instance must use Sampler::SAMPLER_EXTERNAL, or it has no effect
*
* @see Builder::sampler(), Stream
*
@@ -522,9 +547,9 @@ public:
* @param buffer Client-side buffer containing the images to set.
* @param faceOffsets Offsets in bytes into \p buffer for all six images. The offsets
* are specified in the following order: +x, -x, +y, -y, +z, -z
* @param options Optional parameter to controlling user-specified quality and options.
* @param options Optional parameter controlling user-specified quality and options.
*
* @exception utils::PreConditionPanic if the source data constraints are not respected.
* @exception utils::PreConditionPanic If the source data constraints are not respected.
*
*/
void generatePrefilterMipmap(Engine& engine,
+4
View File
@@ -58,6 +58,10 @@ void Texture::setImage(Engine& engine, size_t const level,
downcast(this)->setImage(downcast(engine), level, std::move(buffer), faceOffsets);
}
void Texture::setExternalImage(Engine& engine, ExternalImageHandleRef image) noexcept {
downcast(this)->setExternalImage(downcast(engine), image);
}
void Texture::setExternalImage(Engine& engine, void* image) noexcept {
downcast(this)->setExternalImage(downcast(engine), image);
}
+6 -5
View File
@@ -690,11 +690,9 @@ public:
bool use_shadow_atlas = false;
} shadows;
struct {
#ifndef NDEBUG
bool assert_material_instance_in_use = true;
#else
// TODO: default the following two flags to true.
bool assert_material_instance_in_use = false;
#endif
bool assert_destroy_material_before_material_instance = false;
} debug;
} engine;
struct {
@@ -721,7 +719,10 @@ public:
&features.engine.shadows.use_shadow_atlas, false },
{ "features.engine.debug.assert_material_instance_in_use",
"Assert when a MaterialInstance is destroyed while it is in use by RenderableManager.",
&features.engine.debug.assert_material_instance_in_use, false }
&features.engine.debug.assert_material_instance_in_use, false },
{ "features.engine.debug.assert_destroy_material_before_material_instance",
"Assert when a Material is destroyed but its instances are still alive.",
&features.engine.debug.assert_destroy_material_before_material_instance, false },
}};
utils::Slice<const FeatureFlag> getFeatureFlags() const noexcept {
+13 -3
View File
@@ -383,9 +383,14 @@ void FMaterial::terminate(FEngine& engine) {
auto const& materialInstanceResourceList = engine.getMaterialInstanceResourceList();
auto pos = materialInstanceResourceList.find(this);
if (UTILS_LIKELY(pos != materialInstanceResourceList.cend())) {
FILAMENT_CHECK_PRECONDITION(pos->second.empty())
<< "destroying material \"" << this->getName().c_str_safe() << "\" but "
<< pos->second.size() << " instances still alive.";
if (engine.features.engine.debug.assert_destroy_material_before_material_instance) {
FILAMENT_CHECK_PRECONDITION(pos->second.empty())
<< "destroying material \"" << this->getName().c_str_safe() << "\" but "
<< pos->second.size() << " instances still alive.";
} else {
utils::slog.e << "destroying material \"" << this->getName().c_str_safe() << "\" but "
<< pos->second.size() << " instances still alive.";
}
}
@@ -1098,8 +1103,13 @@ void FMaterial::precacheDepthVariants(FEngine const& engine) {
// later, when/if needed by createAndCacheProgram(). Doing it now potentially uses more
// memory and increases init time, but reduces hiccups during the first frame.
if (UTILS_UNLIKELY(mIsDefaultMaterial)) {
const bool stereoSupported = mEngine.getDriverApi().isStereoSupported();
auto const allDepthVariants = VariantUtils::getDepthVariants();
for (auto const variant: allDepthVariants) {
// Don't precache any stereo variants if stereo is not supported.
if (!stereoSupported && Variant::isStereoVariant(variant)) {
continue;
}
assert_invariant(Variant::isValidDepthVariant(variant));
if (hasVariant(variant)) {
prepareProgram(variant);
+5 -2
View File
@@ -1351,8 +1351,11 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
}
if (hasFXAA) {
bool const preserveAlphaChannel = needsAlphaChannel ||
(hasColorGrading && colorGradingConfig.outputLuminance);
bool const preserveAlphaChannel =
// we're transparent -- alpha channel has user data
needsAlphaChannel ||
// the color-grading pass outputted the luminance channel, and we have an upscaling pass
(hasColorGrading && colorGradingConfig.outputLuminance && scaled);
input = ppm.fxaa(fg, input, xvp, colorGradingConfig.ldrFormat, preserveAlphaChannel);
// the padded buffer is resolved now
xvp.left = xvp.bottom = 0;
+20
View File
@@ -469,6 +469,26 @@ void FTexture::setImage(FEngine& engine, size_t const level,
const_cast<FTexture*>(this)->updateLodRange(level);
}
void FTexture::setExternalImage(FEngine& engine, ExternalImageHandleRef image) noexcept {
FILAMENT_CHECK_PRECONDITION(mExternal) << "The texture must be external.";
// The call to setupExternalImage2 is synchronous, and allows the driver to take ownership of the
// external image on this thread, if necessary.
auto& api = engine.getDriverApi();
api.setupExternalImage2(image);
auto texture = api.createTextureExternalImage2(mTarget, mFormat, mWidth, mHeight, mUsage, image);
if (mTextureIsSwizzled) {
auto const& s = mSwizzle;
auto swizzleView = api.createTextureViewSwizzle(texture, s[0], s[1], s[2], s[3]);
api.destroyTexture(texture);
texture = swizzleView;
}
setHandles(texture);
}
void FTexture::setExternalImage(FEngine& engine, void* image) noexcept {
FILAMENT_CHECK_PRECONDITION(mExternal) << "The texture must be external.";
+1
View File
@@ -66,6 +66,7 @@ public:
PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets,
PrefilterOptions const* options);
void setExternalImage(FEngine& engine, ExternalImageHandleRef image) noexcept;
void setExternalImage(FEngine& engine, void* image) noexcept;
void setExternalImage(FEngine& engine, void* image, size_t plane) noexcept;
void setExternalStream(FEngine& engine, FStream* stream) noexcept;
+109
View File
@@ -0,0 +1,109 @@
add_subdirectory(../ "${CMAKE_CURRENT_BINARY_DIR}/abseil")
# To make Abseil easy for clients to link against, we create a dummy target just for installation
# purposes and combine all of Abseil's libraries into a single, easy to link against static library.
add_library(filament-abseil STATIC dummy.c)
set(ABSEIL_DEPS
# This is a full list of static library targets that Abseil exports, generated with the
# following commands:
# cd out/cmake-debug
# ninja -t targets | grep libabsl | sed 's/^lib//; s/\.a: phony$//'
absl_bad_any_cast_impl
absl_bad_optional_access
absl_bad_variant_access
absl_base
absl_city
absl_civil_time
absl_cord
absl_cord_internal
absl_cordz_functions
absl_cordz_handle
absl_cordz_info
absl_cordz_sample_token
absl_crc32c
absl_crc_cord_state
absl_crc_cpu_detect
absl_crc_internal
absl_debugging_internal
absl_decode_rust_punycode
absl_demangle_internal
absl_demangle_rust
absl_die_if_null
absl_examine_stack
absl_exponential_biased
absl_failure_signal_handler
absl_flags_commandlineflag
absl_flags_commandlineflag_internal
absl_flags_config
absl_flags_internal
absl_flags_marshalling
absl_flags_parse
absl_flags_private_handle_accessor
absl_flags_program_name
absl_flags_reflection
absl_flags_usage
absl_flags_usage_internal
absl_graphcycles_internal
absl_hash
absl_hashtablez_sampler
absl_int128
absl_kernel_timeout_internal
absl_leak_check
absl_log_entry
absl_log_flags
absl_log_globals
absl_log_initialize
absl_log_internal_check_op
absl_log_internal_conditions
absl_log_internal_fnmatch
absl_log_internal_format
absl_log_internal_globals
absl_log_internal_log_sink_set
absl_log_internal_message
absl_log_internal_nullguard
absl_log_internal_proto
absl_log_internal_structured_proto
absl_log_severity
absl_log_sink
absl_low_level_hash
absl_malloc_internal
absl_periodic_sampler
absl_poison
absl_random_distributions
absl_random_internal_distribution_test_util
absl_random_internal_platform
absl_random_internal_pool_urbg
absl_random_internal_randen
absl_random_internal_randen_hwaes
absl_random_internal_randen_hwaes_impl
absl_random_internal_randen_slow
absl_random_internal_seed_material
absl_random_seed_gen_exception
absl_random_seed_sequences
absl_raw_hash_set
absl_raw_logging_internal
absl_scoped_set_env
absl_spinlock_wait
absl_stacktrace
absl_status
absl_statusor
absl_str_format_internal
absl_strerror
absl_string_view
absl_strings
absl_strings_internal
absl_symbolize
absl_synchronization
absl_throw_delegate
absl_time
absl_time_zone
absl_tracing_internal
absl_utf8_for_code_point
absl_vlog_config_internal
)
set(ABSEIL_COMBINED_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libabseil_combined.a")
combine_static_libs(filament-abseil "${ABSEIL_COMBINED_OUTPUT}" "${ABSEIL_DEPS}")
set(ABSEIL_LIB_NAME ${CMAKE_STATIC_LIBRARY_PREFIX}abseil${CMAKE_STATIC_LIBRARY_SUFFIX})
install(FILES "${ABSEIL_COMBINED_OUTPUT}" DESTINATION lib/${DIST_DIR} RENAME ${ABSEIL_LIB_NAME})
View File