Compare commits

..

112 Commits

Author SHA1 Message Date
Benjamin Doherty
979d6742e0 Merge branch 'rc/1.31.7' into release 2023-03-09 10:39:41 -08:00
Mathias Agopian
4a7a033d04 Fix timer query breakage on webgl 2023-03-08 12:33:11 -08:00
Ben Doherty
5c2bbcb4a1 Remove compute shader assertion in GLProgram 2023-03-08 10:56:24 -08:00
Benjamin Doherty
dec903a0ee Bump version to 1.31.7 2023-03-01 11:26:50 -08:00
Benjamin Doherty
e9475b322b Merge branch 'rc/1.31.6' into release 2023-03-01 11:24:13 -08:00
Benjamin Doherty
78785a5bca Release Filament 1.31.6 2023-03-01 11:23:37 -08:00
Mathias Agopian
662b4b5ca3 fix typo that could cause a OOB
fortunately this would only happen when using SSBOs (which are not
used currently).
2023-02-27 13:06:25 -08:00
Mathias Agopian
bee96d1cf1 abstract OpenGL's GLSync
This small abstraction is (will be) needed because GLES 2.0 doesn't
have sync object, however synchronization is sometimes available
externally, in particular with EGL.

This PR doesn't provide other implementations.
2023-02-27 12:40:21 -08:00
Mathias Agopian
122ebe1ccb More improvements to how we handle extensions (#6591)
- make sure to initialize all extension booleans, we treat them
  as feature flags.
- be more explicit about #define'ing gl tokens, so we can more easily
  catch errors later.
- don't blindly use extension tokens that might not be available
  (e.g.: GL_TEXTURE_EXTERNAL_OES or GL_TEXTURE_CUBE_MAP_ARRAY). It
  would probably cause a spurious gl error.
2023-02-24 16:52:43 -08:00
Mathias Agopian
e741e165ae remove unused / no longer used code 2023-02-24 16:50:15 -08:00
Mathias Agopian
d38dc24915 Cleanup how we get GL extensions entry-points
- iOS is treated the same way than Android now. The only difference
  is that iOS only provides prototypes and no typedef, whereas 
  Android only provides typedefs and no prototypes.

- Timer queries is core in GL and an extension on all versions of
  GLES. On iOS it's not available at the header level. An additional
  subtlety is that glGetObjectuiv is core in GLES 3.0, so it conflicts
  with the extension.
  So, now we do things correctly:
  - on desktop we use the core methods
  - on ios we ifdef out everything related to timer queries
  - on gles 2.0 and up we use only the extension entry-points
2023-02-24 11:55:22 -08:00
Powei Feng
d12612f091 Add UV-based tangent space algorithms (#6572)
Added mikktspace as a third party lib
2023-02-24 09:32:02 -08:00
Mathias Agopian
e6d73135c1 fix DEPTH_STENCIL case for fbo attachments
We were not testing for that case properly. This case is taken when 
either:
- depth & stencil textures are the same and not null
- or, only depth is specified but both attachments are requested


Also cleanup the dimension checks in debug builds.
2023-02-23 14:47:17 -08:00
Mathias Agopian
816612cf0a Fix readPixels() for "auto-resolved" MS color buffers
glReadPixel doesn't resolve automatically, but it does with the 
auto-resolve extension, which we're always emulating.
2023-02-23 10:56:08 -08:00
Mathias Agopian
7ca8ba272c don't rely on GL PACK/UNPACK convenience
- some of the convenience are not available in ES2
- it's less efficient
- we can save some PBO space when reading back
  a partial framebuffer.

We also avoid using GL_PACK_ROW_LENGTH which technically is not
a convenience, but in our case we are doing an extra copy anyways, so
we can account for the row-length at that point.
2023-02-23 10:55:46 -08:00
Mathias Agopian
d337a6d019 Scene::prepare is now multithreaded 2023-02-22 16:28:40 -08:00
Mathias Agopian
f79c4c6080 Improve directional shadow performance with large scenes
- We now call visitScene only once for the directional shadowmap instead of
1 + cascade_count times.

- Don't use visitScene for spot shadows

it was only used to compute the near/far planes, but instead we can
use the radius of the light. This could degrade the quality of the
spot shadows, but this can be corrected by setting a correct radius.

caveat: currently the near is hardcoded to 0.01 units. this should be
user-settable.

- Improve performance of visitScene calls

instead of transforming 8 points of an AABB and finding the min/max,
we transform the AABB and use its minz and maxz. This works for affine
transforms.

This change also cleans-up AABB and Box transform APIs, which also
are now inline.
2023-02-22 16:28:40 -08:00
Mathias Agopian
2e7fc6229b Improve StructureOfArray
- StructureOfArray: don't initialize trivial ctors

We mimic the behavior of std::vector<> here, where a resize() won't
initialize the array if the type is trivially_default_constructible.
This can reveal existing bugs, where we depended on the initialization
to 0.

- StructureOfArray: add push_back(std::tuple<>)

This basically allows us to push_back() a struct of the SoA.

- Make PerRenderableData trivially constructible

this improves performance when we have tons of objects in the scene
because PerRenderableData is used in arrays.
2023-02-22 16:28:40 -08:00
Mathias Agopian
fc724575fa Make SYSTRACE_CALL work with SYSTRACE_CONTEXT
SYSTRACE_VALUE now requires a SYSTRACE_CONTEXT.
2023-02-22 16:28:40 -08:00
Mathias Agopian
84716610b8 cleanup: make const everything that can be 2023-02-22 16:28:40 -08:00
Benjamin Doherty
d9aead8aac Linux CI: use clang 14 2023-02-21 16:06:48 -08:00
Powei Feng
ce148ebeb1 Update linux clang to version 10 (#6556) 2023-02-21 16:00:07 -08:00
Powei Feng
e1315fbaa7 Update CI Ubuntu version 2023-02-21 15:57:00 -08:00
Benjamin Doherty
1690549392 Bump version to 1.31.6 2023-02-21 13:18:22 -08:00
Benjamin Doherty
c73710e343 Merge branch 'rc/1.31.5' into release 2023-02-21 13:16:47 -08:00
Benjamin Doherty
29983772ed Release Filament 1.31.5 2023-02-21 13:16:09 -08:00
ViktorHeisenberger
d100e628c2 Invoke ccache on Win+ninja. There is no support for ENV vars. (#6582) 2023-02-21 09:19:03 -08:00
Mathias Agopian
94f121f37d Add a camera near/far setting in gltf_viewer 2023-02-17 11:16:42 -08:00
Mathias Agopian
d9266ba61c fix a main camera far plane culling
we need to use the culling projection matrix for culling!
2023-02-16 15:40:32 -08:00
Ben Doherty
8389056d2d gltfio: Fix crash when a MIME type has no texture provider (#6569) 2023-02-16 14:21:26 -08:00
Powei Feng
26b8cb238a Add build.sh flag for ASAN/UBSAN (#6566) 2023-02-16 13:19:32 -08:00
Powei Feng
f8d4690cd8 Update linux-continuous.yml to use ubuntu-22.04 (#6559) 2023-02-14 16:47:02 -08:00
Benjamin Doherty
c2e2f80945 Fix RELEASE_NOTES.md 2023-02-14 14:10:40 -08:00
Powei Feng
e9efcdf191 -Werror for libfilament and backend (#6547) 2023-02-14 01:15:25 -08:00
Mathias Agopian
8ea159520d workaround our -ffast-math
We use isnan() to detect that the estimation of directional light
parameters from the IBL has failed, however isnan() always returns
false with -ffast-math, which we're using in release builds.
This works around that. The affected code is non essential, performance
is not a concern here.
2023-02-13 21:51:43 -08:00
Mathias Agopian
337e18051a The default render channel is now 2 instead of 0
This also fixes some potential issues with refraction when using
render channels.
2023-02-13 17:31:34 -08:00
Ben Doherty
3c4e094990 Rework how release notes work (#6557) 2023-02-13 14:54:07 -08:00
Powei Feng
71e6f3d037 Update linux clang to version 10 (#6556) 2023-02-13 14:49:45 -08:00
Benjamin Doherty
092a0489da Bump version to 1.31.5 2023-02-13 11:53:24 -08:00
Benjamin Doherty
1c6279366f Merge branch 'rc/1.31.4' into release 2023-02-13 11:51:37 -08:00
Benjamin Doherty
d2690bf75a Release Filament 1.31.4 2023-02-13 11:51:06 -08:00
Ben Doherty
44f002a5a1 gltfio: Fix race condition affecting mobile and web (#6548)
When loading a glTF file on platforms without a filesystem, a client
calls `addResourceData` to populate `ResourceLoader`'s cache with data.
For example, a web client might make HTTP fetch requests to fill in
buffer data. This internal cache of data is stored in
`ResourceLoader::Impl::mUriDataCache`.

This works well, except the cache must persist until after it has been
uploaded to the GPU.

There was already a mechanism (see `uploadUserdata`) in place to ensure
that glTF data persisted until after it had been uploaded to the GPU.
However, this mechanism did not extend to client-provided data. Thus, a
race occured between Filament's driver consuming the buffer and it
getting freed.
2023-02-13 10:44:22 -08:00
Powei Feng
f8442c9ec0 vulkan: Remove unused presentQueueFamilyIndex (#6545) 2023-02-10 12:41:00 -08:00
Powei Feng
b3513c7d1f geometry: Add TangentSpaceMesh implementations (#6530)
geometry: Add TangentSpaceMesh implementations

Added:
 - Hughes-Moller
 - Frisvad's method
 - Flat shading
2023-02-10 09:34:49 -08:00
Mathias Agopian
a82e813333 fix libmath streaming operators 2023-02-09 16:11:30 -08:00
Powei Feng
dd246aeee4 vulkan: Assert that graphics-QF is present-QF (#6540) 2023-02-09 13:31:29 -08:00
Ben Doherty
1653d3615b Fix Metal crash due to empty program names (#6537) 2023-02-09 12:11:04 -08:00
Mathias Agopian
4847b00f9e improve SoA a bit
Instead of storing the arrays into an array of void*, we use a 
tuple<> instead. This improves debugging because now the tuple<>
has pointer with the correct types.

It also improves most of the code except `push_back` which now
relies on a hack -- this is the only place where I'm not able to 
resolve the array strictly at compile time, even if in practice it is.
2023-02-08 16:22:00 -08:00
Igor Korobka
d613145c1a Fix JNI after minification is applied
UbershaderProvider.getNativeObject() is accessed from AssetLoader.cpp,
so it must be annotated with @UsedByNative("AssetLoader.cpp") to
avoid runtime crashes when minification is applied.

Fixes #5944
2023-02-08 15:29:55 -08:00
ritik619
a788f66e18 Fixed typographic error 2023-02-08 12:01:50 -08:00
Romain Guy
9ca3a7456c Fix JNI 2023-02-08 09:07:59 -08:00
Mathias Agopian
5cec001058 matdbg: direct SPIRV edit now supported 2023-02-03 13:57:44 -08:00
Mathias Agopian
2fb42f5144 matdbg: refresh spirv properly
we now refresh the spirv code properly after it's rebuilt from the
glsl tab.
2023-02-02 11:10:21 -08:00
Mathias Agopian
02c22a668c matdbg: make sure we use the same spirv parameters everywhere 2023-02-02 11:10:02 -08:00
Mathias Agopian
a7bf90f5be build.sh -d is now split in two options
`-d` now enables matdbg and adds debugging data, but doesn't affect 
 material optimization

`-g` disables material optimizations


A similar change is done with gradle options. The new proprety
`com.google.android.filament.matnopt` is used to disable material
optimizations.

These options mimic `matc` options.
2023-02-01 23:59:00 -08:00
Mathias Agopian
f71e90fae0 deduplicate spirv disassembly code 2023-02-01 21:12:53 -08:00
Mathias Agopian
8afb11128d move UibGenerator and SibGenerator to the shader folder
The shader folder is where we generate the glsl, so this is more
appropriate.
2023-02-01 21:12:53 -08:00
Mathias Agopian
2e0c238cc6 We now require Vulkan 1.1 for the vulkan backend 2023-02-01 21:10:26 -08:00
Benjamin Doherty
2ac85049a9 Bump version to 1.31.4 2023-02-01 11:55:09 -08:00
Benjamin Doherty
ea428a27d1 Merge branch 'rc/1.31.3' into release 2023-02-01 11:54:04 -08:00
Benjamin Doherty
03b89b4327 Release Filament 1.31.3 2023-02-01 11:53:41 -08:00
Mathias Agopian
a878d1f39c improve sample_full_pbr
- -m option now works with "directory_*.png" or just "*.png"
- "color" replaced by "albedo" to mach other places in the source tree
- fixed warnings
- clear the background when IBL is not used
2023-02-01 10:04:02 -08:00
Mathias Agopian
4a09e13e9d fix a couple typos and consts.
make it easier to activate matdbg on android builds, by adding, but
commenting out the appropriate property.
2023-02-01 10:03:20 -08:00
Mathias Agopian
0b4d32bf98 matdbg: use GLSL 4.5 on desktop when debugging spirv
GLSL 4.5 is closer to spriv than 4.1 and since this is just to 
"interpret" the spirv, 4.5 is fine.

Set the default precision for GLES though.
2023-02-01 10:03:20 -08:00
Mathias Agopian
b940fc9c48 update remote ui 2023-01-31 20:55:23 -08:00
Koncz Levente
2eb0dd7153 Sample Full PBR fixes (#6490)
* Calculate view vector without using camera eye position

* Fix compilation error (during parsing the material when a height map is passed in)

* Add SUN light to the scene
2023-01-31 12:28:25 -08:00
Mathias Agopian
101c7db9a2 update remote ui 2023-01-31 09:52:37 -08:00
Mathias Agopian
032ace2051 Add output color space to ColorGrading settings 2023-01-31 09:46:22 -08:00
Mathias Agopian
5754b9907d Add support for sRGB swapchains
This change adds a 'SRGB' config flag when creating a SwapChain that
enables linear to sRGB conversion on write.

When using this flag, the linear->srgb conversion in the color grading
post processing should be disabled (or, the whole post-processing
stage should be disabled).

There is also a new query to determine if this flag is supported by
the underlaying platform.

On Metal, this happens automatically when the underlaying layer is sRGB.

This reverts commit 3799e219fc.
2023-01-31 09:29:02 -08:00
Mathias Agopian
ffb8203ae7 Fix typo in ColorSpace operator= 2023-01-30 21:35:51 -08:00
Powei Feng
906da033dd vulkan: Add fallback extent for swap chain sizing (#6495)
vulkan: Add fallback extent for swap chain sizing
2023-01-30 19:29:10 -08:00
daemyung danny jang
1077405bc1 Support Windows32 on bluegl as C backend (#6499) 2023-01-30 15:56:15 -08:00
daemyung danny jang
e37df8fc89 Include a header in alphabetical order (#6507) 2023-01-30 14:58:56 -08:00
Mathias Agopian
3799e219fc Revert "Add support for sRGB swapchains"
This reverts commit eab14da30e.

This broke macOS desktop (and maybe other GL platforms).
2023-01-30 11:20:18 -08:00
Mathias Agopian
eab14da30e Add support for sRGB swapchains
This change adds a 'SRGB' config flag when creating a SwapChain that
enables linear to sRGB conversion on write.

When using this flag, the linear->srgb conversion in the color grading
post processing should be disabled (or, the whole post-processing
stage should be disabled).

There is also a new query to determine if this flag is supported by
the underlaying platform.


On Metal, this happens automatically when the underlaying layer is sRGB.
2023-01-30 10:49:38 -08:00
Mathias Agopian
84e999fe57 cleanup PlatformEGL config selection code
We now structure the code to assume we have EGL_KHR_no_config_context,
which is the common case. This allows use to decouple context creation
from swapchain creation.

We still handle the case where the extension is not present by always
selecting a transparent config.
2023-01-30 10:49:38 -08:00
Mathias Agopian
f22ff6a340 the createSwapChain flag shouldn't be a reference 2023-01-30 10:49:38 -08:00
daemyung danny jang
d9d0b93306 Fix a build error (#6502) 2023-01-30 10:38:36 -08:00
Powei Feng
09248cd451 Destroy FilamentInstance's mRoot in EntityManager (#6500) 2023-01-27 16:05:42 -08:00
Koncz Levente
73880428dc Ortho shading fixes (#6453) 2023-01-27 09:36:56 -08:00
Ben Doherty
2a049d1324 Initialize object_uniforms in depth shader (#6492) 2023-01-26 16:23:14 -08:00
Powei Feng
51cbd74235 Add missing STL includes (#6496) 2023-01-26 16:07:58 -08:00
Powei Feng
45246b6109 geometry: Add TangentSpaceMesh class outline (#6476)
- Defined class with documentation in comments
 - Implemented algorithm selection
 - No actual algorithms written yet

Part of google/filament#6358
2023-01-26 14:39:48 -08:00
Ben Doherty
d3956adca8 matdbg: take desktop/mobile into account for SPIR-V to GLSL translation (#6488) 2023-01-26 11:30:51 -08:00
Benjamin Doherty
3bef718238 Bump version to 1.31.3 2023-01-24 14:28:21 -08:00
Benjamin Doherty
e9daaa0503 Merge branch 'rc/1.31.2' into release 2023-01-24 14:27:02 -08:00
Benjamin Doherty
298e54c32a Release Filament 1.31.2 2023-01-24 14:26:22 -08:00
Ben Doherty
4c82f0259d Add systrace support on Apple platforms (#6480) 2023-01-23 14:11:47 -08:00
Mathias Agopian
d0c043c7ff implement draw command channels
There can be up to 4 channels drawing commands can be associated to. 
Channels work like "priorities" except it's the strongest command ordering 
key, in particular it takes precedence over the object's blending mode.
2023-01-23 13:47:41 -08:00
Powei Feng
20cbecfd7c vulkan: put getEnabledLayers behind VK_ENABLE_VALIDATION (#6474) 2023-01-18 18:38:53 -08:00
Powei Feng
194defdb1b vulkan: Fix readPixels memory leak (#6473) 2023-01-18 16:35:58 -08:00
Benjamin Doherty
6d3ea21993 Bump version to 1.31.2 2023-01-18 14:25:45 -08:00
Benjamin Doherty
5017cbe67e Release Filament 1.31.1 2023-01-18 14:23:21 -08:00
Ben Doherty
4c4201cb72 Update check-headers script to ignore platform headers (#6472) 2023-01-18 13:53:45 -08:00
Powei Feng
3ee635f8e4 Fix enabledLayers (#6467)
instanceCreateInfo should not take stack-allocated data
2023-01-18 13:50:10 -08:00
Ben Doherty
4c2dabffd6 Vulkan: fix stack-use-after-scope ASAN error in VulkanContext.cpp (#6463) 2023-01-18 12:00:08 -08:00
Mathias Agopian
185c83dae2 Fix a crash on Vulkan with some Adreno drivers
We were using a specialization constant to size an array inside an
UBO interface block, which caused the crash in the Vulkan driver.

However, this specialization constant was only used to workaround a
Chrome bug on WebGL. Additionally, specialized array size inside blocks
are not fully supported in spirv.

This workaround simply replaces the specialization constant by a 
constant on Vulkan.

Fix #6444
2023-01-18 10:36:43 -08:00
Mathias Agopian
15d124b225 disable KHR_debug messages
there were never useful and in fact harmful, because confusing to our
users.
2023-01-18 10:35:48 -08:00
Mathias Agopian
9c474c5b08 remove too verbose log when auto-instancing 2023-01-18 10:35:31 -08:00
Mathias Agopian
f92f283e00 Fix a typo with auto instancing
fixes b/265831206
2023-01-17 16:42:26 -08:00
Mathias Agopian
f6b94614e8 Make all OpenGLPlatform related interfaces public
- Remove DefaultPlatform from public headers
DefaultPlatform is now PlatormFactory and is just an implementation
detail.

- VulkanPlatform is now public
- Improvements to the OpenGLPlatform interface
- Cleanup PlatformEGL and PlatformEGLAndroid

Also:

- reworked how external image worked so that all the implementation
  is contained in the Platform and no dependency to the backend is
  needed.

- MetalPlatform is now entirely private and final

This is because MetalPlatform wasn't an interface. We probably need one
so it could be customized in the future. But as it stands now it's
better to be private.
2023-01-17 16:39:44 -08:00
Ben Doherty
978517b057 Update actions/checkout version (#6454) 2023-01-17 09:59:19 -08:00
Levente Koncz
d911640809 Attempt to fix skybox shader in ORTHO view 2023-01-13 16:29:08 -08:00
Mathias Agopian
473e610430 reenable compute in the GL backend
We do some shenanigans so it works with API < 21 on android.
2023-01-13 16:00:56 -08:00
Mathias Agopian
3b9b725406 fix dynamic lighting with custom projections
Forxelization made many assumptions about the shape of the projection
matrix, the gist of these fixes is to remove those assumptions.

Fix #6390
2023-01-13 11:36:44 -08:00
Mathias Agopian
fa742bc6bf fix typos 2023-01-13 11:36:44 -08:00
Romain Guy
6a02dd0993 Update to Android Studio Electric Eel and AGP 7.4.0 (#6456) 2023-01-13 08:21:03 -08:00
Powei Feng
243d10f864 [vulkan] enumerate: Returning size = 0 is ok (#6450) 2023-01-12 12:56:34 -08:00
Romain Guy
bbe46071f3 Update Android dependencies (#6452) 2023-01-12 10:02:18 -08:00
Ben Doherty
8ded184ea3 Metal: add labels to aid debugging (#6451) 2023-01-12 09:55:43 -08:00
Romain Guy
ce407ba844 Fix typo 2023-01-11 08:48:04 -08:00
Powei Feng
ddb6a7fa93 Update Linux build instructions (#6438) 2023-01-10 16:42:44 -08:00
226 changed files with 120575 additions and 99776 deletions

View File

@@ -13,7 +13,7 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
- name: Run build script
run: |
cd build/android && printf "y" | ./build.sh continuous

View File

@@ -13,7 +13,7 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
- name: Run build script
run: |
cd build/ios && printf "y" | ./build.sh continuous

View File

@@ -10,10 +10,10 @@ on:
jobs:
build-linux:
name: build-linux
runs-on: ubuntu-18.04
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
- name: Run build script
run: |
cd build/linux && printf "y" | ./build.sh continuous

View File

@@ -13,7 +13,7 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
- name: Run build script
run: |
cd build/mac && printf "y" | ./build.sh continuous

View File

@@ -15,10 +15,10 @@ jobs:
strategy:
matrix:
os: [macos-latest, ubuntu-18.04]
os: [macos-latest, ubuntu-22.04]
steps:
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
- name: Run build script
run: |
WORKFLOW_OS=`echo \`uname\` | sed "s/Darwin/mac/" | tr [:upper:] [:lower:]`
@@ -32,7 +32,7 @@ jobs:
runs-on: windows-2019
steps:
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
- name: Run build script
run: |
build\windows\build-github.bat presubmit
@@ -43,7 +43,7 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
- name: Run build script
run: |
cd build/android && printf "y" | ./build.sh presubmit
@@ -53,7 +53,7 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
- name: Run build script
run: |
cd build/ios && printf "y" | ./build.sh presubmit
@@ -66,7 +66,7 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
- name: Run build script
run: |
cd build/web && printf "y" | ./build.sh presubmit

View File

@@ -31,7 +31,7 @@ jobs:
strategy:
matrix:
os: [macos-latest, ubuntu-18.04]
os: [macos-latest, ubuntu-22.04]
steps:
- name: Decide Git ref
@@ -41,7 +41,7 @@ jobs:
TAG=${REF##*/}
echo "ref=${REF}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
@@ -76,7 +76,7 @@ jobs:
TAG=${REF##*/}
echo "ref=${REF}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
@@ -109,7 +109,7 @@ jobs:
TAG=${REF##*/}
echo "ref=${REF}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
@@ -160,7 +160,7 @@ jobs:
TAG=${REF##*/}
echo "ref=${REF}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
@@ -194,7 +194,7 @@ jobs:
echo "ref=${REF}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
shell: bash
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script

View File

@@ -24,3 +24,4 @@ jobs:
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
pull-request-number: ${{ github.event.pull_request.number }}
release-notes-file: 'NEW_RELEASE_NOTES.md'

View File

@@ -13,7 +13,7 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
- name: Run build script
run: |
cd build/web && printf "y" | ./build.sh continuous

View File

@@ -13,7 +13,7 @@ jobs:
runs-on: windows-2019
steps:
- uses: actions/checkout@v2.0.0
- uses: actions/checkout@v3.3.0
- name: Run build script
run: |
build\windows\build-github.bat continuous

View File

@@ -92,6 +92,8 @@ Make sure you've installed the following dependencies:
- `libc++abi-7-dev` (`libcxxabi-static` on Fedora) or higher
- `ninja-build`
- `libxi-dev`
- `libxcomposite-dev` (`libXcomposite-devel` on Fedora)
- `libxxf86vm-dev` (`libXxf86vm-devel` on Fedora)
After dependencies have been installed, we highly recommend using the [easy build](#easy-build)
script.

View File

@@ -31,6 +31,8 @@ option(FILAMENT_SKIP_SDL2 "Skip dependencies of SDL2, and SDL2" OFF)
option(FILAMENT_LINUX_IS_MOBILE "Treat Linux as Mobile" OFF)
option(FILAMENT_ENABLE_ASAN_UBSAN "Enable Address and Undefined Behavior Sanitizers" OFF)
set(FILAMENT_NDK_VERSION "" CACHE STRING
"Android NDK version or version prefix to be used when building for Android."
)
@@ -67,25 +69,30 @@ endif()
# ==================================================================================================
find_program(CCACHE_PROGRAM ccache)
if (CCACHE_PROGRAM)
set(C_LAUNCHER "${CCACHE_PROGRAM}")
set(CXX_LAUNCHER "${CCACHE_PROGRAM}")
configure_file(build/launch-c.in launch-c)
configure_file(build/launch-cxx.in launch-cxx)
execute_process(COMMAND chmod a+rx
"${CMAKE_CURRENT_BINARY_DIR}/launch-c"
"${CMAKE_CURRENT_BINARY_DIR}/launch-cxx"
)
if (CMAKE_GENERATOR STREQUAL "Xcode")
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_CURRENT_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_CURRENT_BINARY_DIR}/launch-cxx")
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_CURRENT_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_CURRENT_BINARY_DIR}/launch-cxx")
if (WIN32)
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
else()
set(CMAKE_C_COMPILER_LAUNCHER "${CMAKE_CURRENT_BINARY_DIR}/launch-c")
set(CMAKE_CXX_COMPILER_LAUNCHER "${CMAKE_CURRENT_BINARY_DIR}/launch-cxx")
set(C_LAUNCHER "${CCACHE_PROGRAM}")
set(CXX_LAUNCHER "${CCACHE_PROGRAM}")
configure_file(build/launch-c.in launch-c)
configure_file(build/launch-cxx.in launch-cxx)
execute_process(COMMAND chmod a+rx
"${CMAKE_CURRENT_BINARY_DIR}/launch-c"
"${CMAKE_CURRENT_BINARY_DIR}/launch-cxx"
)
if (CMAKE_GENERATOR STREQUAL "Xcode")
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_CURRENT_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_CURRENT_BINARY_DIR}/launch-cxx")
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_CURRENT_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_CURRENT_BINARY_DIR}/launch-cxx")
else()
set(CMAKE_C_COMPILER_LAUNCHER "${CMAKE_CURRENT_BINARY_DIR}/launch-c")
set(CMAKE_CXX_COMPILER_LAUNCHER "${CMAKE_CURRENT_BINARY_DIR}/launch-cxx")
endif()
endif()
endif()
@@ -374,10 +381,10 @@ endif()
# ==================================================================================================
# Debug compiler flags
# ==================================================================================================
# ASAN is deactivated for now because:
# -fsanitize=undefined causes extremely long link times
# -fsanitize=address causes a crash with assimp, which we can't explain for now
#set(EXTRA_SANITIZE_OPTIONS "-fsanitize=undefined -fsanitize=address")
if (FILAMENT_ENABLE_ASAN_UBSAN)
set(EXTRA_SANITIZE_OPTIONS "-fsanitize=address -fsanitize=undefined")
endif()
if (NOT MSVC AND NOT WEBGL)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fstack-protector")
endif()
@@ -497,9 +504,14 @@ if (FILAMENT_SUPPORTS_METAL)
set(MATC_API_FLAGS ${MATC_API_FLAGS} -a metal)
endif()
# Disable optimizations and enable debug info (preserves names in SPIR-V)
# Enable debug info (preserves names in SPIR-V)
if (FILAMENT_ENABLE_MATDBG)
set(MATC_OPT_FLAGS ${MATC_OPT_FLAGS} -d)
endif()
# Disable optimizations
if (FILAMENT_DISABLE_MATOPT)
set(MATC_OPT_FLAGS -gd)
set(MATC_OPT_FLAGS ${MATC_OPT_FLAGS} -g)
endif()
set(MATC_BASE_FLAGS ${MATC_API_FLAGS} -p ${MATC_TARGET} ${MATC_OPT_FLAGS})
@@ -675,6 +687,7 @@ add_subdirectory(${EXTERNAL}/robin-map/tnt)
add_subdirectory(${EXTERNAL}/smol-v/tnt)
add_subdirectory(${EXTERNAL}/benchmark/tnt)
add_subdirectory(${EXTERNAL}/meshoptimizer/tnt)
add_subdirectory(${EXTERNAL}/mikktspace)
add_subdirectory(${EXTERNAL}/cgltf/tnt)
add_subdirectory(${EXTERNAL}/draco/tnt)
add_subdirectory(${EXTERNAL}/jsmn/tnt)

10
NEW_RELEASE_NOTES.md Normal file
View File

@@ -0,0 +1,10 @@
# Filament Release Notes log
**If you are merging a PR into main**: please add the release note below, under the *Release notes
for next branch cut* header.
**If you are cherry-picking a commit into an rc/ branch**: add the release note under the
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
## Release notes for next branch cut

View File

@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.31.1'
implementation 'com.google.android.filament:filament-android:1.31.7'
}
```
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
iOS projects can use CocoaPods to install the latest release:
```
pod 'Filament', '~> 1.31.1'
pod 'Filament', '~> 1.31.7'
```
### Snapshots

View File

@@ -3,7 +3,33 @@
This file contains one line summaries of commits that are worthy of mentioning in release notes.
A new header is inserted each time a *tag* is created.
## main branch
**Do not edit this file unless you are performing a release or cherry-picking into an rc/ branch.**
Instead, if you are authoring a PR for the main branch, add your release note to
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
## v1.31.7
## v1.31.6
- engine: the default render channel is now 2 instead of 0
- gltfio: Fix crash when a MIME type has no texture provider
## v1.31.5
- gltfio: fix potential early freeing of data provided with `ResourceLoader::addResourceData`.
## v1.31.4
- engine: fix broken picking [⚠️ **Recompile Materials to get the fix**]
- engine: added support for sRGB swapchains. See `SwapChain.h`
- bluegl: support Windows32
## v1.31.3
- vulkan: fix memory leak in readPixels
- engine: added support for draw-commands channels (stronger ordering of commands/renderables)
## v1.31.2
## v1.31.1

View File

@@ -12,7 +12,10 @@
// When set, support for Vulkan will be excluded.
//
// com.google.android.filament.matdbg
// When set, enables matdbg, disables shader optimizations
// When set, enables matdbg
//
// com.google.android.filament.matnopt
// When set, disable shader optimizations.
//
// com.google.android.filament.skip-samples
// Exclude samples from the project. Useful to speed up compilation.
@@ -62,6 +65,10 @@ buildscript {
.gradleProperty("com.google.android.filament.matdbg")
.isPresent()
def matnopt = providers
.gradleProperty("com.google.android.filament.matnopt")
.isPresent()
def abis = ["arm64-v8a", "armeabi-v7a", "x86_64", "x86"]
def newAbis = providers
.gradleProperty("com.google.android.filament.abis")
@@ -75,9 +82,9 @@ buildscript {
'minSdk': 19,
'targetSdk': 33,
'compileSdk': 33,
'kotlin': '1.7.10',
'kotlin_coroutines': '1.6.1',
'buildTools': '33.0.0',
'kotlin': '1.8.0',
'kotlin_coroutines': '1.6.4',
'buildTools': '33.0.1',
'ndk': '25.1.8937393',
'androidx_core': '1.9.0',
'androidx_annotations': '1.3.0'
@@ -96,8 +103,7 @@ buildscript {
]
dependencies {
// NOTE: See TODO in gradle.properties once we move to Gradle 7.4
classpath 'com.android.tools.build:gradle:7.3.0'
classpath 'com.android.tools.build:gradle:7.4.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
}
@@ -109,7 +115,7 @@ buildscript {
"-DFILAMENT_DIST_DIR=${filamentPath}".toString(),
"-DFILAMENT_SUPPORTS_VULKAN=${excludeVulkan ? 'OFF' : 'ON'}".toString(),
"-DFILAMENT_ENABLE_MATDBG=${matdbg ? 'ON' : 'OFF'}".toString(),
"-DFILAMENT_DISABLE_MATOPT=${matdbg ? 'ON' : 'OFF'}".toString()
"-DFILAMENT_DISABLE_MATOPT=${matnopt ? 'ON' : 'OFF'}".toString()
]
ext.cppFlags = [

View File

@@ -150,6 +150,13 @@ Java_com_google_android_filament_RenderableManager_nBuilderPriority(JNIEnv*, jcl
builder->priority((uint8_t) priority);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderChannel(JNIEnv*, jclass,
jlong nativeBuilder, jint channel) {
RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
builder->channel((uint8_t) channel);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderCulling(JNIEnv*, jclass,
jlong nativeBuilder, jboolean enabled) {
@@ -339,6 +346,13 @@ Java_com_google_android_filament_RenderableManager_nSetPriority(JNIEnv*, jclass,
rm->setPriority((RenderableManager::Instance) i, (uint8_t) priority);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetChannel(JNIEnv*, jclass,
jlong nativeRenderableManager, jint i, jint channel) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
rm->setChannel((RenderableManager::Instance) i, (uint8_t) channel);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetCulling(JNIEnv*, jclass,
jlong nativeRenderableManager, jint i, jboolean enabled) {

View File

@@ -16,6 +16,7 @@
#include <jni.h>
#include <filament/Engine.h>
#include <filament/SwapChain.h>
#include "common/CallbackUtils.h"
@@ -32,3 +33,9 @@ Java_com_google_android_filament_SwapChain_nSetFrameCompletedCallback(JNIEnv* en
JniCallback::postToJavaAndDestroy(callback);
}, callback);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_SwapChain_nIsSRGBSwapChainSupported(JNIEnv *, jclass, jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
return (bool)SwapChain::isSRGBSwapChainSupported(*engine);
}

View File

@@ -257,23 +257,79 @@ public class RenderableManager {
* Provides coarse-grained control over draw order.
*
* <p>In general Filament reserves the right to re-order renderables to allow for efficient
* rendering. However clients can control ordering at a coarse level using <em>priority</em>.</p>
* rendering. However clients can control ordering at a coarse level using \em priority.
* The priority is applied separately for opaque and translucent objects, that is, opaque
* objects are always drawn before translucent objects regardless of the priority.</p>
*
* <p>For example, this could be used to draw a semitransparent HUD, if a client wishes to
* avoid using a separate View for the HUD. Note that priority is completely orthogonal to
* {@link Builder#layerMask}, which merely controls visibility.</p>
* <p>The Skybox always using the lowest priority, so it's drawn last, which may improve
* performance.</p>
*
* <p>The priority is clamped to the range [0..7], defaults to 4; 7 is lowest priority
* (rendered last).</p>
*
* @see Builder#blendOrder
*/
/**
* Provides coarse-grained control over draw order.
*
* <p>In general Filament reserves the right to re-order renderables to allow for efficient
* rendering. However clients can control ordering at a coarse level using priority.
* The priority is applied separately for opaque and translucent objects, that is, opaque
* objects are always drawn before translucent objects regardless of the priority.</p>
*
* <p>For example, this could be used to draw a semitransparent HUD, if a client wishes to
* avoid using a separate View for the HUD. Note that priority is completely orthogonal to
* {@link Builder#layerMask}, which merely controls visibility.</p>
* <p>The Skybox always using the lowest priority, so it's drawn last, which may improve
* performance.</p>
*
* @param priority clamped to the range [0..7], defaults to 4; 7 is lowest priority
* (rendered last).
*
* @return Builder reference for chaining calls.
*
* @see Builder#channel
* @see Builder#blendOrder
* @see #setPriority
* @see #setBlendOrderAt
*/
@NonNull
public Builder priority(@IntRange(from = 0, to = 7) int priority) {
nBuilderPriority(mNativeBuilder, priority);
return this;
}
/**
* Set the channel this renderable is associated to. There can be 4 channels.
*
* <p>All renderables in a given channel are rendered together, regardless of anything else.
* They are sorted as usual within a channel.</p>
* <p>Channels work similarly to priorities, except that they enforce the strongest
* ordering.</p>
*
* <p>Channels 0 and 1 may not have render primitives using a material with `refractionType`
* set to `screenspace`.</p>
*
* @param channel clamped to the range [0..3], defaults to 2.
*
* @return Builder reference for chaining calls.
*
* @see Builder::blendOrder()
* @see Builder::priority()
* @see RenderableManager::setBlendOrderAt()
*/
@NonNull
public Builder channel(@IntRange(from = 0, to = 3) int channel) {
nBuilderChannel(mNativeBuilder, channel);
return this;
}
/**
* Controls frustum culling, true by default.
*
@@ -655,6 +711,15 @@ public class RenderableManager {
nSetPriority(mNativeObject, i, priority);
}
/**
* Changes the channel of a renderable
*
* @see Builder#channel
*/
public void setChannel(@EntityInstance int i, @IntRange(from = 0, to = 3) int channel) {
nSetChannel(mNativeObject, i, channel);
}
/**
* Changes whether or not frustum culling is on.
*
@@ -876,6 +941,7 @@ public class RenderableManager {
private static native void nBuilderBoundingBox(long nativeBuilder, float cx, float cy, float cz, float ex, float ey, float ez);
private static native void nBuilderLayerMask(long nativeBuilder, int select, int value);
private static native void nBuilderPriority(long nativeBuilder, int priority);
private static native void nBuilderChannel(long nativeBuilder, int channel);
private static native void nBuilderCulling(long nativeBuilder, boolean enabled);
private static native void nBuilderCastShadows(long nativeBuilder, boolean enabled);
private static native void nBuilderReceiveShadows(long nativeBuilder, boolean enabled);
@@ -898,6 +964,7 @@ public class RenderableManager {
private static native void nSetAxisAlignedBoundingBox(long nativeRenderableManager, int i, float cx, float cy, float cz, float ex, float ey, float ez);
private static native void nSetLayerMask(long nativeRenderableManager, int i, int select, int value);
private static native void nSetPriority(long nativeRenderableManager, int i, int priority);
private static native void nSetChannel(long nativeRenderableManager, int i, int channel);
private static native void nSetCulling(long nativeRenderableManager, int i, boolean enabled);
private static native void nSetLightChannel(long nativeRenderableManager, int i, int channel, boolean enable);
private static native boolean nGetLightChannel(long nativeRenderableManager, int i, int channel);

View File

@@ -91,11 +91,34 @@ public class SwapChain {
*/
public static final long CONFIG_ENABLE_XCB = 0x4;
/**
* Indicates that the SwapChain must automatically perform linear to sRGB encoding.
*
* This flag is ignored if isSRGBSwapChainSupported() is false.
*
* When using this flag, post-processing should be disabled.
*
* @see SwapChain#isSRGBSwapChainSupported
* @see View#setPostProcessingEnabled
*/
public static final long CONFIG_SRGB_COLORSPACE = 0x10;
SwapChain(long nativeSwapChain, Object surface) {
mNativeObject = nativeSwapChain;
mSurface = surface;
}
/**
* Return whether createSwapChain supports the SWAP_CHAIN_CONFIG_SRGB_COLORSPACE flag.
* The default implementation returns false.
*
* @param engine A reference to the filament Engine
* @return true if SWAP_CHAIN_CONFIG_SRGB_COLORSPACE is supported, false otherwise.
*/
public static boolean isSRGBSwapChainSupported(@NonNull Engine engine) {
return nIsSRGBSwapChainSupported(engine.getNativeObject());
}
/**
* @return the native <code>Object</code> this <code>SwapChain</code> was created from or null
* for a headless SwapChain.
@@ -141,4 +164,5 @@ public class SwapChain {
}
private static native void nSetFrameCompletedCallback(long nativeSwapChain, Object handler, Runnable callback);
private static native boolean nIsSRGBSwapChainSupported(long nativeEngine);
}

View File

@@ -276,7 +276,7 @@ public class TextureSampler {
}
/**
* Sets the wrapping mode in the t (depth) direction.
* Sets the wrapping mode in the r (depth) direction.
* @param mode wrapping mode
*/
public void setWrapModeR(WrapMode mode) {

View File

@@ -166,6 +166,8 @@ Java_com_google_android_filament_utils_AutomationEngine_nGetViewerOptions(JNIEnv
const jfieldID cameraAperture = env->GetFieldID(klass, "cameraAperture", "F");
const jfieldID cameraSpeed = env->GetFieldID(klass, "cameraSpeed", "F");
const jfieldID cameraISO = env->GetFieldID(klass, "cameraISO", "F");
const jfieldID cameraNear = env->GetFieldID(klass, "cameraNear", "F");
const jfieldID cameraFar = env->GetFieldID(klass, "cameraFar", "F");
const jfieldID groundShadowStrength = env->GetFieldID(klass, "groundShadowStrength", "F");
const jfieldID groundPlaneEnabled = env->GetFieldID(klass, "groundPlaneEnabled", "Z");
const jfieldID skyboxEnabled = env->GetFieldID(klass, "skyboxEnabled", "Z");
@@ -177,6 +179,8 @@ Java_com_google_android_filament_utils_AutomationEngine_nGetViewerOptions(JNIEnv
env->SetFloatField(result, cameraAperture, options.cameraAperture);
env->SetFloatField(result, cameraSpeed, options.cameraSpeed);
env->SetFloatField(result, cameraISO, options.cameraISO);
env->SetFloatField(result, cameraNear, options.cameraNear);
env->SetFloatField(result, cameraFar, options.cameraFar);
env->SetFloatField(result, groundShadowStrength, options.groundShadowStrength);
env->SetBooleanField(result, groundPlaneEnabled, options.groundPlaneEnabled);
env->SetBooleanField(result, skyboxEnabled, options.skyboxEnabled);

View File

@@ -97,6 +97,8 @@ public class AutomationEngine {
public float cameraAperture = 16.0f;
public float cameraSpeed = 125.0f;
public float cameraISO = 100.0f;
public float cameraNear = 0.1f;
public float cameraFar = 100.0f;
public float groundShadowStrength = 0.75f;
public boolean groundPlaneEnabled = false;
public boolean skyboxEnabled = true;

View File

@@ -27,8 +27,8 @@ import com.google.android.filament.gltfio.*
import kotlinx.coroutines.*
import java.nio.Buffer
private const val kNearPlane = 0.05 // 5 cm
private const val kFarPlane = 1000.0 // 1 km
private const val kNearPlane = 0.05f // 5 cm
private const val kFarPlane = 1000.0f // 1 km
private const val kAperture = 16f
private const val kShutterSpeed = 1f / 125f
private const val kSensitivity = 100f
@@ -80,6 +80,18 @@ class ModelViewer(
updateCameraProjection()
}
var cameraNear = kNearPlane
set(value) {
field = value
updateCameraProjection()
}
var cameraFar = kFarPlane
set(value) {
field = value
updateCameraProjection()
}
val scene: Scene
val view: View
val camera: Camera
@@ -368,7 +380,8 @@ class ModelViewer(
val width = view.viewport.width
val height = view.viewport.height
val aspect = width.toDouble() / height.toDouble()
camera.setLensProjection(cameraFocalLength.toDouble(), aspect, kNearPlane, kFarPlane)
camera.setLensProjection(cameraFocalLength.toDouble(), aspect,
cameraNear.toDouble(), cameraFar.toDouble())
}
inner class SurfaceCallback : UiHelper.RendererCallback {

View File

@@ -28,47 +28,81 @@ import com.google.android.filament.proguard.UsedByNative;
@UsedByNative("AssetLoader.cpp")
public interface MaterialProvider {
/**
* MaterialKey specifies the requirements for a requested glTF material.
* The provider creates Filament materials that fulfill these requirements.
*/
@UsedByNative("MaterialKey.cpp")
public static class MaterialKey {
@UsedByNative("MaterialKey.cpp")
public boolean doubleSided;
@UsedByNative("MaterialKey.cpp")
public boolean unlit;
@UsedByNative("MaterialKey.cpp")
public boolean hasVertexColors;
@UsedByNative("MaterialKey.cpp")
public boolean hasBaseColorTexture;
@UsedByNative("MaterialKey.cpp")
public boolean hasNormalTexture;
@UsedByNative("MaterialKey.cpp")
public boolean hasOcclusionTexture;
@UsedByNative("MaterialKey.cpp")
public boolean hasEmissiveTexture;
@UsedByNative("MaterialKey.cpp")
public boolean useSpecularGlossiness;
@UsedByNative("MaterialKey.cpp")
public int alphaMode; // 0 = OPAQUE, 1 = MASK, 2 = BLEND
@UsedByNative("MaterialKey.cpp")
public boolean enableDiagnostics;
@UsedByNative("MaterialKey.cpp")
public boolean hasMetallicRoughnessTexture; // piggybacks with specularRoughness
@UsedByNative("MaterialKey.cpp")
public int metallicRoughnessUV; // piggybacks with specularRoughness
@UsedByNative("MaterialKey.cpp")
public int baseColorUV;
@UsedByNative("MaterialKey.cpp")
public boolean hasClearCoatTexture;
@UsedByNative("MaterialKey.cpp")
public int clearCoatUV;
@UsedByNative("MaterialKey.cpp")
public boolean hasClearCoatRoughnessTexture;
@UsedByNative("MaterialKey.cpp")
public int clearCoatRoughnessUV;
@UsedByNative("MaterialKey.cpp")
public boolean hasClearCoatNormalTexture;
@UsedByNative("MaterialKey.cpp")
public int clearCoatNormalUV;
@UsedByNative("MaterialKey.cpp")
public boolean hasClearCoat;
@UsedByNative("MaterialKey.cpp")
public boolean hasTransmission;
@UsedByNative("MaterialKey.cpp")
public boolean hasTextureTransforms;
@UsedByNative("MaterialKey.cpp")
public int emissiveUV;
@UsedByNative("MaterialKey.cpp")
public int aoUV;
@UsedByNative("MaterialKey.cpp")
public int normalUV;
@UsedByNative("MaterialKey.cpp")
public boolean hasTransmissionTexture;
@UsedByNative("MaterialKey.cpp")
public int transmissionUV;
@UsedByNative("MaterialKey.cpp")
public boolean hasSheenColorTexture;
@UsedByNative("MaterialKey.cpp")
public int sheenColorUV;
@UsedByNative("MaterialKey.cpp")
public boolean hasSheenRoughnessTexture;
@UsedByNative("MaterialKey.cpp")
public int sheenRoughnessUV;
@UsedByNative("MaterialKey.cpp")
public boolean hasVolumeThicknessTexture;
@UsedByNative("MaterialKey.cpp")
public int volumeThicknessUV;
@UsedByNative("MaterialKey.cpp")
public boolean hasSheen;
@UsedByNative("MaterialKey.cpp")
public boolean hasIOR;
public MaterialKey() {}

View File

@@ -20,6 +20,7 @@ import com.google.android.filament.Engine;
import com.google.android.filament.MaterialInstance;
import com.google.android.filament.Material;
import com.google.android.filament.VertexBuffer;
import com.google.android.filament.proguard.UsedByNative;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -94,6 +95,7 @@ public class UbershaderProvider implements MaterialProvider {
nDestroyMaterials(mNativeObject);
}
@UsedByNative("AssetLoader.cpp")
public long getNativeObject() {
return mNativeObject;
}

View File

@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.31.1
VERSION_NAME=1.31.7
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
@@ -22,3 +22,5 @@ android.useAndroidX=true
com.google.android.filament.tools-dir=../../../out/release/filament
com.google.android.filament.dist-dir=../out/android-release/filament
com.google.android.filament.abis=all
#com.google.android.filament.matdbg
#com.google.android.filament.matnopt

View File

@@ -1,6 +1,6 @@
#Wed Nov 17 10:40:18 PST 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -356,6 +356,8 @@ class MainActivity : Activity() {
automation.applySettings(modelViewer.engine, json, viewerContent)
modelViewer.view.colorGrading = automation.getColorGrading(modelViewer.engine)
modelViewer.cameraFocalLength = automation.viewerOptions.cameraFocalLength
modelViewer.cameraNear = automation.viewerOptions.cameraNear
modelViewer.cameraFar = automation.viewerOptions.cameraFar
updateRootTransform()
}

View File

Before

Width:  |  Height:  |  Size: 848 KiB

After

Width:  |  Height:  |  Size: 848 KiB

View File

@@ -22,9 +22,11 @@ function print_help {
echo " All (and only) git-ignored files under android/ are deleted."
echo " This is sometimes needed instead of -c (which still misses some clean steps)."
echo " -d"
echo " Enable matdbg and disable material optimization."
echo " Enable matdbg."
echo " -f"
echo " Always invoke CMake before incremental builds."
echo " -g"
echo " Disable material optimization."
echo " -i"
echo " Install build output"
echo " -m"
@@ -56,6 +58,9 @@ function print_help {
echo " When building for Android, also build select sample APKs."
echo " sampleN is an Android sample, e.g., sample-gltf-viewer."
echo " This automatically performs a partial desktop build and install."
echo " -b"
echo " Enable Address and Undefined Behavior Sanitizers (asan/ubsan) for debugging."
echo " This is only for the desktop build."
echo ""
echo "Build types:"
echo " release"
@@ -162,6 +167,11 @@ EGL_ON_LINUX_OPTION="-DFILAMENT_SUPPORTS_EGL_ON_LINUX=OFF"
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=OFF"
MATDBG_GRADLE_OPTION=""
MATOPT_OPTION=""
MATOPT_GRADLE_OPTION=""
ASAN_UBSAN_OPTION=""
IOS_BUILD_SIMULATOR=false
BUILD_UNIVERSAL_LIBRARIES=false
@@ -221,6 +231,8 @@ function build_desktop_target {
${SWIFTSHADER_OPTION} \
${EGL_ON_LINUX_OPTION} \
${MATDBG_OPTION} \
${MATOPT_OPTION} \
${ASAN_UBSAN_OPTION} \
${deployment_target} \
${architectures} \
../..
@@ -347,6 +359,7 @@ function build_android_target {
-DCMAKE_INSTALL_PREFIX="../android-${lc_target}/filament" \
-DCMAKE_TOOLCHAIN_FILE="../../build/toolchain-${arch}-linux-android.cmake" \
${MATDBG_OPTION} \
${MATOPT_OPTION} \
${VULKAN_ANDROID_OPTION} \
../..
fi
@@ -463,6 +476,7 @@ function build_android {
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
${VULKAN_ANDROID_GRADLE_OPTION} \
${MATDBG_GRADLE_OPTION} \
${MATOPT_GRADLE_OPTION} \
:filament-android:assembleDebug \
:gltfio-android:assembleDebug \
:filament-utils-android:assembleDebug
@@ -510,6 +524,7 @@ function build_android {
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
${VULKAN_ANDROID_GRADLE_OPTION} \
${MATDBG_GRADLE_OPTION} \
${MATOPT_GRADLE_OPTION} \
:filament-android:assembleRelease \
:gltfio-android:assembleRelease \
:filament-utils-android:assembleRelease
@@ -576,6 +591,7 @@ function build_ios_target {
-DIOS=1 \
-DCMAKE_TOOLCHAIN_FILE=../../third_party/clang/iOS.cmake \
${MATDBG_OPTION} \
${MATOPT_OPTION} \
../..
fi
@@ -740,7 +756,7 @@ function run_tests {
pushd "$(dirname "$0")" > /dev/null
while getopts ":hacCfijmp:q:uvslwtedk:" opt; do
while getopts ":hacCfijmp:q:uvslwtedk:b" opt; do
case ${opt} in
h)
print_help
@@ -758,12 +774,16 @@ while getopts ":hacCfijmp:q:uvslwtedk:" opt; do
;;
d)
PRINT_MATDBG_HELP=true
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=ON, -DFILAMENT_DISABLE_MATOPT=ON, -DFILAMENT_BUILD_FILAMAT=ON"
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=ON, -DFILAMENT_BUILD_FILAMAT=ON"
MATDBG_GRADLE_OPTION="-Pcom.google.android.filament.matdbg"
;;
f)
ISSUE_CMAKE_ALWAYS=true
;;
g)
MATOPT_OPTION="-DFILAMENT_DISABLE_MATOPT=ON"
MATOPT_GRADLE_OPTION="-Pcom.google.android.filament.matnopt"
;;
i)
INSTALL_COMMAND=install
;;
@@ -863,6 +883,9 @@ while getopts ":hacCfijmp:q:uvslwtedk:" opt; do
BUILD_ANDROID_SAMPLES=true
ANDROID_SAMPLES=$(echo "${OPTARG}" | tr ',' '\n')
;;
b) ASAN_UBSAN_OPTION="-DFILAMENT_ENABLE_ASAN_UBSAN=ON"
echo "Enabled ASAN/UBSAN"
;;
\?)
echo "Invalid option: -${OPTARG}" >&2
echo ""

View File

@@ -44,6 +44,10 @@ FILAMENT_HEADERS="$1"
includes=()
pushd "$FILAMENT_HEADERS" >/dev/null
for f in $(find . -name '*.h'); do
# Ignore platform headers. These may contain platform-specific includes.
if [[ "$f" == *backend/platforms/* ]]; then
continue
fi
include_path="${f#./}" # strip leading ./
includes+=("${include_path}")
done

View File

@@ -1,7 +1,7 @@
#!/bin/bash
# version of clang we want to use
GITHUB_CLANG_VERSION=8
GITHUB_CLANG_VERSION=14
# version of CMake to use instead of the default one
CMAKE_VERSION=3.19.5
# version of ninja to use

View File

@@ -3821,7 +3821,7 @@ Since $\left< cos \theta \right>$ does not depend on $\phi$ (azimuthal independe
$$\begin{align*}
C^0_l &= 2\pi \int_0^{\pi} \left< cos \theta \right> y^0_l(\theta) sin \theta d\theta \\
C^0_l &= 2\pi K^)_l \int_0^{\frac{\pi}{2}} P^0_l(cos \theta) cos \theta sin \theta d\theta \\
C^0_l &= 2\pi K^m_l \int_0^{\frac{\pi}{2}} P^0_l(cos \theta) cos \theta sin \theta d\theta \\
C^m_l &= 0, m != 0
\end{align*}$$

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -50,7 +50,6 @@ set(PUBLIC_HDRS
set(SRCS
src/AtlasAllocator.cpp
src/Box.cpp
src/BufferObject.cpp
src/Camera.cpp
src/Color.cpp
@@ -589,6 +588,7 @@ else()
-Wgnu-conditional-omitted-operand
-Wweak-vtables -Wnon-virtual-dtor -Wclass-varargs -Wimplicit-fallthrough
-Wover-aligned
-Werror
)
endif()

View File

@@ -9,6 +9,7 @@ set(GENERATION_ROOT ${CMAKE_CURRENT_BINARY_DIR})
# Sources and headers
# ==================================================================================================
set(PUBLIC_HDRS
include/backend/AcquiredImage.h
include/backend/BufferDescriptor.h
include/backend/CallbackHandler.h
include/backend/DriverApiForward.h
@@ -36,12 +37,12 @@ set(SRCS
src/noop/NoopDriver.cpp
src/noop/PlatformNoop.cpp
src/Platform.cpp
src/PlatformFactory.cpp
src/Program.cpp
src/SamplerGroup.cpp
)
set(PRIVATE_HDRS
include/private/backend/AcquiredImage.h
include/private/backend/CircularBuffer.h
include/private/backend/CommandBufferQueue.h
include/private/backend/CommandStream.h
@@ -50,6 +51,7 @@ set(PRIVATE_HDRS
include/private/backend/DriverApi.h
include/private/backend/DriverAPI.inc
include/private/backend/HandleAllocator.h
include/private/backend/PlatformFactory.h
include/private/backend/SamplerGroup.h
src/CommandStreamDispatcher.h
src/DataReshaper.h
@@ -62,6 +64,7 @@ set(PRIVATE_HDRS
if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMENT_USE_SWIFTSHADER)
list(APPEND SRCS
include/backend/platforms/OpenGLPlatform.h
src/opengl/gl_headers.cpp
src/opengl/gl_headers.h
src/opengl/GLUtils.cpp
@@ -76,7 +79,6 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMEN
src/opengl/OpenGLPlatform.cpp
src/opengl/OpenGLTimerQuery.cpp
src/opengl/OpenGLTimerQuery.h
include/private/backend/OpenGLPlatform.h
)
if (EGL)
list(APPEND SRCS src/opengl/platforms/PlatformEGL.cpp)
@@ -112,7 +114,7 @@ endif()
# ==================================================================================================
if (FILAMENT_SUPPORTS_METAL)
set(METAL_SRCS
set(METAL_OBJC_SRCS
src/metal/MetalBlitter.mm
src/metal/MetalBuffer.mm
src/metal/MetalBufferPool.mm
@@ -122,18 +124,21 @@ if (FILAMENT_SUPPORTS_METAL)
src/metal/MetalExternalImage.mm
src/metal/MetalHandles.mm
src/metal/MetalPlatform.mm
src/metal/MetalResourceTracker.cpp
src/metal/MetalState.mm
src/metal/MetalTimerQuery.mm
src/metal/MetalUtils.mm
)
list(APPEND SRCS ${METAL_SRCS})
set(METAL_CPP_SRCS
src/metal/MetalResourceTracker.cpp
)
list(APPEND SRCS ${METAL_OBJC_SRCS} ${METAL_CPP_SRCS})
if (IOS)
# Objective-C++ sources need an additional compiler flag on iOS to disable exceptions.
set_property(SOURCE
${METAL_SRCS}
${METAL_OBJC_SRCS}
src/opengl/platforms/PlatformCocoaTouchGL.mm
src/opengl/platforms/CocoaTouchExternalImage.mm
src/opengl/platforms/PlatformCocoaGL.mm
@@ -150,6 +155,7 @@ endif()
# See root CMakeLists.txt for platforms that support Vulkan
if (FILAMENT_SUPPORTS_VULKAN)
list(APPEND SRCS
include/backend/platforms/VulkanPlatform.h
src/vulkan/VulkanBlitter.cpp
src/vulkan/VulkanBlitter.h
src/vulkan/VulkanBuffer.cpp
@@ -173,7 +179,6 @@ if (FILAMENT_SUPPORTS_VULKAN)
src/vulkan/VulkanPipelineCache.cpp
src/vulkan/VulkanPipelineCache.h
src/vulkan/VulkanPlatform.cpp
src/vulkan/VulkanPlatform.h
src/vulkan/VulkanSamplerCache.cpp
src/vulkan/VulkanSamplerCache.h
src/vulkan/VulkanStagePool.cpp
@@ -348,6 +353,7 @@ else()
-Wgnu-conditional-omitted-operand
-Wweak-vtables -Wnon-virtual-dtor -Wclass-varargs -Wimplicit-fallthrough
-Wover-aligned
-Werror
)
endif()

View File

@@ -42,11 +42,42 @@
*/
namespace filament::backend {
/**
* Requests a SwapChain with an alpha channel.
*/
static constexpr uint64_t SWAP_CHAIN_CONFIG_TRANSPARENT = 0x1;
/**
* This flag indicates that the swap chain may be used as a source surface
* for reading back render results. This config flag must be set when creating
* any SwapChain that will be used as the source for a blit operation.
*/
static constexpr uint64_t SWAP_CHAIN_CONFIG_READABLE = 0x2;
/**
* Indicates that the native X11 window is an XCB window rather than an XLIB window.
* This is ignored on non-Linux platforms and in builds that support only one X11 API.
*/
static constexpr uint64_t SWAP_CHAIN_CONFIG_ENABLE_XCB = 0x4;
/**
* Indicates that the native window is a CVPixelBufferRef.
*
* This is only supported by the Metal backend. The CVPixelBuffer must be in the
* kCVPixelFormatType_32BGRA format.
*
* It is not necessary to add an additional retain call before passing the pixel buffer to
* Filament. Filament will call CVPixelBufferRetain during Engine::createSwapChain, and
* CVPixelBufferRelease when the swap chain is destroyed.
*/
static constexpr uint64_t SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER = 0x8;
/**
* Indicates that the SwapChain must automatically perform linear to srgb encoding.
*/
static constexpr uint64_t SWAP_CHAIN_CONFIG_SRGB_COLORSPACE = 0x10;
static constexpr size_t MAX_VERTEX_ATTRIBUTE_COUNT = 16; // This is guaranteed by OpenGL ES.
static constexpr size_t MAX_SAMPLER_COUNT = 62; // Maximum needed at feature level 3.
static constexpr size_t MAX_VERTEX_BUFFER_COUNT = 16; // Max number of bound buffer objects.

View File

@@ -279,8 +279,8 @@ public:
break;
}
size_t bpr = bpp * stride;
size_t bprAligned = (bpr + (alignment - 1)) & (~alignment + 1);
size_t const bpr = bpp * stride;
size_t const bprAligned = (bpr + (alignment - 1)) & (~alignment + 1);
return bprAligned * height;
}

View File

@@ -23,22 +23,28 @@
#include <utils/compiler.h>
namespace filament {
namespace backend {
namespace filament::backend {
class Driver;
/**
* Platform is an interface that abstracts how the backend (also referred to as Driver) is
* created. The backend provides several common Platform concrete implementations, which are
* selected automatically. It is possible however to provide a custom Platform when creating
* the filament Engine.
*/
class UTILS_PUBLIC Platform {
public:
struct SwapChain {};
struct Fence {};
struct Stream {};
struct ExternalTexture {
uintptr_t image = 0;
};
struct DriverConfig {
size_t handleArenaSize = 0; // size of handle arena in bytes. Setting to 0 indicates default value is to be used. Driver clamps to valid values.
/*
* size of handle arena in bytes. Setting to 0 indicates default value is to be used.
* Driver clamps to valid values.
*/
size_t handleArenaSize = 0;
};
virtual ~Platform() noexcept;
@@ -62,7 +68,8 @@ public:
*
* @return nullptr on failure, or a pointer to the newly created driver.
*/
virtual backend::Driver* createDriver(void* sharedContext, const DriverConfig& driverConfig) noexcept = 0;
virtual backend::Driver* createDriver(void* sharedContext,
const DriverConfig& driverConfig) noexcept = 0;
/**
* Processes the platform's event queue when called from its primary event-handling thread.
@@ -71,39 +78,9 @@ public:
* on platforms that need it, such as macOS + OpenGL. Returns false if this is not the main
* thread, or if the platform does not need to perform any special processing.
*/
virtual bool pumpEvents() noexcept { return false; }
virtual bool pumpEvents() noexcept;
};
class UTILS_PUBLIC DefaultPlatform : public Platform {
public:
~DefaultPlatform() noexcept override;
/**
* Creates a Platform configured for the requested backend if available
*
* @param backendHint Preferred backend, if not available the backend most suitable for the
* underlying platform is returned and \p backendHint is updated
* accordingly. Can't be nullptr.
*
* @return A pointer to the Platform object.
*
* @see destroy
*/
static DefaultPlatform* create(backend::Backend* backendHint) noexcept;
/**
* Destroys a Platform object returned by create()
*
* @param platform a reference (as a pointer) to the DefaultPlatform pointer to destroy.
* \p platform is cleared upon return.
*
* @see create
*/
static void destroy(DefaultPlatform** platform) noexcept;
};
} // namespace backend
} // namespace filament
#endif // TNT_FILAMENT_BACKEND_PLATFORM_H

View File

@@ -0,0 +1,4 @@
# include/backend Headers
Headers in `include/backend/` are fully public, in particular they can be included in filament's
public headers.

View File

@@ -0,0 +1,261 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_OPENGLPLATFORM_H
#define TNT_FILAMENT_BACKEND_PRIVATE_OPENGLPLATFORM_H
#include <backend/AcquiredImage.h>
#include <backend/Platform.h>
namespace filament::backend {
class Driver;
/**
* A Platform interface that creates an OpenGL backend.
*
* WARNING: None of the methods below are allowed to change the GL state and must restore it
* upon return.
*
*/
class OpenGLPlatform : public Platform {
protected:
/*
* Derived classes can use this to instantiate the default OpenGLDriver backend.
* This is typically called from your implementation of createDriver()
*/
static Driver* createDefaultDriver(OpenGLPlatform* platform,
void* sharedContext, const DriverConfig& driverConfig);
~OpenGLPlatform() noexcept override;
public:
struct ExternalTexture {
unsigned int target; // GLenum target
unsigned int id; // GLuint id
};
/**
* Called by the driver to destroy the OpenGL context. This should clean up any windows
* or buffers from initialization. This is for instance where `eglDestroyContext` would be
* called.
*/
virtual void terminate() noexcept = 0;
/**
* Called by the driver to create a SwapChain for this driver.
*
* @param nativeWindow a token representing the native window. See concrete implementation
* for details.
* @param flags extra flags used by the implementation, see filament::SwapChain
* @return The driver's SwapChain object.
*
*/
virtual SwapChain* createSwapChain(void* 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.
*
* @param width width of the buffer
* @param height height of the buffer
* @param flags extra flags used by the implementation, see filament::SwapChain
* @return The driver's SwapChain object.
*
* TODO: we need a more generic way of passing construction parameters
* A void* might be enough.
*/
virtual SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept = 0;
/**
* Called by the driver to destroys the SwapChain
* @param swapChain SwapChain to be destroyed.
*/
virtual void destroySwapChain(SwapChain* swapChain) noexcept = 0;
/**
* Called by the driver to establish the default FBO. The default implementation returns 0.
* @return a GLuint casted to a uint32_t that is an OpenGL framebuffer object.
*/
virtual uint32_t createDefaultRenderTarget() noexcept;
/**
* Called by the driver to make the OpenGL context active on the calling thread and bind
* the drawSwapChain to the default render target (FBO) created with createDefaultRenderTarget.
* @param drawSwapChain SwapChain to draw to. It must be bound to the default FBO.
* @param readSwapChain SwapChain to read from (for operation like `glBlitFramebuffer`)
*/
virtual void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept = 0;
/**
* Called by the driver once the current frame finishes drawing. Typically, this should present
* the drawSwapChain. This is for example where `eglMakeCurrent()` would be called.
* @param swapChain the SwapChain to present.
*/
virtual void commit(SwapChain* swapChain) noexcept = 0;
/**
* Set the time the next committed buffer should be presented to the user at.
*
* @param presentationTimeInNanosecond time in the future in nanosecond. The clock used depends
* on the concrete platform implementation.
*/
virtual void setPresentationTime(int64_t presentationTimeInNanosecond) noexcept;
// --------------------------------------------------------------------------------------------
// Fence support
/**
* Can this implementation create a Fence.
* @return true if supported, false otherwise. The default implementation returns false.
*/
virtual bool canCreateFence() noexcept;
/**
* Creates a Fence (e.g. eglCreateSyncKHR). This must be implemented if `canCreateFence`
* returns true. Fences are used for frame pacing.
*
* @return A Fence object. The default implementation returns nullptr.
*/
virtual Fence* createFence() noexcept;
/**
* Destroys a Fence object. The default implementation does nothing.
*
* @param fence Fence to destroy.
*/
virtual void destroyFence(Fence* fence) noexcept;
/**
* Waits on a Fence.
*
* @param fence Fence to wait on.
* @param timeout Timeout.
* @return Whether the fence signaled or timed out. See backend::FenceStatus.
* The default implementation always return backend::FenceStatus::ERROR.
*/
virtual backend::FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept;
// --------------------------------------------------------------------------------------------
// Streaming support
/**
* Creates a Stream from a native Stream.
*
* WARNING: This is called synchronously from the application thread (NOT the Driver thread)
*
* @param nativeStream The native stream, this parameter depends on the concrete implementation.
* @return A new Stream object.
*/
virtual Stream* createStream(void* nativeStream) noexcept;
/**
* Destroys a Stream.
* @param stream Stream to destroy.
*/
virtual void destroyStream(Stream* stream) noexcept;
/**
* The specified stream takes ownership of the texture (tname) object
* Once attached, the texture is automatically updated with the Stream's content, which
* could be a video stream for instance.
*
* @param stream Stream to take ownership of the texture
* @param tname GL texture id to "bind" to the Stream.
*/
virtual void attach(Stream* stream, intptr_t tname) noexcept;
/**
* Destroys the texture associated to the stream
* @param stream Stream to detach from its texture
*/
virtual void detach(Stream* stream) noexcept;
/**
* Updates the content of the texture attached to the stream.
* @param stream Stream to update
* @param timestamp Output parameter: Timestamp of the image bound to the texture.
*/
virtual void updateTexImage(Stream* stream, int64_t* timestamp) noexcept;
// --------------------------------------------------------------------------------------------
// External Image support
/**
* Creates an external texture handle. External textures don't have any parameters because
* these are undefined until setExternalImage() is called.
* @return a pointer to an ExternalTexture structure filled with valid token. However, the
* implementation could just return { 0, GL_TEXTURE_2D } at this point. The actual
* values can be delayed until setExternalImage.
*/
virtual ExternalTexture *createExternalImageTexture() noexcept;
/**
* Destroys an external texture handle and associated data.
* @param texture a pointer to the handle to destroy.
*/
virtual void destroyExternalImage(ExternalTexture* 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.
*
* 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* 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.
*
* @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* externalImage, ExternalTexture* 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.
* @param source Image to transform.
* @return Transformed image.
*/
virtual AcquiredImage transformAcquiredImage(AcquiredImage source) noexcept;
};
} // namespace filament
#endif // TNT_FILAMENT_BACKEND_PRIVATE_OPENGLPLATFORM_H

View File

@@ -0,0 +1,67 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
#include <stdint.h>
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/DriverEnums.h>
namespace filament::backend {
struct PlatformCocoaGLImpl;
/**
* A concrete implementation of OpenGLPlatform that supports macOS's Cocoa.
*/
class PlatformCocoaGL : public OpenGLPlatform {
public:
PlatformCocoaGL();
~PlatformCocoaGL() noexcept override;
protected:
// --------------------------------------------------------------------------------------------
// Platform Interface
Driver* createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) noexcept override;
// Currently returns 0
int getOSVersion() const noexcept override;
bool pumpEvents() noexcept override;
// --------------------------------------------------------------------------------------------
// OpenGLPlatform Interface
void terminate() noexcept override;
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
private:
PlatformCocoaGLImpl* pImpl = nullptr;
};
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H

View File

@@ -0,0 +1,69 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_TOUCH_GL_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_TOUCH_GL_H
#include <stdint.h>
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/DriverEnums.h>
namespace filament::backend {
struct PlatformCocoaTouchGLImpl;
class PlatformCocoaTouchGL : public OpenGLPlatform {
public:
PlatformCocoaTouchGL();
~PlatformCocoaTouchGL() noexcept;
// --------------------------------------------------------------------------------------------
// Platform Interface
Driver* createDriver(void* sharedGLContext,
const Platform::DriverConfig& driverConfig) noexcept override;
int getOSVersion() const noexcept final { return 0; }
// --------------------------------------------------------------------------------------------
// OpenGLPlatform Interface
void terminate() noexcept override;
uint32_t createDefaultRenderTarget() noexcept override;
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;
void destroyExternalImage(ExternalTexture* texture) noexcept override;
void retainExternalImage(void* externalImage) noexcept override;
bool setExternalImage(void* externalImage, ExternalTexture* texture) noexcept override;
private:
PlatformCocoaTouchGLImpl* pImpl = nullptr;
};
using ContextManager = PlatformCocoaTouchGL;
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_TOUCH_GL_H

View File

@@ -22,65 +22,97 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <backend/DriverEnums.h>
#include <backend/platforms/OpenGLPlatform.h>
#include "private/backend/OpenGLPlatform.h"
#include <backend/DriverEnums.h>
namespace filament::backend {
/**
* A concrete implementation of OpenGLPlatform that supports EGL.
*/
class PlatformEGL : public OpenGLPlatform {
public:
PlatformEGL() noexcept;
Driver* createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept override;
protected:
// --------------------------------------------------------------------------------------------
// Platform Interface
/**
* Initializes EGL, creates the OpenGL context and returns a concrete Driver implementation
* that supports OpenGL/OpenGL ES.
*/
Driver* createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) noexcept override;
/**
* This returns zero. This method can be overridden to return something more useful.
* @return zero
*/
int getOSVersion() const noexcept override;
// --------------------------------------------------------------------------------------------
// OpenGLPlatform Interface
void terminate() noexcept override;
SwapChain* createSwapChain(void* nativewindow, uint64_t& flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t& flags) noexcept override;
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;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
bool canCreateFence() noexcept override { return true; }
bool canCreateFence() noexcept override;
Fence* createFence() noexcept override;
void destroyFence(Fence* fence) noexcept override;
FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept override;
void createExternalImageTexture(void* texture) noexcept override;
void destroyExternalImage(void* texture) noexcept override;
OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;
void destroyExternalImage(ExternalTexture* texture) noexcept override;
bool setExternalImage(void* externalImage, ExternalTexture* texture) noexcept override;
/* default no-op implementations... */
int getOSVersion() const noexcept override { return 0; }
void setPresentationTime(int64_t presentationTimeInNanosecond) noexcept override {}
Stream* createStream(void* nativeStream) noexcept override { return nullptr; }
void destroyStream(Stream* stream) noexcept override {}
void attach(Stream* stream, intptr_t tname) noexcept override {}
void detach(Stream* stream) noexcept override {}
void updateTexImage(Stream* stream, int64_t* timestamp) noexcept override {}
protected:
/**
* Logs glGetError() to slog.e
* @param name a string giving some context on the error. Typically __func__.
*/
static void logEglError(const char* name) noexcept;
/**
* Calls glGetError() to clear the current error flags. logs a warning to log.w if
* an error was pending.
*/
static void clearGlError() noexcept;
/**
* Always use this instead of eglMakeCurrent().
*/
EGLBoolean makeCurrent(EGLSurface drawSurface, EGLSurface readSurface) noexcept;
void initializeGlExtensions() noexcept;
// TODO: this should probably use getters instead.
EGLDisplay mEGLDisplay = EGL_NO_DISPLAY;
EGLContext mEGLContext = EGL_NO_CONTEXT;
EGLSurface mCurrentDrawSurface = EGL_NO_SURFACE;
EGLSurface mCurrentReadSurface = EGL_NO_SURFACE;
EGLSurface mEGLDummySurface = EGL_NO_SURFACE;
EGLConfig mEGLConfig = EGL_NO_CONFIG_KHR;
EGLConfig mEGLTransparentConfig = EGL_NO_CONFIG_KHR;
// supported extensions detected at runtime
struct {
bool OES_EGL_image_external_essl3 = false;
struct {
bool OES_EGL_image_external_essl3 = false;
} gl;
struct {
bool KHR_no_config_context = false;
bool KHR_gl_colorspace = false;
} egl;
} ext;
private:
void initializeGlExtensions() noexcept;
EGLConfig findSwapChainConfig(uint64_t flags) const;
};
} // namespace filament::backend

View File

@@ -0,0 +1,82 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H
#include <backend/platforms/PlatformEGL.h>
namespace filament::backend {
class ExternalStreamManagerAndroid;
/**
* A concrete implementation of OpenGLPlatform and subclass of PlatformEGL that supports
* EGL on Android. It adds Android streaming functionality to PlatformEGL.
*/
class PlatformEGLAndroid : public PlatformEGL {
public:
PlatformEGLAndroid() noexcept;
~PlatformEGLAndroid() noexcept override;
protected:
// --------------------------------------------------------------------------------------------
// Platform Interface
/**
* Returns the Android SDK version.
* @return Android SDK version.
*/
int getOSVersion() const noexcept override;
Driver* createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) noexcept override;
// --------------------------------------------------------------------------------------------
// OpenGLPlatform Interface
void terminate() noexcept override;
/**
* Set the presentation time using `eglPresentationTimeANDROID`
* @param presentationTimeInNanosecond
*/
void setPresentationTime(int64_t presentationTimeInNanosecond) noexcept override;
Stream* createStream(void* nativeStream) noexcept override;
void destroyStream(Stream* stream) noexcept override;
void attach(Stream* stream, intptr_t tname) noexcept override;
void detach(Stream* stream) noexcept override;
void updateTexImage(Stream* stream, int64_t* timestamp) noexcept override;
/**
* Converts a AHardwareBuffer to EGLImage
* @param source source.image is a AHardwareBuffer
* @return source.image contains an EGLImage
*/
AcquiredImage transformAcquiredImage(AcquiredImage source) noexcept override;
private:
int mOSVersion;
ExternalStreamManagerAndroid& mExternalStreamManager;
};
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H

View File

@@ -21,16 +21,15 @@
namespace filament::backend {
class PlatformEGLHeadless final : public PlatformEGL {
/**
* A concrete implementation of OpenGLPlatform that supports EGL with only headless swapchains.
*/
class PlatformEGLHeadless : public PlatformEGL {
public:
PlatformEGLHeadless() noexcept;
Driver* createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept final;
void createExternalImageTexture(void* texture) noexcept final {}
void destroyExternalImage(void* texture) noexcept final {}
Driver* createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) noexcept override;
};
} // namespace filament

View File

@@ -19,44 +19,41 @@
#include <stdint.h>
#include <bluegl/BlueGL.h>
#include "bluegl/BlueGL.h"
#include <GL/glx.h>
#include <backend/DriverEnums.h>
#include <backend/platforms/OpenGLPlatform.h>
#include "private/backend/OpenGLPlatform.h"
#include <backend/DriverEnums.h>
#include <vector>
namespace filament::backend {
class PlatformGLX final : public OpenGLPlatform {
public:
/**
* A concrete implementation of OpenGLPlatform that supports GLX.
*/
class PlatformGLX : public OpenGLPlatform {
protected:
// --------------------------------------------------------------------------------------------
// Platform Interface
Driver* createDriver(void* const sharedGLContext, const DriverConfig& driverConfig) noexcept override;
Driver* createDriver(void* sharedGLContext,
const DriverConfig& driverConfig) noexcept override;
int getOSVersion() const noexcept final override { return 0; }
// --------------------------------------------------------------------------------------------
// OpenGLPlatform Interface
void terminate() noexcept override;
SwapChain* createSwapChain(void* nativewindow, uint64_t& flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t& flags) noexcept override;
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
Fence* createFence() noexcept override;
void destroyFence(Fence* fence) noexcept override;
FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept override;
void setPresentationTime(int64_t time) 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, int64_t* timestamp) noexcept final override {}
int getOSVersion() const noexcept final override { return 0; }
private:
Display *mGLXDisplay;
GLXContext mGLXContext;

View File

@@ -20,40 +20,39 @@
#include <stdint.h>
#include <windows.h>
#include <utils/unwindows.h>
#include "utils/unwindows.h"
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/DriverEnums.h>
#include "private/backend/OpenGLPlatform.h"
namespace filament::backend {
class PlatformWGL final : public OpenGLPlatform {
public:
Driver* createDriver(void* const sharedGLContext, const Platform::DriverConfig& driverConfig) noexcept override;
/**
* A concrete implementation of OpenGLPlatform that supports WGL.
*/
class PlatformWGL : public OpenGLPlatform {
protected:
// --------------------------------------------------------------------------------------------
// Platform Interface
Driver* createDriver(void* sharedGLContext,
const Platform::DriverConfig& driverConfig) noexcept override;
int getOSVersion() const noexcept final override { return 0; }
// --------------------------------------------------------------------------------------------
// OpenGLPlatform Interface
void terminate() noexcept override;
SwapChain* createSwapChain(void* nativewindow, uint64_t& flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t& flags) noexcept override;
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
Fence* createFence() noexcept override;
void destroyFence(Fence* fence) noexcept override;
FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept override;
void setPresentationTime(int64_t time) 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, int64_t* timestamp) noexcept final override {}
int getOSVersion() const noexcept final override { return 0; }
private:
protected:
HGLRC mContext = NULL;
HWND mHWnd = NULL;
HDC mWhdc = NULL;

View File

@@ -0,0 +1,55 @@
/*
* 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_BACKEND_OPENGL_OPENGL_PLATFORM_WEBGL_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_WEBGL_H
#include <stdint.h>
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/DriverEnums.h>
namespace filament::backend {
/**
* A concrete implementation of OpenGLPlatform that supports WebGL.
*/
class PlatformWebGL : public OpenGLPlatform {
protected:
// --------------------------------------------------------------------------------------------
// Platform Interface
Driver* createDriver(void* sharedGLContext,
const Platform::DriverConfig& driverConfig) noexcept override;
int getOSVersion() const noexcept override;
// --------------------------------------------------------------------------------------------
// OpenGLPlatform Interface
void terminate() noexcept override;
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
};
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_WEBGL_H

View File

@@ -14,21 +14,36 @@
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_VULKANPLATFORM_H
#define TNT_FILAMENT_BACKEND_VULKANPLATFORM_H
#ifndef TNT_FILAMENT_BACKEND_PLATFORMS_VULKANPLATFORM_H
#define TNT_FILAMENT_BACKEND_PLATFORMS_VULKANPLATFORM_H
#include <backend/Platform.h>
namespace filament::backend {
class VulkanPlatform : public DefaultPlatform {
/**
* A Platform interface that creates a Vulkan backend.
*/
class VulkanPlatform : public Platform {
public:
struct SurfaceBundle {
void* surface;
// On certain platforms, the extent of the surface cannot be queried from Vulkan. In those
// situations, we allow the frontend to pass in the extent to use in creating the swap
// chains. Platform implementation should set extent to 0 if they do not expect to set the
// swap chain extent.
uint32_t width;
uint32_t height;
};
// Given a Vulkan instance and native window handle, creates the platform-specific surface.
virtual void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept = 0;
virtual SurfaceBundle createVkSurfaceKHR(void* nativeWindow, void* instance,
uint64_t flags) noexcept = 0;
~VulkanPlatform() override;
};
} // namespace filament::backend
#endif //TNT_FILAMENT_BACKEND_VULKANPLATFORM_H
#endif //TNT_FILAMENT_BACKEND_PLATFORMS_VULKANPLATFORM_H

View File

@@ -299,11 +299,11 @@ DECL_DRIVER_API_SYNCHRONOUS_0(bool, isFrameBufferFetchSupported)
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(uint8_t, getMaxDrawBuffers)
DECL_DRIVER_API_SYNCHRONOUS_0(math::float2, getClipSpaceParams)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, canGenerateMipmaps)
DECL_DRIVER_API_SYNCHRONOUS_N(void, setupExternalImage, void*, image)
DECL_DRIVER_API_SYNCHRONOUS_N(void, cancelExternalImage, void*, image)
DECL_DRIVER_API_SYNCHRONOUS_N(bool, getTimerQueryValue, backend::TimerQueryHandle, query, uint64_t*, elapsedTime)
DECL_DRIVER_API_SYNCHRONOUS_N(backend::SyncStatus, getSyncStatus, backend::SyncHandle, sh)
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isWorkaroundNeeded, backend::Workaround, workaround)

View File

@@ -1,111 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_OPENGLPLATFORM_H
#define TNT_FILAMENT_BACKEND_PRIVATE_OPENGLPLATFORM_H
#include <backend/Platform.h>
#include "private/backend/AcquiredImage.h"
namespace filament {
namespace backend {
class Driver;
class OpenGLPlatform : public DefaultPlatform {
protected:
/*
* Derived classes can use this to instantiate the default OpenGLDriver backend.
* This is typically called from your implementation of createDriver()
*/
static Driver* createDefaultDriver(OpenGLPlatform* platform, void* sharedContext, const DriverConfig& driverConfig);
public:
~OpenGLPlatform() noexcept override;
// Called to destroy the OpenGL context. This should clean up any windows
// or buffers from initialization.
virtual void terminate() noexcept = 0;
virtual SwapChain* createSwapChain(void* nativeWindow, uint64_t& flags) noexcept = 0;
// headless swapchain
virtual SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t& flags) noexcept = 0;
virtual void destroySwapChain(SwapChain* swapChain) noexcept = 0;
virtual void createDefaultRenderTarget(uint32_t& framebuffer, uint32_t& colorbuffer,
uint32_t& depthbuffer) noexcept {
framebuffer = 0;
colorbuffer = 0;
depthbuffer = 0;
}
// Called to make the OpenGL context active on the calling thread.
virtual void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept = 0;
// Called once the current frame finishes drawing. Typically this should
// swap draw buffers (i.e. for double-buffered rendering).
virtual void commit(SwapChain* swapChain) noexcept = 0;
virtual void setPresentationTime(int64_t presentationTimeInNanosecond) noexcept = 0;
virtual bool canCreateFence() noexcept { return false; }
virtual Fence* createFence() noexcept = 0;
virtual void destroyFence(Fence* fence) noexcept = 0;
virtual backend::FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept = 0;
// this is called synchronously in the application thread (NOT the Driver thread)
virtual Stream* createStream(void* nativeStream) noexcept = 0;
virtual void destroyStream(Stream* stream) noexcept = 0;
// attach takes ownership of the texture (tname) object
virtual void attach(Stream* stream, intptr_t tname) noexcept = 0;
// detach destroys the texture associated to the stream
virtual void detach(Stream* stream) noexcept = 0;
virtual void updateTexImage(Stream* stream, int64_t* timestamp) noexcept = 0;
// The method allows platforms to convert a user-supplied external image object into a new type
// (e.g. HardwareBuffer => EGLImage). It makes sense for the default implementation to do nothing.
virtual AcquiredImage transformAcquiredImage(AcquiredImage source) noexcept { return source; }
// called to bind the platform-specific externalImage to a texture
// texture points to a OpenGLDriver::GLTexture
virtual bool setExternalImage(void* externalImage, void* texture) noexcept {
return false;
}
// called on the application thread to allow Filament to take ownership of the image
virtual void retainExternalImage(void* externalImage) noexcept {}
// called to release ownership of the image
virtual void releaseExternalImage(void* externalImage) noexcept {}
// called once when a new SAMPLER_EXTERNAL texture is created.
virtual void createExternalImageTexture(void* texture) noexcept {}
// called once before a SAMPLER_EXTERNAL texture is destroyed.
virtual void destroyExternalImage(void* texture) noexcept {}
};
} // namespace backend
} // namespace filament
#endif // TNT_FILAMENT_BACKEND_PRIVATE_OPENGLPLATFORM_H

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2022 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.
*/
//! \file
#ifndef TNT_FILAMENT_BACKEND_PLATFORM_FACTORY_H
#define TNT_FILAMENT_BACKEND_PLATFORM_FACTORY_H
#include "backend/DriverEnums.h"
#include "utils/compiler.h"
namespace filament::backend {
class Platform;
class UTILS_PUBLIC PlatformFactory {
public:
/**
* Creates a Platform configured for the requested backend if available
*
* @param backendHint Preferred backend, if not available the backend most suitable for the
* underlying platform is returned and \p backendHint is updated
* accordingly. Can't be nullptr.
*
* @return A pointer to the Platform object.
*
* @see destroy
*/
static Platform* create(backend::Backend* backendHint) noexcept;
/**
* Destroys a Platform object returned by create()
*
* @param platform a reference (as a pointer) to the Platform pointer to destroy.
* \p platform is cleared upon return.
*
* @see create
*/
static void destroy(Platform** platform) noexcept;
};
} // namespace filament
#endif // TNT_FILAMENT_BACKEND_PLATFORM_FACTORY_H

View File

@@ -0,0 +1,3 @@
# include/private/backend Headers
Headers in `include/private/backend/` are only public to filament and cannot be used by end-users.

View File

@@ -75,6 +75,7 @@ CommandStream::CommandStream(Driver& driver, CircularBuffer& buffer) noexcept
void CommandStream::execute(void* buffer) {
SYSTRACE_CALL();
SYSTRACE_CONTEXT();
Profiler profiler;

View File

@@ -14,22 +14,21 @@
* limitations under the License.
*/
#include "private/backend/Driver.h"
#include "DriverBase.h"
#include "private/backend/AcquiredImage.h"
#include "private/backend/Driver.h"
#include "private/backend/CommandStream.h"
#include "DriverBase.h"
#include <backend/AcquiredImage.h>
#include <backend/BufferDescriptor.h>
#include <utils/Systrace.h>
#include <math/half.h>
#include <math/vec2.h>
#include <math/vec3.h>
#include <math/vec4.h>
#include <backend/BufferDescriptor.h>
#include <utils/Systrace.h>
using namespace utils;
using namespace filament::math;

View File

@@ -16,172 +16,13 @@
#include <backend/Platform.h>
#include <utils/Systrace.h>
#include <utils/debug.h>
#if defined(__ANDROID__)
#include <sys/system_properties.h>
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
#include "opengl/platforms/PlatformEGLAndroid.h"
#endif
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkAndroid.h"
#endif
#elif defined(IOS)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
#include "opengl/platforms/PlatformCocoaTouchGL.h"
#endif
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkCocoaTouch.h"
#endif
#elif defined(__APPLE__)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
#include "opengl/platforms/PlatformCocoaGL.h"
#endif
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkCocoa.h"
#endif
#elif defined(__linux__)
#if defined(FILAMENT_SUPPORTS_GGP)
#include "vulkan/PlatformVkLinuxGGP.h"
#elif defined(FILAMENT_SUPPORTS_WAYLAND)
#if defined (FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkLinuxWayland.h"
#endif
#elif defined(FILAMENT_SUPPORTS_X11)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
#include "opengl/platforms/PlatformGLX.h"
#endif
#if defined (FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkLinuxX11.h"
#endif
#elif defined(FILAMENT_SUPPORTS_EGL_ON_LINUX)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
#include "opengl/platforms/PlatformEGLHeadless.h"
#endif
#endif
#elif defined(WIN32)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
#include "opengl/platforms/PlatformWGL.h"
#endif
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkWindows.h"
#endif
#elif defined(__EMSCRIPTEN__)
#include "opengl/platforms/PlatformWebGL.h"
#endif
#if defined (FILAMENT_SUPPORTS_METAL)
namespace filament::backend {
filament::backend::DefaultPlatform* createDefaultMetalPlatform();
}
#endif
#include "noop/PlatformNoop.h"
namespace filament::backend {
// this generates the vtable in this translation unit
Platform::~Platform() noexcept = default;
// Creates the platform-specific Platform object. The caller takes ownership and is
// responsible for destroying it. Initialization of the backend API is deferred until
// createDriver(). The passed-in backend hint is replaced with the resolved backend.
DefaultPlatform* DefaultPlatform::create(Backend* backend) noexcept {
SYSTRACE_CALL();
assert_invariant(backend);
#if defined(__ANDROID__)
char scratch[PROP_VALUE_MAX + 1];
int length = __system_property_get("debug.filament.backend", scratch);
if (length > 0) {
*backend = Backend(atoi(scratch));
}
#endif
if (*backend == Backend::DEFAULT) {
#if defined(__EMSCRIPTEN__)
*backend = Backend::OPENGL;
#elif defined(__ANDROID__)
*backend = Backend::OPENGL;
#elif defined(IOS) || defined(__APPLE__)
*backend = Backend::METAL;
#elif defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
*backend = Backend::VULKAN;
#else
* backend = Backend::OPENGL;
#endif
}
if (*backend == Backend::NOOP) {
return new PlatformNoop();
}
if (*backend == Backend::VULKAN) {
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
#if defined(__ANDROID__)
return new PlatformVkAndroid();
#elif defined(IOS)
return new PlatformVkCocoaTouch();
#elif defined(__linux__)
#if defined(FILAMENT_SUPPORTS_GGP)
return new PlatformVkLinuxGGP();
#elif defined(FILAMENT_SUPPORTS_WAYLAND)
return new PlatformVkLinuxWayland();
#elif defined(FILAMENT_SUPPORTS_X11)
return new PlatformVkLinuxX11();
#endif
#elif defined(__APPLE__)
return new PlatformVkCocoa();
#elif defined(WIN32)
return new PlatformVkWindows();
#else
return nullptr;
#endif
#else
return nullptr;
#endif
}
if (*backend == Backend::METAL) {
#if defined(FILAMENT_SUPPORTS_METAL)
return createDefaultMetalPlatform();
#else
return nullptr;
#endif
}
assert_invariant(*backend == Backend::OPENGL);
#if defined(FILAMENT_SUPPORTS_OPENGL)
#if defined(FILAMENT_USE_EXTERNAL_GLES3) || defined(FILAMENT_USE_SWIFTSHADER)
// Swiftshader OpenGLES support is deprecated and incomplete
return nullptr;
#elif defined(__ANDROID__)
return new PlatformEGLAndroid();
#elif defined(IOS)
return new PlatformCocoaTouchGL();
#elif defined(__APPLE__)
return new PlatformCocoaGL();
#elif defined(__linux__)
#if defined(FILAMENT_SUPPORTS_X11)
return new PlatformGLX();
#elif defined(FILAMENT_SUPPORTS_EGL_ON_LINUX)
return new PlatformEGLHeadless();
#endif
#elif defined(WIN32)
return new PlatformWGL();
#elif defined(__EMSCRIPTEN__)
return new PlatformWebGL();
#else
return nullptr;
#endif
#else
return nullptr;
#endif
bool Platform::pumpEvents() noexcept {
return false;
}
// destroys a Platform created by create()
void DefaultPlatform::destroy(DefaultPlatform** platform) noexcept {
delete *platform;
*platform = nullptr;
}
DefaultPlatform::~DefaultPlatform() noexcept = default;
} // namespace filament::backend

View File

@@ -0,0 +1,182 @@
/*
* 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 <private/backend/PlatformFactory.h>
#include <utils/Systrace.h>
#include <utils/debug.h>
#if defined(__ANDROID__)
#include <sys/system_properties.h>
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
#include "backend/platforms/PlatformEGLAndroid.h"
#endif
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkAndroid.h"
#endif
#elif defined(IOS)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
#include "backend/platforms/PlatformCocoaTouchGL.h"
#endif
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkCocoaTouch.h"
#endif
#elif defined(__APPLE__)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
#include <backend/platforms/PlatformCocoaGL.h>
#endif
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkCocoa.h"
#endif
#elif defined(__linux__)
#if defined(FILAMENT_SUPPORTS_GGP)
#include "vulkan/PlatformVkLinuxGGP.h"
#elif defined(FILAMENT_SUPPORTS_WAYLAND)
#if defined (FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkLinuxWayland.h"
#endif
#elif defined(FILAMENT_SUPPORTS_X11)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
#include "backend/platforms/PlatformGLX.h"
#endif
#if defined (FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkLinuxX11.h"
#endif
#elif defined(FILAMENT_SUPPORTS_EGL_ON_LINUX)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
#include "backend/platforms/PlatformEGLHeadless.h"
#endif
#endif
#elif defined(WIN32)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
#include "backend/platforms/PlatformWGL.h"
#endif
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkWindows.h"
#endif
#elif defined(__EMSCRIPTEN__)
#include "backend/platforms/PlatformWebGL.h"
#endif
#if defined (FILAMENT_SUPPORTS_METAL)
namespace filament::backend {
filament::backend::Platform* createDefaultMetalPlatform();
}
#endif
#include "noop/PlatformNoop.h"
namespace filament::backend {
// Creates the platform-specific Platform object. The caller takes ownership and is
// responsible for destroying it. Initialization of the backend API is deferred until
// createDriver(). The passed-in backend hint is replaced with the resolved backend.
Platform* PlatformFactory::create(Backend* backend) noexcept {
SYSTRACE_CALL();
assert_invariant(backend);
#if defined(__ANDROID__)
char scratch[PROP_VALUE_MAX + 1];
int length = __system_property_get("debug.filament.backend", scratch);
if (length > 0) {
*backend = Backend(atoi(scratch));
}
#endif
if (*backend == Backend::DEFAULT) {
#if defined(__EMSCRIPTEN__)
*backend = Backend::OPENGL;
#elif defined(__ANDROID__)
*backend = Backend::OPENGL;
#elif defined(IOS) || defined(__APPLE__)
*backend = Backend::METAL;
#elif defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
*backend = Backend::VULKAN;
#else
* backend = Backend::OPENGL;
#endif
}
if (*backend == Backend::NOOP) {
return new PlatformNoop();
}
if (*backend == Backend::VULKAN) {
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
#if defined(__ANDROID__)
return new PlatformVkAndroid();
#elif defined(IOS)
return new PlatformVkCocoaTouch();
#elif defined(__linux__)
#if defined(FILAMENT_SUPPORTS_GGP)
return new PlatformVkLinuxGGP();
#elif defined(FILAMENT_SUPPORTS_WAYLAND)
return new PlatformVkLinuxWayland();
#elif defined(FILAMENT_SUPPORTS_X11)
return new PlatformVkLinuxX11();
#endif
#elif defined(__APPLE__)
return new PlatformVkCocoa();
#elif defined(WIN32)
return new PlatformVkWindows();
#else
return nullptr;
#endif
#else
return nullptr;
#endif
}
if (*backend == Backend::METAL) {
#if defined(FILAMENT_SUPPORTS_METAL)
return createDefaultMetalPlatform();
#else
return nullptr;
#endif
}
assert_invariant(*backend == Backend::OPENGL);
#if defined(FILAMENT_SUPPORTS_OPENGL)
#if defined(FILAMENT_USE_EXTERNAL_GLES3) || defined(FILAMENT_USE_SWIFTSHADER)
// Swiftshader OpenGLES support is deprecated and incomplete
return nullptr;
#elif defined(__ANDROID__)
return new PlatformEGLAndroid();
#elif defined(IOS)
return new PlatformCocoaTouchGL();
#elif defined(__APPLE__)
return new PlatformCocoaGL();
#elif defined(__linux__)
#if defined(FILAMENT_SUPPORTS_X11)
return new PlatformGLX();
#elif defined(FILAMENT_SUPPORTS_EGL_ON_LINUX)
return new PlatformEGLHeadless();
#endif
#elif defined(WIN32)
return new PlatformWGL();
#elif defined(__EMSCRIPTEN__)
return new PlatformWebGL();
#else
return nullptr;
#endif
#else
return nullptr;
#endif
}
// destroys a Platform created by create()
void PlatformFactory::destroy(Platform** platform) noexcept {
delete *platform;
*platform = nullptr;
}
} // namespace filament::backend

View File

@@ -68,7 +68,7 @@ public:
}
};
void blit(id<MTLCommandBuffer> cmdBuffer, const BlitArgs& args);
void blit(id<MTLCommandBuffer> cmdBuffer, const BlitArgs& args, const char* label);
/**
* Free resources. Should be called at least once per process when no further calls to blit will
@@ -112,11 +112,12 @@ private:
};
void blitFastPath(id<MTLCommandBuffer> cmdBuffer, bool& blitColor, bool& blitDepth,
const BlitArgs& args);
const BlitArgs& args, const char* label);
void blitSlowPath(id<MTLCommandBuffer> cmdBuffer, bool& blitColor, bool& blitDepth,
const BlitArgs& args);
const BlitArgs& args, const char* label);
void blitDepthPlane(id<MTLCommandBuffer> cmdBuffer, bool blitColor, bool blitDepth,
const BlitArgs& args, uint32_t depthPlaneSource, uint32_t depthPlaneDest);
const BlitArgs& args, uint32_t depthPlaneSource, uint32_t depthPlaneDest,
const char* label);
id<MTLTexture> createIntermediateTexture(id<MTLTexture> t, MTLSize size);
id<MTLFunction> compileFragmentFunction(BlitFunctionKey key);
id<MTLFunction> getBlitVertexFunction();

View File

@@ -143,7 +143,7 @@ MetalBlitter::MetalBlitter(MetalContext& context) noexcept : mContext(context) {
#define MTLSizeEqual(a, b) (a.width == b.width && a.height == b.height && a.depth == b.depth)
void MetalBlitter::blit(id<MTLCommandBuffer> cmdBuffer, const BlitArgs& args) {
void MetalBlitter::blit(id<MTLCommandBuffer> cmdBuffer, const BlitArgs& args, const char* label) {
bool blitColor = args.blitColor();
bool blitDepth = args.blitDepth();
@@ -164,7 +164,7 @@ void MetalBlitter::blit(id<MTLCommandBuffer> cmdBuffer, const BlitArgs& args) {
// Determine if the blit for color or depth are eligible to use a MTLBlitCommandEncoder.
// blitColor and / or blitDepth are set to false upon success, to indicate that no more work is
// necessary for that attachment.
blitFastPath(cmdBuffer, blitColor, blitDepth, args);
blitFastPath(cmdBuffer, blitColor, blitDepth, args, label);
if (!blitColor && !blitDepth) {
return;
@@ -207,21 +207,22 @@ void MetalBlitter::blit(id<MTLCommandBuffer> cmdBuffer, const BlitArgs& args) {
slowBlit.destination.region = finalBlit.source.region = sourceRegionNoOffset;
}
blitSlowPath(cmdBuffer, blitColor, blitDepth, slowBlit);
blitSlowPath(cmdBuffer, blitColor, blitDepth, slowBlit, label);
bool finalBlitColor = intermediateColor != nil;
bool finalBlitDepth = intermediateDepth != nil;
blitFastPath(cmdBuffer, finalBlitColor, finalBlitDepth, finalBlit);
blitFastPath(cmdBuffer, finalBlitColor, finalBlitDepth, finalBlit, label);
}
void MetalBlitter::blitFastPath(id<MTLCommandBuffer> cmdBuffer, bool& blitColor, bool& blitDepth,
const BlitArgs& args) {
const BlitArgs& args, const char* label) {
if (blitColor) {
if (args.source.color.sampleCount == args.destination.color.sampleCount &&
args.source.color.pixelFormat == args.destination.color.pixelFormat &&
MTLSizeEqual(args.source.region.size, args.destination.region.size)) {
id<MTLBlitCommandEncoder> blitEncoder = [cmdBuffer blitCommandEncoder];
blitEncoder.label = @(label);
[blitEncoder copyFromTexture:args.source.color
sourceSlice:args.source.slice
sourceLevel:args.source.level
@@ -243,6 +244,7 @@ void MetalBlitter::blitFastPath(id<MTLCommandBuffer> cmdBuffer, bool& blitColor,
MTLSizeEqual(args.source.region.size, args.destination.region.size)) {
id<MTLBlitCommandEncoder> blitEncoder = [cmdBuffer blitCommandEncoder];
blitEncoder.label = @(label);
[blitEncoder copyFromTexture:args.source.depth
sourceSlice:args.source.slice
sourceLevel:args.source.level
@@ -260,7 +262,7 @@ void MetalBlitter::blitFastPath(id<MTLCommandBuffer> cmdBuffer, bool& blitColor,
}
void MetalBlitter::blitSlowPath(id<MTLCommandBuffer> cmdBuffer, bool& blitColor, bool& blitDepth,
const BlitArgs& args) {
const BlitArgs& args, const char* label) {
uint32_t depthPlaneSource = args.source.region.origin.z;
uint32_t depthPlaneDest = args.destination.region.origin.z;
@@ -268,7 +270,8 @@ void MetalBlitter::blitSlowPath(id<MTLCommandBuffer> cmdBuffer, bool& blitColor,
assert_invariant(args.source.region.size.depth == args.destination.region.size.depth);
uint32_t depthPlaneCount = args.source.region.size.depth;
for (NSUInteger d = 0; d < depthPlaneCount; d++) {
blitDepthPlane(cmdBuffer, blitColor, blitDepth, args, depthPlaneSource++, depthPlaneDest++);
blitDepthPlane(cmdBuffer, blitColor, blitDepth, args, depthPlaneSource++, depthPlaneDest++,
label);
}
blitColor = false;
@@ -276,7 +279,8 @@ void MetalBlitter::blitSlowPath(id<MTLCommandBuffer> cmdBuffer, bool& blitColor,
}
void MetalBlitter::blitDepthPlane(id<MTLCommandBuffer> cmdBuffer, bool blitColor, bool blitDepth,
const BlitArgs& args, uint32_t depthPlaneSource, uint32_t depthPlaneDest) {
const BlitArgs& args, uint32_t depthPlaneSource, uint32_t depthPlaneDest,
const char* label) {
MTLRenderPassDescriptor* descriptor = [MTLRenderPassDescriptor renderPassDescriptor];
if (blitColor) {
@@ -288,7 +292,7 @@ void MetalBlitter::blitDepthPlane(id<MTLCommandBuffer> cmdBuffer, bool blitColor
}
id<MTLRenderCommandEncoder> encoder = [cmdBuffer renderCommandEncoderWithDescriptor:descriptor];
encoder.label = @"Blit";
encoder.label = @(label);
BlitFunctionKey key;
key.blitColor = blitColor;

View File

@@ -69,6 +69,7 @@ void MetalBuffer::copyIntoBuffer(void* src, size_t size, size_t byteOffset) {
// Encode a blit from the staging buffer into the private GPU buffer.
id<MTLCommandBuffer> cmdBuffer = getPendingCommandBuffer(&mContext);
id<MTLBlitCommandEncoder> blitEncoder = [cmdBuffer blitCommandEncoder];
blitEncoder.label = @"Buffer upload blit";
[blitEncoder copyFromBuffer:staging->buffer
sourceOffset:0
toBuffer:mBuffer

View File

@@ -27,7 +27,7 @@
#include "MetalState.h"
#include "MetalTimerQuery.h"
#include "private/backend/MetalPlatform.h"
#include "MetalPlatform.h"
#include <CoreVideo/CVMetalTexture.h>
#include <CoreVideo/CVPixelBuffer.h>
@@ -706,6 +706,11 @@ bool MetalDriver::isAutoDepthResolveSupported() {
return mContext->supportsAutoDepthResolve;
}
bool MetalDriver::isSRGBSwapChainSupported() {
// the SWAP_CHAIN_CONFIG_SRGB_COLORSPACE flag is not supported
return false;
}
bool MetalDriver::isWorkaroundNeeded(Workaround workaround) {
switch (workaround) {
case Workaround::SPLIT_EASU:
@@ -803,11 +808,6 @@ void MetalDriver::setupExternalImage(void* image) {
CVPixelBufferRetain(pixelBuffer);
}
void MetalDriver::cancelExternalImage(void* image) {
CVPixelBufferRef pixelBuffer = (CVPixelBufferRef) image;
CVPixelBufferRelease(pixelBuffer);
}
void MetalDriver::setExternalImage(Handle<HwTexture> th, void* image) {
ASSERT_PRECONDITION(!isInRenderPass(mContext),
"setExternalImage must be called outside of a render pass.");
@@ -1263,7 +1263,7 @@ void MetalDriver::readPixels(Handle<HwRenderTarget> src, uint32_t x, uint32_t y,
args.source.color = srcTexture;
args.destination.color = readPixelsTexture;
mContext->blitter->blit(getPendingCommandBuffer(mContext), args);
mContext->blitter->blit(getPendingCommandBuffer(mContext), args, "readPixels blit");
#if !defined(IOS)
// Managed textures on macOS require explicit synchronization between GPU / CPU.
@@ -1347,7 +1347,7 @@ void MetalDriver::blit(TargetBufferFlags buffers,
args.destination.level = dstColorAttachment.level;
args.source.slice = srcColorAttachment.layer;
args.destination.slice = dstColorAttachment.layer;
mContext->blitter->blit(getPendingCommandBuffer(mContext), args);
mContext->blitter->blit(getPendingCommandBuffer(mContext), args, "Color blit");
}
}
@@ -1370,7 +1370,7 @@ void MetalDriver::blit(TargetBufferFlags buffers,
args.destination.level = dstDepthAttachment.level;
args.source.slice = srcDepthAttachment.layer;
args.destination.slice = dstDepthAttachment.layer;
mContext->blitter->blit(getPendingCommandBuffer(mContext), args);
mContext->blitter->blit(getPendingCommandBuffer(mContext), args, "Depth blit");
}
}
}

View File

@@ -391,6 +391,9 @@ MetalProgram::MetalProgram(id<MTLDevice> device, const Program& program) noexcep
id<MTLFunction> function = [library newFunctionWithName:@"main0"
constantValues:constants
error:&error];
if (!program.getName().empty()) {
function.label = @(program.getName().c_str());
}
assert_invariant(function);
*shaderFunctions[i] = function;
}
@@ -720,6 +723,7 @@ void MetalTexture::loadWithCopyBuffer(uint32_t level, uint32_t slice, MTLRegion
stagingBufferSize);
id<MTLCommandBuffer> blitCommandBuffer = getPendingCommandBuffer(&context);
id<MTLBlitCommandEncoder> blitCommandEncoder = [blitCommandBuffer blitCommandEncoder];
blitCommandEncoder.label = @"Texture upload buffer blit";
[blitCommandEncoder copyFromBuffer:entry->buffer
sourceOffset:0
sourceBytesPerRow:shape.bytesPerRow
@@ -792,7 +796,7 @@ void MetalTexture::loadWithBlit(uint32_t level, uint32_t slice, MTLRegion region
args.destination.region = region;
args.source.color = stagingTexture;
args.destination.color = destinationTexture;
context.blitter->blit(getPendingCommandBuffer(&context), args);
context.blitter->blit(getPendingCommandBuffer(&context), args, "Texture upload blit");
}
void MetalTexture::updateLodRange(uint32_t level) {

View File

@@ -22,10 +22,9 @@
#import <Metal/Metal.h>
namespace filament {
namespace backend {
namespace filament::backend {
class MetalPlatform : public DefaultPlatform {
class MetalPlatform final : public Platform {
public:
~MetalPlatform() override;
@@ -60,7 +59,6 @@ private:
};
} // namespace backend
} // namespace filament
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_PRIVATE_METALPLATFORM_H

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "private/backend/MetalPlatform.h"
#include "MetalPlatform.h"
#include "MetalDriverFactory.h"
@@ -22,16 +22,15 @@
#import <Foundation/Foundation.h>
namespace filament {
namespace backend {
namespace filament::backend {
DefaultPlatform* createDefaultMetalPlatform() {
Platform* createDefaultMetalPlatform() {
return new MetalPlatform();
}
MetalPlatform::~MetalPlatform() = default;
Driver* MetalPlatform::createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept {
Driver* MetalPlatform::createDriver(void* /*sharedContext*/, const Platform::DriverConfig& driverConfig) noexcept {
return MetalDriverFactory::create(this, driverConfig);
}
@@ -75,5 +74,4 @@ id<MTLCommandBuffer> MetalPlatform::createAndEnqueueCommandBuffer() noexcept {
return commandBuffer;
}
} // namespace backend
} // namespace filament

View File

@@ -173,7 +173,11 @@ bool NoopDriver::isAutoDepthResolveSupported() {
return true;
}
bool NoopDriver::isWorkaroundNeeded(Workaround workaround) {
bool NoopDriver::isSRGBSwapChainSupported() {
return false;
}
bool NoopDriver::isWorkaroundNeeded(Workaround) {
return false;
}
@@ -224,9 +228,6 @@ void NoopDriver::update3DImage(Handle<HwTexture> th,
void NoopDriver::setupExternalImage(void* image) {
}
void NoopDriver::cancelExternalImage(void* image) {
}
bool NoopDriver::getTimerQueryValue(Handle<HwTimerQuery> tqh, uint64_t* elapsedTime) {
return false;
}

View File

@@ -22,7 +22,7 @@
namespace filament::backend {
class PlatformNoop final : public DefaultPlatform {
class PlatformNoop final : public Platform {
public:
int getOSVersion() const noexcept final { return 0; }

View File

@@ -120,7 +120,12 @@ constexpr inline GLenum getBufferBindingType(BufferObjectBinding bindingType) no
case BufferObjectBinding::UNIFORM:
return GL_UNIFORM_BUFFER;
case BufferObjectBinding::SHADER_STORAGE:
#if defined(GL_VERSION_4_1) || defined(GL_ES_VERSION_3_1)
return GL_SHADER_STORAGE_BUFFER;
#else
utils::panic(__func__, __FILE__, __LINE__, "SHADER_STORAGE not supported");
return 0x90D2; // just to return something
#endif
}
}

View File

@@ -16,6 +16,10 @@
#include "OpenGLContext.h"
#include <backend/platforms/OpenGLPlatform.h>
#include <utility>
// change to true to display all GL extensions in the console on start-up
#define DEBUG_PRINT_EXTENSIONS false
@@ -70,7 +74,9 @@ OpenGLContext::OpenGLContext() noexcept {
constexpr GLint MAX_FRAGMENT_SAMPLER_COUNT = caps3.MAX_FRAGMENT_SAMPLER_COUNT;
if constexpr (BACKEND_OPENGL_VERSION == BACKEND_OPENGL_VERSION_GLES) {
#if defined(GL_ES_VERSION_2_0)
initExtensionsGLES();
#endif
if (state.major == 3) {
assert_invariant(gets.max_texture_image_units >= 16);
assert_invariant(gets.max_combined_texture_image_units >= 32);
@@ -88,8 +94,9 @@ OpenGLContext::OpenGLContext() noexcept {
}
}
} else if constexpr (BACKEND_OPENGL_VERSION == BACKEND_OPENGL_VERSION_GL) {
// OpenGL version
#if defined(GL_VERSION_4_1)
initExtensionsGL();
#endif
if (state.major == 4) {
assert_invariant(state.minor >= 1);
mShaderModel = ShaderModel::DESKTOP;
@@ -268,7 +275,9 @@ OpenGLContext::OpenGLContext() noexcept {
}
#endif
#if !defined(NDEBUG) && defined(GL_KHR_debug)
// in practice KHR_Debug has never been useful, and actually is confusing. We keep this
// only for our own debugging, in case we need it some day.
#if false && !defined(NDEBUG) && defined(GL_KHR_debug)
if (ext.KHR_debug) {
auto cb = +[](GLenum, GLenum type, GLuint, GLenum severity, GLsizei length,
const GLchar* message, const void *) {
@@ -349,6 +358,8 @@ void OpenGLContext::setDefaultState() noexcept {
#endif
}
#if defined(GL_ES_VERSION_2_0)
void OpenGLContext::initExtensionsGLES() noexcept {
const char * const extensions = (const char*)glGetString(GL_EXTENSIONS);
GLUtils::unordered_string_set const exts = GLUtils::split(extensions);
@@ -393,6 +404,10 @@ void OpenGLContext::initExtensionsGLES() noexcept {
}
}
#endif // defined(GL_ES_VERSION_2_0)
#if defined(GL_VERSION_4_1)
void OpenGLContext::initExtensionsGL() noexcept {
GLUtils::unordered_string_set exts;
GLint n = 0;
@@ -416,21 +431,31 @@ void OpenGLContext::initExtensionsGL() noexcept {
ext.EXT_color_buffer_float = true; // Assumes core profile.
ext.EXT_color_buffer_half_float = true; // Assumes core profile.
ext.EXT_debug_marker = exts.has("GL_EXT_debug_marker"sv);
ext.EXT_disjoint_timer_query = true;
ext.EXT_multisampled_render_to_texture = false;
ext.EXT_multisampled_render_to_texture2 = false;
ext.EXT_shader_framebuffer_fetch = exts.has("GL_EXT_shader_framebuffer_fetch"sv);
ext.EXT_texture_compression_bptc = exts.has("GL_EXT_texture_compression_bptc"sv);
ext.EXT_texture_compression_etc2 = exts.has("GL_ARB_ES3_compatibility"sv);
ext.EXT_texture_compression_rgtc = exts.has("GL_EXT_texture_compression_rgtc"sv);
ext.EXT_texture_compression_s3tc = exts.has("GL_EXT_texture_compression_s3tc"sv);
ext.EXT_texture_compression_s3tc_srgb = exts.has("GL_EXT_texture_compression_s3tc_srgb"sv);
ext.EXT_texture_compression_rgtc = exts.has("GL_EXT_texture_compression_rgtc"sv);
ext.EXT_texture_compression_bptc = exts.has("GL_EXT_texture_compression_bptc"sv);
ext.EXT_texture_cube_map_array = true;
ext.EXT_texture_filter_anisotropic = exts.has("GL_EXT_texture_filter_anisotropic"sv);
ext.EXT_texture_sRGB = exts.has("GL_EXT_texture_sRGB"sv);
ext.GOOGLE_cpp_style_line_directive = exts.has("GL_GOOGLE_cpp_style_line_directive"sv);
ext.KHR_debug = major >= 4 && minor >= 3;
ext.KHR_texture_compression_astc_hdr = exts.has("GL_KHR_texture_compression_astc_hdr"sv);
ext.KHR_texture_compression_astc_ldr = exts.has("GL_KHR_texture_compression_astc_ldr"sv);
ext.OES_EGL_image_external_essl3 = exts.has("GL_OES_EGL_image_external_essl3"sv);
ext.OES_EGL_image_external_essl3 = false;
ext.QCOM_tiled_rendering = false;
ext.WEBGL_compressed_texture_etc = false;
ext.WEBGL_compressed_texture_s3tc = false;
ext.WEBGL_compressed_texture_s3tc_srgb = false;
}
#endif // defined(GL_VERSION_4_1)
void OpenGLContext::bindBuffer(GLenum target, GLuint buffer) noexcept {
if (target == GL_ELEMENT_ARRAY_BUFFER) {
constexpr size_t targetIndex = getIndexForBufferTarget(GL_ELEMENT_ARRAY_BUFFER);
@@ -463,13 +488,8 @@ void OpenGLContext::pixelStore(GLenum pname, GLint param) noexcept {
switch (pname) {
case GL_PACK_ALIGNMENT: pcur = &state.pack.alignment; break;
case GL_PACK_ROW_LENGTH: pcur = &state.pack.row_length; break;
case GL_PACK_SKIP_PIXELS: pcur = &state.pack.skip_pixels; break; // convenience
case GL_PACK_SKIP_ROWS: pcur = &state.pack.skip_row; break; // convenience
case GL_UNPACK_ALIGNMENT: pcur = &state.unpack.alignment; break;
case GL_UNPACK_ROW_LENGTH: pcur = &state.unpack.row_length; break;
case GL_UNPACK_SKIP_PIXELS: pcur = &state.unpack.skip_pixels; break; // convenience
case GL_UNPACK_SKIP_ROWS: pcur = &state.unpack.skip_row; break; // convenience
default:
goto default_case;
}
@@ -616,12 +636,10 @@ void OpenGLContext::resetState() noexcept {
GLenum const bufferTargets[] = {
GL_UNIFORM_BUFFER,
GL_TRANSFORM_FEEDBACK_BUFFER,
#if !defined(__EMSCRIPTEN__)
#if !defined(__EMSCRIPTEN__) && (defined(GL_VERSION_4_1) || defined(GL_ES_VERSION_3_1))
GL_SHADER_STORAGE_BUFFER,
#endif
GL_ARRAY_BUFFER,
GL_COPY_READ_BUFFER,
GL_COPY_WRITE_BUFFER,
GL_ELEMENT_ARRAY_BUFFER,
GL_PIXEL_PACK_BUFFER,
GL_PIXEL_UNPACK_BUFFER,
@@ -644,23 +662,30 @@ void OpenGLContext::resetState() noexcept {
// Reset state.textures to its default state to avoid the complexity and error-prone
// nature of resetting the GL state to its existing state
state.textures = {};
const GLuint textureTargets[] = {
GL_TEXTURE_2D,
GL_TEXTURE_2D_ARRAY,
GL_TEXTURE_CUBE_MAP,
GL_TEXTURE_3D,
const std::pair<GLuint, bool> textureTargets[] = {
{ GL_TEXTURE_2D, true },
{ GL_TEXTURE_2D_ARRAY, true },
{ GL_TEXTURE_CUBE_MAP, true },
{ GL_TEXTURE_3D, true },
#if !defined(__EMSCRIPTEN__)
GL_TEXTURE_2D_MULTISAMPLE,
GL_TEXTURE_EXTERNAL_OES,
GL_TEXTURE_CUBE_MAP_ARRAY,
#if defined(GL_VERSION_4_1) || defined(GL_ES_VERSION_3_1)
{ GL_TEXTURE_2D_MULTISAMPLE, true },
#endif
#if defined(GL_OES_EGL_image_external)
{ GL_TEXTURE_EXTERNAL_OES, ext.OES_EGL_image_external_essl3 },
#endif
#if defined(GL_VERSION_4_1) || defined(GL_EXT_texture_cube_map_array)
{ GL_TEXTURE_CUBE_MAP_ARRAY, ext.EXT_texture_cube_map_array },
#endif
#endif
};
for (GLint unit = 0; unit < gets.max_combined_texture_image_units; ++unit) {
glActiveTexture(GL_TEXTURE0 + unit);
glBindSampler(unit, 0);
for (auto const target : textureTargets) {
glBindTexture(target, 0);
for (auto [target, available] : textureTargets) {
if (available) {
glBindTexture(target, 0);
}
}
}
glActiveTexture(GL_TEXTURE0 + state.textures.active);
@@ -668,14 +693,10 @@ void OpenGLContext::resetState() noexcept {
// state.unpack
glPixelStorei(GL_UNPACK_ALIGNMENT, state.unpack.alignment);
glPixelStorei(GL_UNPACK_ROW_LENGTH, state.unpack.row_length);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, state.unpack.skip_pixels);
glPixelStorei(GL_UNPACK_SKIP_ROWS, state.unpack.skip_row);
// state.pack
glPixelStorei(GL_PACK_ALIGNMENT, state.pack.alignment);
glPixelStorei(GL_PACK_ROW_LENGTH, state.pack.row_length);
glPixelStorei(GL_PACK_SKIP_PIXELS, state.pack.skip_pixels);
glPixelStorei(GL_PACK_SKIP_ROWS, state.pack.skip_row);
glPixelStorei(GL_PACK_ROW_LENGTH, 0); // we rely on GL_PACK_ROW_LENGTH being zero
// state.window
glScissor(
@@ -694,4 +715,30 @@ void OpenGLContext::resetState() noexcept {
}
OpenGLContext::FenceSync OpenGLContext::createFenceSync(
OpenGLPlatform&) noexcept {
auto sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
CHECK_GL_ERROR(utils::slog.e)
return { .sync = sync };
}
void OpenGLContext::destroyFenceSync(
OpenGLPlatform&, FenceSync sync) noexcept {
glDeleteSync(sync.sync);
CHECK_GL_ERROR(utils::slog.e)
}
OpenGLContext::FenceSync::Status OpenGLContext::clientWaitSync(
OpenGLPlatform&, FenceSync sync) const noexcept {
GLenum const status = glClientWaitSync(sync.sync, 0, 0u);
CHECK_GL_ERROR(utils::slog.e)
using Status = OpenGLContext::FenceSync::Status;
switch (status) {
case GL_ALREADY_SIGNALED: return Status::ALREADY_SIGNALED;
case GL_TIMEOUT_EXPIRED: return Status::TIMEOUT_EXPIRED;
case GL_CONDITION_SATISFIED: return Status::CONDITION_SATISFIED;
default: return Status::FAILURE;
}
}
} // namesapce filament

View File

@@ -33,6 +33,8 @@
namespace filament::backend {
class OpenGLPlatform;
class OpenGLContext {
public:
static constexpr const size_t MAX_TEXTURE_UNIT_COUNT = MAX_SAMPLER_COUNT;
@@ -110,9 +112,6 @@ public:
GLenum sfailBack, GLenum dpfailBack, GLenum dppassBack) noexcept;
inline void stencilMaskSeparate(GLuint maskFront, GLuint maskBack) noexcept;
inline void polygonOffset(GLfloat factor, GLfloat units) noexcept;
inline void beginQuery(GLenum target, GLuint query) noexcept;
inline void endQuery(GLenum target) noexcept;
inline GLuint getQuery(GLenum target) const noexcept;
inline void setScissor(GLint left, GLint bottom, GLsizei width, GLsizei height) noexcept;
inline void viewport(GLint left, GLint bottom, GLsizei width, GLsizei height) noexcept;
@@ -121,6 +120,26 @@ public:
void deleteBuffers(GLsizei n, const GLuint* buffers, GLenum target) noexcept;
void deleteVertexArrays(GLsizei n, const GLuint* arrays) noexcept;
// we abstract GL's sync because it's not available in ES2, but we can use EGL's sync
// instead, if available.
struct FenceSync {
enum class Status {
ALREADY_SIGNALED,
TIMEOUT_EXPIRED,
CONDITION_SATISFIED,
FAILURE
};
union {
void* fence;
GLsync sync;
};
};
FenceSync createFenceSync(OpenGLPlatform& platform) noexcept;
void destroyFenceSync(OpenGLPlatform& platform, FenceSync sync) noexcept;
FenceSync::Status clientWaitSync(OpenGLPlatform& platform, FenceSync sync) const noexcept;
// glGet*() values
struct {
GLfloat max_anisotropy;
@@ -149,21 +168,21 @@ public:
bool EXT_color_buffer_half_float;
bool EXT_debug_marker;
bool EXT_disjoint_timer_query;
bool EXT_multisampled_render_to_texture;
bool EXT_multisampled_render_to_texture2;
bool EXT_multisampled_render_to_texture;
bool EXT_shader_framebuffer_fetch;
bool KHR_texture_compression_astc_hdr;
bool KHR_texture_compression_astc_ldr;
bool EXT_texture_compression_bptc;
bool EXT_texture_compression_etc2;
bool EXT_texture_compression_rgtc;
bool EXT_texture_compression_s3tc;
bool EXT_texture_compression_s3tc_srgb;
bool EXT_texture_compression_rgtc;
bool EXT_texture_compression_bptc;
bool EXT_texture_cube_map_array;
bool EXT_texture_filter_anisotropic;
bool EXT_texture_sRGB;
bool GOOGLE_cpp_style_line_directive;
bool KHR_debug;
bool KHR_texture_compression_astc_hdr;
bool KHR_texture_compression_astc_ldr;
bool OES_EGL_image_external_essl3;
bool QCOM_tiled_rendering;
bool WEBGL_compressed_texture_etc;
@@ -315,8 +334,8 @@ public:
GLintptr offset = 0;
GLsizeiptr size = 0;
} buffers[MAX_BUFFER_BINDINGS];
} targets[2]; // there are only 2 indexed buffer target (uniform and transform feedback)
GLuint genericBinding[9] = { 0 };
} targets[3]; // there are only 3 indexed buffer targets
GLuint genericBinding[7] = {};
} buffers;
struct {
@@ -332,15 +351,10 @@ public:
struct {
GLint row_length = 0;
GLint alignment = 4;
GLint skip_pixels = 0;
GLint skip_row = 0;
} unpack;
struct {
GLint row_length = 0;
GLint alignment = 4;
GLint skip_pixels = 0;
GLint skip_row = 0;
} pack;
struct {
@@ -348,10 +362,6 @@ public:
vec4gli viewport { 0 };
vec2glf depthRange { 0.0f, 1.0f };
} window;
struct {
GLuint timer = -1u;
} queries;
} state;
private:
@@ -403,8 +413,12 @@ private:
RenderPrimitive mDefaultVAO;
// this is chosen to minimize code size
#if defined(GL_ES_VERSION_2_0)
void initExtensionsGLES() noexcept;
#endif
#if defined(GL_VERSION_4_1)
void initExtensionsGL() noexcept;
#endif
template <typename T, typename F>
static inline void update_state(T& state, T const& expected, F functor, bool force = false) noexcept {
@@ -429,7 +443,9 @@ constexpr size_t OpenGLContext::getIndexForTextureTarget(GLuint target) noexcept
case GL_TEXTURE_2D: return 0;
case GL_TEXTURE_2D_ARRAY: return 1;
case GL_TEXTURE_CUBE_MAP: return 2;
#if defined(GL_VERSION_4_1) || defined(GL_ES_VERSION_3_1)
case GL_TEXTURE_2D_MULTISAMPLE: return 3;
#endif
case GL_TEXTURE_EXTERNAL_OES: return 4;
case GL_TEXTURE_3D: return 5;
case GL_TEXTURE_CUBE_MAP_ARRAY: return 6;
@@ -450,17 +466,15 @@ constexpr size_t OpenGLContext::getIndexForCap(GLenum cap) noexcept { //NOLINT
case GL_SAMPLE_ALPHA_TO_COVERAGE: index = 6; break;
case GL_SAMPLE_COVERAGE: index = 7; break;
case GL_POLYGON_OFFSET_FILL: index = 8; break;
case GL_PRIMITIVE_RESTART_FIXED_INDEX: index = 9; break;
case GL_RASTERIZER_DISCARD: index = 10; break;
#ifdef GL_ARB_seamless_cube_map
case GL_TEXTURE_CUBE_MAP_SEAMLESS: index = 11; break;
case GL_TEXTURE_CUBE_MAP_SEAMLESS: index = 9; break;
#endif
#if BACKEND_OPENGL_VERSION == BACKEND_OPENGL_VERSION_GL
case GL_PROGRAM_POINT_SIZE: index = 12; break;
case GL_PROGRAM_POINT_SIZE: index = 10; break;
#endif
default: index = 13; break; // should never happen
default: break;
}
assert_invariant(index < 13 && index < state.enables.caps.size());
assert_invariant(index < state.enables.caps.size());
return index;
}
@@ -470,15 +484,14 @@ constexpr size_t OpenGLContext::getIndexForBufferTarget(GLenum target) noexcept
// The indexed buffers MUST be first in this list (those usable with bindBufferRange)
case GL_UNIFORM_BUFFER: index = 0; break;
case GL_TRANSFORM_FEEDBACK_BUFFER: index = 1; break;
#if defined(GL_VERSION_4_1) || defined(GL_ES_VERSION_3_1)
case GL_SHADER_STORAGE_BUFFER: index = 2; break;
#endif
case GL_ARRAY_BUFFER: index = 3; break;
case GL_COPY_READ_BUFFER: index = 4; break;
case GL_COPY_WRITE_BUFFER: index = 5; break;
case GL_ELEMENT_ARRAY_BUFFER: index = 6; break;
case GL_PIXEL_PACK_BUFFER: index = 7; break;
case GL_PIXEL_UNPACK_BUFFER: index = 8; break;
default: index = 9; break; // should never happen
case GL_ELEMENT_ARRAY_BUFFER: index = 4; break;
case GL_PIXEL_PACK_BUFFER: index = 5; break;
case GL_PIXEL_UNPACK_BUFFER: index = 6; break;
default: break;
}
assert_invariant(index < sizeof(state.buffers.genericBinding)/sizeof(state.buffers.genericBinding[0])); // NOLINT(misc-redundant-expression)
return index;
@@ -501,21 +514,21 @@ void OpenGLContext::bindSampler(GLuint unit, GLuint sampler) noexcept {
}
void OpenGLContext::setScissor(GLint left, GLint bottom, GLsizei width, GLsizei height) noexcept {
vec4gli scissor(left, bottom, width, height);
vec4gli const scissor(left, bottom, width, height);
update_state(state.window.scissor, scissor, [&]() {
glScissor(left, bottom, width, height);
});
}
void OpenGLContext::viewport(GLint left, GLint bottom, GLsizei width, GLsizei height) noexcept {
vec4gli viewport(left, bottom, width, height);
vec4gli const viewport(left, bottom, width, height);
update_state(state.window.viewport, viewport, [&]() {
glViewport(left, bottom, width, height);
});
}
void OpenGLContext::depthRange(GLclampf near, GLclampf far) noexcept {
vec2glf depthRange(near, far);
vec2glf const depthRange(near, far);
update_state(state.window.depthRange, depthRange, [&]() {
glDepthRangef(near, far);
});
@@ -526,7 +539,7 @@ void OpenGLContext::bindVertexArray(RenderPrimitive const* p) noexcept {
update_state(state.vao.p, vao, [&]() {
glBindVertexArray(vao->vao);
// update GL_ELEMENT_ARRAY_BUFFER, which is updated by glBindVertexArray
size_t targetIndex = getIndexForBufferTarget(GL_ELEMENT_ARRAY_BUFFER);
size_t const targetIndex = getIndexForBufferTarget(GL_ELEMENT_ARRAY_BUFFER);
state.buffers.genericBinding[targetIndex] = vao->elementArray;
if (UTILS_UNLIKELY(bugs.vao_doesnt_store_element_array_buffer_binding)) {
// This shouldn't be needed, but it looks like some drivers don't do the implicit
@@ -538,8 +551,10 @@ void OpenGLContext::bindVertexArray(RenderPrimitive const* p) noexcept {
void OpenGLContext::bindBufferRange(GLenum target, GLuint index, GLuint buffer,
GLintptr offset, GLsizeiptr size) noexcept {
size_t targetIndex = getIndexForBufferTarget(target);
assert_invariant(targetIndex <= 2); // validity check
size_t const targetIndex = getIndexForBufferTarget(target);
// validity check
assert_invariant(targetIndex < sizeof(state.buffers.targets) / sizeof(*state.buffers.targets));
// this ALSO sets the generic binding
if ( state.buffers.targets[targetIndex].buffers[index].name != buffer
@@ -616,7 +631,7 @@ void OpenGLContext::disableVertexAttribArray(GLuint index) noexcept {
}
void OpenGLContext::enable(GLenum cap) noexcept {
size_t index = getIndexForCap(cap);
size_t const index = getIndexForCap(cap);
if (UTILS_UNLIKELY(!state.enables.caps[index])) {
state.enables.caps.set(index);
glEnable(cap);
@@ -624,7 +639,7 @@ void OpenGLContext::enable(GLenum cap) noexcept {
}
void OpenGLContext::disable(GLenum cap) noexcept {
size_t index = getIndexForCap(cap);
size_t const index = getIndexForCap(cap);
if (UTILS_UNLIKELY(state.enables.caps[index])) {
state.enables.caps.unset(index);
glDisable(cap);
@@ -723,41 +738,6 @@ void OpenGLContext::polygonOffset(GLfloat factor, GLfloat units) noexcept {
});
}
void OpenGLContext::beginQuery(GLenum target, GLuint query) noexcept {
switch (target) {
case GL_TIME_ELAPSED:
if (state.queries.timer != -1u) {
// this is an error
break;
}
state.queries.timer = query;
break;
default:
return;
}
glBeginQuery(target, query);
}
void OpenGLContext::endQuery(GLenum target) noexcept {
switch (target) {
case GL_TIME_ELAPSED:
state.queries.timer = -1u;
break;
default:
return;
}
glEndQuery(target);
}
GLuint OpenGLContext::getQuery(GLenum target) const noexcept {
switch (target) {
case GL_TIME_ELAPSED:
return state.queries.timer;
default:
return 0;
}
}
} // namespace filament
#endif //TNT_FILAMENT_BACKEND_OPENGLCONTEXT_H

View File

@@ -17,14 +17,14 @@
#include "OpenGLDriver.h"
#include "private/backend/DriverApi.h"
#include "private/backend/OpenGLPlatform.h"
#include "CommandStreamDispatcher.h"
#include "OpenGLContext.h"
#include "OpenGLDriverFactory.h"
#include "OpenGLProgram.h"
#include "OpenGLTimerQuery.h"
#include "OpenGLContext.h"
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/SamplerDescriptor.h>
#include <utils/compiler.h>
@@ -69,7 +69,9 @@ using namespace utils;
namespace filament::backend {
Driver* OpenGLDriverFactory::create(
OpenGLPlatform* const platform, void* const sharedGLContext, const Platform::DriverConfig& driverConfig) noexcept {
OpenGLPlatform* const platform,
void* const sharedGLContext,
const Platform::DriverConfig& driverConfig) noexcept {
return OpenGLDriver::create(platform, sharedGLContext, driverConfig);
}
@@ -171,12 +173,16 @@ OpenGLDriver::OpenGLDriver(OpenGLPlatform* platform, const Platform::DriverConfi
// set a reasonable default value for our stream array
mTexturesWithStreamsAttached.reserve(8);
mStreamsWithPendingAquiredImage.reserve(8);
mStreamsWithPendingAcquiredImage.reserve(8);
#ifndef NDEBUG
slog.i << "OS version: " << mPlatform.getOSVersion() << io::endl;
#endif
// Timer queries are core in GL 3.3, otherwise we need EXT_disjoint_timer_query
// iOS headers don't define GL_EXT_disjoint_timer_query, so make absolutely sure
// we won't use it.
#if defined(GL_VERSION_3_3) || defined(GL_EXT_disjoint_timer_query)
if (mContext.ext.EXT_disjoint_timer_query ||
BACKEND_OPENGL_VERSION == BACKEND_OPENGL_VERSION_GL) {
// timer queries are available
@@ -187,7 +193,9 @@ OpenGLDriver::OpenGLDriver(OpenGLPlatform* platform, const Platform::DriverConfi
mTimerQueryImpl = new TimerQueryNative(mContext);
}
mFrameTimeSupported = true;
} else if (mPlatform.canCreateFence()) {
} else
#endif
if (mPlatform.canCreateFence()) {
// no timer queries, but we can use fences
mTimerQueryImpl = new OpenGLTimerQueryFence(mPlatform);
mFrameTimeSupported = true;
@@ -537,6 +545,7 @@ void OpenGLDriver::textureStorage(OpenGLDriver::GLTexture* t,
GLsizei(width), GLsizei(height), GLsizei(depth) * 6);
break;
}
#if defined(GL_VERSION_4_1) || defined(GL_ES_VERSION_3_1)
case GL_TEXTURE_2D_MULTISAMPLE:
if constexpr (TEXTURE_2D_MULTISAMPLE_SUPPORTED) {
// NOTE: if there is a mix of texture and renderbuffers, "fixed_sample_locations" must be true
@@ -554,6 +563,7 @@ void OpenGLDriver::textureStorage(OpenGLDriver::GLTexture* t,
PANIC_LOG("GL_TEXTURE_2D_MULTISAMPLE is not supported");
}
break;
#endif
default: // cannot happen
break;
}
@@ -574,7 +584,17 @@ void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
GLTexture* t = construct<GLTexture>(th, target, levels, samples, w, h, depth, format, usage);
if (UTILS_LIKELY(usage & TextureUsage::SAMPLEABLE)) {
if (UTILS_UNLIKELY(t->target == SamplerType::SAMPLER_EXTERNAL)) {
mPlatform.createExternalImageTexture(t);
t->externalTexture = mPlatform.createExternalImageTexture();
if (t->externalTexture) {
t->gl.target = t->externalTexture->target;
t->gl.id = t->externalTexture->id;
t->gl.targetIndex = (uint8_t)OpenGLContext::getIndexForTextureTarget(t->gl.target);
// internalFormat actually depends on the external image, but it doesn't matter
// because it's not used anywhere for anything important.
t->gl.internalFormat = getInternalFormat(format);
t->gl.baseLevel = 0;
t->gl.maxLevel = 0;
}
} else {
glGenTextures(1, &t->gl.id);
@@ -611,6 +631,7 @@ void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
if (t->samples > 1) {
// Note: we can't be here in practice because filament's user API doesn't
// allow the creation of multi-sampled textures.
#if defined(GL_VERSION_4_1) || defined(GL_ES_VERSION_3_1)
if (gl.features.multisample_texture) {
// multi-sample texture on GL 3.2 / GLES 3.1 and above
t->gl.target = GL_TEXTURE_2D_MULTISAMPLE;
@@ -619,6 +640,7 @@ void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
} else {
// Turn off multi-sampling for that texture. It's just not supported.
}
#endif
}
textureStorage(t, w, h, depth);
}
@@ -711,6 +733,7 @@ void OpenGLDriver::importTextureR(Handle<HwTexture> th, intptr_t id,
if (t->samples > 1) {
// Note: we can't be here in practice because filament's user API doesn't
// allow the creation of multi-sampled textures.
#if defined(GL_VERSION_4_1) || defined(GL_ES_VERSION_3_1)
if (gl.features.multisample_texture) {
// multi-sample texture on GL 3.2 / GLES 3.1 and above
t->gl.target = GL_TEXTURE_2D_MULTISAMPLE;
@@ -718,6 +741,7 @@ void OpenGLDriver::importTextureR(Handle<HwTexture> th, intptr_t id,
} else {
// Turn off multi-sampling for that texture. It's just not supported.
}
#endif
}
CHECK_GL_ERROR(utils::slog.e)
@@ -790,6 +814,7 @@ void OpenGLDriver::framebufferTexture(TargetBufferInfo const& binfo,
GLTexture* t = handle_cast<GLTexture*>(binfo.handle);
assert_invariant(t);
assert_invariant(t->target != SamplerType::SAMPLER_EXTERNAL);
assert_invariant(rt->width <= valueForLevel(binfo.level, t->width) &&
rt->height <= valueForLevel(binfo.level, t->height));
@@ -897,7 +922,9 @@ void OpenGLDriver::framebufferTexture(TargetBufferInfo const& binfo,
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
case GL_TEXTURE_2D:
#if defined(GL_VERSION_4_1) || defined(GL_ES_VERSION_3_1)
case GL_TEXTURE_2D_MULTISAMPLE:
#endif
if (any(t->usage & TextureUsage::SAMPLEABLE)) {
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment,
target, t->gl.id, binfo.level);
@@ -1063,10 +1090,7 @@ void OpenGLDriver::createDefaultRenderTargetR(
construct<GLRenderTarget>(rth, 0, 0); // FIXME: we don't know the width/height
uint32_t framebuffer = 0;
uint32_t colorbuffer = 0;
uint32_t depthbuffer = 0;
mPlatform.createDefaultRenderTarget(framebuffer, colorbuffer, depthbuffer);
uint32_t framebuffer = mPlatform.createDefaultRenderTarget();
GLRenderTarget* rt = handle_cast<GLRenderTarget*>(rth);
rt->gl.fbo = framebuffer;
@@ -1128,21 +1152,26 @@ void OpenGLDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
rt->gl.samples = samples;
rt->targets = targets;
UTILS_UNUSED_IN_RELEASE math::vec2<uint32_t> tmin = {std::numeric_limits<uint32_t>::max()};
UTILS_UNUSED_IN_RELEASE math::vec2<uint32_t> tmax = {0};
UTILS_UNUSED_IN_RELEASE math::vec2<uint32_t> tmin = { std::numeric_limits<uint32_t>::max() };
UTILS_UNUSED_IN_RELEASE math::vec2<uint32_t> tmax = { 0 };
auto checkDimensions = [&tmin, &tmax](GLTexture* t, uint8_t level) {
const auto twidth = std::max(1u, t->width >> level);
const auto theight = std::max(1u, t->height >> level);
tmin = { std::min(tmin.x, twidth), std::min(tmin.y, theight) };
tmax = { std::max(tmax.x, twidth), std::max(tmax.y, theight) };
};
if (any(targets & TargetBufferFlags::COLOR_ALL)) {
GLenum bufs[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT] = { GL_NONE };
const size_t maxDrawBuffers = getMaxDrawBuffers();
for (size_t i = 0; i < maxDrawBuffers; i++) {
if (any(targets & getTargetBufferFlagsAt(i))) {
auto t = rt->gl.color[i] = handle_cast<GLTexture*>(color[i].handle);
const auto twidth = std::max(1u, t->width >> color[i].level);
const auto theight = std::max(1u, t->height >> color[i].level);
tmin = { std::min(tmin.x, twidth), std::min(tmin.y, theight) };
tmax = { std::max(tmax.x, twidth), std::max(tmax.y, theight) };
assert_invariant(color[i].handle);
rt->gl.color[i] = handle_cast<GLTexture*>(color[i].handle);
framebufferTexture(color[i], rt, GL_COLOR_ATTACHMENT0 + i);
bufs[i] = GL_COLOR_ATTACHMENT0 + i;
checkDimensions(rt->gl.color[i], color[i].level);
}
}
glDrawBuffers((GLsizei)maxDrawBuffers, bufs);
@@ -1152,37 +1181,28 @@ void OpenGLDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
// handle special cases first (where depth/stencil are packed)
bool specialCased = false;
if ((targets & TargetBufferFlags::DEPTH_AND_STENCIL) == TargetBufferFlags::DEPTH_AND_STENCIL) {
assert_invariant(!stencil.handle || stencil.handle == depth.handle);
auto t = rt->gl.depth = handle_cast<GLTexture*>(depth.handle);
const auto twidth = std::max(1u, t->width >> depth.level);
const auto theight = std::max(1u, t->height >> depth.level);
tmin = { std::min(tmin.x, twidth), std::min(tmin.y, theight) };
tmax = { std::max(tmax.x, twidth), std::max(tmax.y, theight) };
if (any(rt->gl.depth->usage & TextureUsage::SAMPLEABLE) ||
(!depth.handle && !stencil.handle)) {
// special case: depth & stencil requested, and both provided as the same texture
// special case: depth & stencil requested, but both not provided
specialCased = true;
assert_invariant(depth.handle);
// either we supplied only the depth handle or both depth/stencil are identical and not null
if (depth.handle && (stencil.handle == depth.handle || !stencil.handle)) {
rt->gl.depth = handle_cast<GLTexture*>(depth.handle);
framebufferTexture(depth, rt, GL_DEPTH_STENCIL_ATTACHMENT);
specialCased = true;
checkDimensions(rt->gl.depth, depth.level);
}
}
if (!specialCased) {
if (any(targets & TargetBufferFlags::DEPTH)) {
auto t = rt->gl.depth = handle_cast<GLTexture*>(depth.handle);
const auto twidth = std::max(1u, t->width >> depth.level);
const auto theight = std::max(1u, t->height >> depth.level);
tmin = { std::min(tmin.x, twidth), std::min(tmin.y, theight) };
tmax = { std::max(tmax.x, twidth), std::max(tmax.y, theight) };
assert_invariant(depth.handle);
rt->gl.depth = handle_cast<GLTexture*>(depth.handle);
framebufferTexture(depth, rt, GL_DEPTH_ATTACHMENT);
checkDimensions(rt->gl.depth, depth.level);
}
if (any(targets & TargetBufferFlags::STENCIL)) {
auto t = rt->gl.stencil = handle_cast<GLTexture*>(stencil.handle);
const auto twidth = std::max(1u, t->width >> stencil.level);
const auto theight = std::max(1u, t->height >> stencil.level);
tmin = { std::min(tmin.x, twidth), std::min(tmin.y, theight) };
tmax = { std::max(tmax.x, twidth), std::max(tmax.y, theight) };
assert_invariant(stencil.handle);
rt->gl.stencil = handle_cast<GLTexture*>(stencil.handle);
framebufferTexture(stencil, rt, GL_STENCIL_ATTACHMENT);
checkDimensions(rt->gl.stencil, stencil.level);
}
}
@@ -1204,19 +1224,19 @@ void OpenGLDriver::createSyncR(Handle<HwSync> fh, int) {
DEBUG_MARKER()
GLSync* f = handle_cast<GLSync *>(fh);
f->gl.sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
CHECK_GL_ERROR(utils::slog.e)
f->handle = mContext.createFenceSync(mPlatform);
// check the status of the sync once a frame, since we must do this from our thread
std::weak_ptr<GLSync::State> const weak = f->result;
runEveryNowAndThen([sync = f->gl.sync, weak]() -> bool {
runEveryNowAndThen(
[&platform = mPlatform, context = mContext, handle = f->handle, weak]() -> bool {
auto result = weak.lock();
if (result) {
GLenum const status = glClientWaitSync(sync, 0, 0u);
auto const status = context.clientWaitSync(platform, handle);
result->status.store(status, std::memory_order_relaxed);
return (status != GL_TIMEOUT_EXPIRED);
return (status != OpenGLContext::FenceSync::Status::TIMEOUT_EXPIRED);
}
return true; // we're done
return true;
});
}
@@ -1317,7 +1337,7 @@ void OpenGLDriver::destroyTexture(Handle<HwTexture> th) {
detachStream(t);
}
if (UTILS_UNLIKELY(t->target == SamplerType::SAMPLER_EXTERNAL)) {
mPlatform.destroyExternalImage(t);
mPlatform.destroyExternalImage(t->externalTexture);
} else {
glDeleteTextures(1, &t->gl.id);
}
@@ -1325,9 +1345,6 @@ void OpenGLDriver::destroyTexture(Handle<HwTexture> th) {
assert_invariant(t->gl.target == GL_RENDERBUFFER);
glDeleteRenderbuffers(1, &t->gl.id);
}
if (t->gl.fence) {
glDeleteSync(t->gl.fence);
}
if (t->gl.sidecarRenderBufferMS) {
glDeleteRenderbuffers(1, &t->gl.sidecarRenderBufferMS);
}
@@ -1406,10 +1423,9 @@ void OpenGLDriver::destroyTimerQuery(Handle<HwTimerQuery> tqh) {
void OpenGLDriver::destroySync(Handle<HwSync> sh) {
DEBUG_MARKER()
if (sh) {
GLSync* s = handle_cast<GLSync*>(sh);
glDeleteSync(s->gl.sync);
mContext.destroyFenceSync(mPlatform, s->handle);
destruct(sh, s);
}
}
@@ -1451,7 +1467,7 @@ void OpenGLDriver::setAcquiredImage(Handle<HwStream> sh, void* hwbuffer,
// If there's no pending image, do nothing. Note that GL_OES_EGL_image does not let you pass
// NULL to glEGLImageTargetTexture2DOES, and there is no concept of "detaching" an
// EGLimage from a texture.
mStreamsWithPendingAquiredImage.push_back(glstream);
mStreamsWithPendingAcquiredImage.push_back(glstream);
}
}
@@ -1459,8 +1475,8 @@ void OpenGLDriver::setAcquiredImage(Handle<HwStream> sh, void* hwbuffer,
// and therefore do not require synchronization. The former is always called immediately before
// beginFrame, the latter is called by the user from anywhere outside beginFrame / endFrame.
void OpenGLDriver::updateStreams(DriverApi* driver) {
if (UTILS_UNLIKELY(!mStreamsWithPendingAquiredImage.empty())) {
for (GLStream* s : mStreamsWithPendingAquiredImage) {
if (UTILS_UNLIKELY(!mStreamsWithPendingAcquiredImage.empty())) {
for (GLStream* s : mStreamsWithPendingAcquiredImage) {
assert_invariant(s);
assert_invariant(s->streamType == StreamType::ACQUIRED);
@@ -1478,7 +1494,15 @@ void OpenGLDriver::updateStreams(DriverApi* driver) {
return t->hwStream == s;
});
if (pos != streams.end()) {
setExternalTexture(*pos, image);
GLTexture* t = *pos;
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;
t->gl.targetIndex = (uint8_t)OpenGLContext::getIndexForTextureTarget(t->gl.target);
bindTexture(OpenGLContext::DUMMY_TEXTURE_BINDING, t);
}
}
if (previousImage.image) {
@@ -1486,7 +1510,7 @@ void OpenGLDriver::updateStreams(DriverApi* driver) {
}
});
}
mStreamsWithPendingAquiredImage.clear();
mStreamsWithPendingAcquiredImage.clear();
}
}
@@ -1676,6 +1700,10 @@ bool OpenGLDriver::isAutoDepthResolveSupported() {
return true;
}
bool OpenGLDriver::isSRGBSwapChainSupported() {
return mPlatform.isSRGBSwapChainSupported();
}
bool OpenGLDriver::isWorkaroundNeeded(Workaround workaround) {
switch (workaround) {
case Workaround::SPLIT_EASU:
@@ -1951,7 +1979,9 @@ void OpenGLDriver::generateMipmaps(Handle<HwTexture> th) {
auto& gl = mContext;
GLTexture* t = handle_cast<GLTexture *>(th);
#if defined(GL_VERSION_4_1) || defined(GL_ES_VERSION_3_1)
assert_invariant(t->gl.target != GL_TEXTURE_2D_MULTISAMPLE);
#endif
// Note: glGenerateMimap can also fail if the internal format is not both
// color-renderable and filterable (i.e.: doesn't work for depth)
bindTexture(OpenGLContext::DUMMY_TEXTURE_BINDING, t);
@@ -1992,8 +2022,13 @@ void OpenGLDriver::setTextureData(GLTexture* t, uint32_t level,
gl.pixelStore(GL_UNPACK_ROW_LENGTH, GLint(p.stride));
gl.pixelStore(GL_UNPACK_ALIGNMENT, GLint(p.alignment));
gl.pixelStore(GL_UNPACK_SKIP_PIXELS, GLint(p.left));
gl.pixelStore(GL_UNPACK_SKIP_ROWS, GLint(p.top));
// This is equivalent to using GL_UNPACK_SKIP_PIXELS and GL_UNPACK_SKIP_ROWS
using PBD = PixelBufferDescriptor;
size_t const stride = p.stride ? p.stride : width;
size_t const bpp = PBD::computeDataSize(p.format, p.type, 1, 1, 1);
size_t const bpr = PBD::computeDataSize(p.format, p.type, stride, 1, p.alignment);
void const* const buffer = static_cast<char const*>(p.buffer) + p.left * bpp + bpr * p.top;
switch (t->target) {
case SamplerType::SAMPLER_EXTERNAL:
@@ -2007,7 +2042,7 @@ void OpenGLDriver::setTextureData(GLTexture* t, uint32_t level,
assert_invariant(t->gl.target == GL_TEXTURE_2D);
glTexSubImage2D(t->gl.target, GLint(level),
GLint(xoffset), GLint(yoffset),
GLsizei(width), GLsizei(height), glFormat, glType, p.buffer);
GLsizei(width), GLsizei(height), glFormat, glType, buffer);
break;
case SamplerType::SAMPLER_3D:
assert_invariant(zoffset + depth <= std::max(1u, t->depth >> level));
@@ -2016,7 +2051,7 @@ void OpenGLDriver::setTextureData(GLTexture* t, uint32_t level,
assert_invariant(t->gl.target == GL_TEXTURE_3D);
glTexSubImage3D(t->gl.target, GLint(level),
GLint(xoffset), GLint(yoffset), GLint(zoffset),
GLsizei(width), GLsizei(height), GLsizei(depth), glFormat, glType, p.buffer);
GLsizei(width), GLsizei(height), GLsizei(depth), glFormat, glType, buffer);
break;
case SamplerType::SAMPLER_2D_ARRAY:
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
@@ -2028,7 +2063,7 @@ void OpenGLDriver::setTextureData(GLTexture* t, uint32_t level,
t->gl.target == GL_TEXTURE_CUBE_MAP_ARRAY);
glTexSubImage3D(t->gl.target, GLint(level),
GLint(xoffset), GLint(yoffset), GLint(zoffset),
GLsizei(width), GLsizei(height), GLsizei(depth), glFormat, glType, p.buffer);
GLsizei(width), GLsizei(height), GLsizei(depth), glFormat, glType, buffer);
break;
case SamplerType::SAMPLER_CUBEMAP: {
assert_invariant(t->gl.target == GL_TEXTURE_CUBE_MAP);
@@ -2044,7 +2079,7 @@ void OpenGLDriver::setTextureData(GLTexture* t, uint32_t level,
GLenum const target = getCubemapTarget(zoffset + face);
glTexSubImage2D(target, GLint(level), GLint(xoffset), GLint(yoffset),
GLsizei(width), GLsizei(height), glFormat, glType,
static_cast<uint8_t const*>(p.buffer) + faceSize * face);
static_cast<uint8_t const*>(buffer) + faceSize * face);
}
break;
}
@@ -2163,37 +2198,26 @@ void OpenGLDriver::setupExternalImage(void* image) {
mPlatform.retainExternalImage(image);
}
void OpenGLDriver::cancelExternalImage(void* image) {
mPlatform.releaseExternalImage(image);
}
void OpenGLDriver::setExternalImage(Handle<HwTexture> th, void* image) {
DEBUG_MARKER()
mPlatform.setExternalImage(image, handle_cast<GLTexture*>(th));
setExternalTexture(handle_cast<GLTexture*>(th), image);
GLTexture* t = handle_cast<GLTexture*>(th);
assert_invariant(t);
assert_invariant(t->target == SamplerType::SAMPLER_EXTERNAL);
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;
t->gl.targetIndex = (uint8_t)OpenGLContext::getIndexForTextureTarget(t->gl.target);
bindTexture(OpenGLContext::DUMMY_TEXTURE_BINDING, t);
}
}
void OpenGLDriver::setExternalImagePlane(Handle<HwTexture> th, void* image, uint32_t plane) {
DEBUG_MARKER()
}
void OpenGLDriver::setExternalTexture(GLTexture* t, void* image) {
auto& gl = mContext;
// TODO: move this logic to PlatformEGL.
if (gl.ext.OES_EGL_image_external_essl3) {
assert_invariant(t->target == SamplerType::SAMPLER_EXTERNAL);
assert_invariant(t->gl.target == GL_TEXTURE_EXTERNAL_OES);
bindTexture(OpenGLContext::DUMMY_TEXTURE_BINDING, t);
gl.activeTexture(OpenGLContext::DUMMY_TEXTURE_BINDING);
#ifdef GL_OES_EGL_image
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, static_cast<GLeglImageOES>(image));
#endif
}
}
void OpenGLDriver::setExternalStream(Handle<HwTexture> th, Handle<HwStream> sh) {
auto& gl = mContext;
if (gl.ext.OES_EGL_image_external_essl3) {
@@ -2329,13 +2353,14 @@ SyncStatus OpenGLDriver::getSyncStatus(Handle<HwSync> sh) {
return SyncStatus::NOT_SIGNALED;
}
auto status = s->result->status.load(std::memory_order_relaxed);
using Status = OpenGLContext::FenceSync::Status;
switch (status) {
case GL_CONDITION_SATISFIED:
case GL_ALREADY_SIGNALED:
case Status::CONDITION_SATISFIED:
case Status::ALREADY_SIGNALED:
return SyncStatus::SIGNALED;
case GL_TIMEOUT_EXPIRED:
case Status::TIMEOUT_EXPIRED:
return SyncStatus::NOT_SIGNALED;
case GL_WAIT_FAILED:
case Status::FAILURE:
default:
return SyncStatus::ERROR;
}
@@ -2706,10 +2731,7 @@ void OpenGLDriver::readPixels(Handle<HwRenderTarget> src,
GLenum const glFormat = getFormat(p.format);
GLenum const glType = getType(p.type);
gl.pixelStore(GL_PACK_ROW_LENGTH, (GLint)p.stride);
gl.pixelStore(GL_PACK_ALIGNMENT, (GLint)p.alignment);
gl.pixelStore(GL_PACK_SKIP_PIXELS, (GLint)p.left);
gl.pixelStore(GL_PACK_SKIP_ROWS, (GLint)p.top);
gl.pixelStore(GL_PACK_ALIGNMENT, (GLint)p.alignment);
/*
* glReadPixel() operation...
@@ -2737,44 +2759,54 @@ void OpenGLDriver::readPixels(Handle<HwRenderTarget> src,
*/
GLRenderTarget const* s = handle_cast<GLRenderTarget const*>(src);
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, s->gl.fbo);
// glReadPixel doesn't resolve automatically, but it does with the auto-resolve extension,
// which we're always emulating. So if we have a resolved fbo (fbo_read), use that instead.
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, s->gl.fbo_read ? s->gl.fbo_read : s->gl.fbo);
using PBD = PixelBufferDescriptor;
// The PBO only needs to accommodate the area we're reading, with alignment.
auto const pboSize = (GLsizeiptr)PBD::computeDataSize(
p.format, p.type, width, height, p.alignment);
GLuint pbo;
glGenBuffers(1, &pbo);
gl.bindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
glBufferData(GL_PIXEL_PACK_BUFFER, (GLsizeiptr)p.size, nullptr, GL_STATIC_DRAW);
glBufferData(GL_PIXEL_PACK_BUFFER, pboSize, nullptr, GL_STATIC_DRAW);
glReadPixels(GLint(x), GLint(y), GLint(width), GLint(height), glFormat, glType, nullptr);
gl.bindBuffer(GL_PIXEL_PACK_BUFFER, 0);
CHECK_GL_ERROR(utils::slog.e)
// we're forced to make a copy on the heap because otherwise it deletes std::function<> copy
// constructor.
auto* pUserBuffer = new PixelBufferDescriptor(std::move(p));
whenGpuCommandsComplete([this, width, height, pbo, pUserBuffer]() mutable {
auto* const pUserBuffer = new PixelBufferDescriptor(std::move(p));
whenGpuCommandsComplete([this, width, height, pbo, pboSize, pUserBuffer]() mutable {
PixelBufferDescriptor& p = *pUserBuffer;
auto& gl = mContext;
gl.bindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
void* vaddr = nullptr;
#if defined(__EMSCRIPTEN__)
std::unique_ptr<uint8_t> clientBuffer = std::make_unique<uint8_t>(p.size);
glGetBufferSubData(GL_PIXEL_PACK_BUFFER, 0, p.size, clientBuffer.get());
std::unique_ptr<uint8_t> clientBuffer = std::make_unique<uint8_t>(pboSize);
glGetBufferSubData(GL_PIXEL_PACK_BUFFER, 0, pboSize, clientBuffer.get());
vaddr = clientBuffer.get();
#else
vaddr = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, (GLsizeiptr)p.size, GL_MAP_READ_BIT);
vaddr = glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, pboSize, GL_MAP_READ_BIT);
#endif
if (vaddr) {
// now we need to flip the buffer vertically to match our API
size_t const stride = p.stride ? p.stride : width;
size_t const bpp = PixelBufferDescriptor::computeDataSize(
p.format, p.type, 1, 1, 1);
size_t const bpr = PixelBufferDescriptor::computeDataSize(
p.format, p.type, stride, 1, p.alignment);
char const* head = (char const*)vaddr + p.left * bpp + bpr * p.top;
char* tail = (char*)p.buffer + p.left * bpp + bpr * (p.top + height - 1);
size_t const bpp = PBD::computeDataSize(p.format, p.type, 1, 1, 1);
size_t const dstBpr = PBD::computeDataSize(p.format, p.type, stride, 1, p.alignment);
char* pDst = (char*)p.buffer + p.left * bpp + dstBpr * (p.top + height - 1);
size_t const srcBpr = PBD::computeDataSize(p.format, p.type, width, 1, p.alignment);
char const* pSrc = (char const*)vaddr;
for (size_t i = 0; i < height; ++i) {
memcpy(tail, head, bpp * width);
head += bpr;
tail -= bpr;
memcpy(pDst, pSrc, bpp * width);
pSrc += srcBpr;
pDst -= dstBpr;
}
#if !defined(__EMSCRIPTEN__)
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
@@ -2841,7 +2873,7 @@ void OpenGLDriver::readBufferSubData(backend::BufferObjectHandle boh,
}
void OpenGLDriver::whenGpuCommandsComplete(std::function<void()> fn) noexcept {
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
OpenGLContext::FenceSync sync = mContext.createFenceSync(mPlatform);
mGpuCommandCompleteOps.emplace_back(sync, std::move(fn));
CHECK_GL_ERROR(utils::slog.e)
}
@@ -2854,15 +2886,16 @@ void OpenGLDriver::executeGpuCommandsCompleteOps() noexcept {
auto& v = mGpuCommandCompleteOps;
auto it = v.begin();
while (it != v.end()) {
GLenum const status = glClientWaitSync(it->first, 0, 0);
if (status == GL_ALREADY_SIGNALED || status == GL_CONDITION_SATISFIED) {
using Status = OpenGLContext::FenceSync::Status;
auto const status = mContext.clientWaitSync(mPlatform, it->first);
if (status == Status::ALREADY_SIGNALED || status == Status::CONDITION_SATISFIED) {
it->second();
glDeleteSync(it->first);
mContext.destroyFenceSync(mPlatform, it->first);
it = v.erase(it);
} else if (UTILS_UNLIKELY(status == GL_WAIT_FAILED)) {
} else if (UTILS_UNLIKELY(status == Status::FAILURE)) {
// This should never happen, but is very problematic if it does, as we might leak
// some data depending on what the callback does. However, we clean up our own state.
glDeleteSync(it->first);
mContext.destroyFenceSync(mPlatform, it->first);
it = v.erase(it);
} else {
++it;
@@ -3200,8 +3233,14 @@ void OpenGLDriver::dispatchCompute(Handle<HwProgram> program, math::uint3 workGr
useProgram(p);
#if defined(GL_ES_VERSION_3_1) || defined(GL_VERSION_4_3)
// FIXME: this line is commented-out for now due to issues switching G3 clients to API 21.
// glDispatchCompute(workGroupCount.x, workGroupCount.y, workGroupCount.z);
#if defined(__ANDROID__)
// on Android, GLES3.1 and above entry-points are defined in glext
// (this is temporary, until we phase-out API < 21)
using glext::glDispatchCompute;
#endif
glDispatchCompute(workGroupCount.x, workGroupCount.y, workGroupCount.z);
#endif
#ifdef FILAMENT_ENABLE_MATDBG

View File

@@ -21,12 +21,14 @@
#include "GLUtils.h"
#include "OpenGLContext.h"
#include "private/backend/AcquiredImage.h"
#include "private/backend/Driver.h"
#include "private/backend/HandleAllocator.h"
#include "backend/Program.h"
#include "backend/TargetBufferInfo.h"
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/AcquiredImage.h>
#include <backend/Program.h>
#include <backend/TargetBufferInfo.h>
#include <utils/compiler.h>
#include <utils/Allocator.h>
@@ -120,7 +122,6 @@ public:
GLenum target = 0;
GLenum internalFormat = 0;
GLuint sidecarRenderBufferMS = 0; // multi-sample sidecar renderbuffer
mutable GLsync fence = {};
// texture parameters go here too
GLfloat anisotropy = 1.0;
@@ -132,7 +133,7 @@ public:
uint8_t reserved : 3;
} gl;
void* platformPImpl = nullptr;
OpenGLPlatform::ExternalTexture* externalTexture = nullptr;
};
struct GLTimerQuery : public HwTimerQuery {
@@ -184,11 +185,10 @@ public:
struct GLSync : public HwSync {
using HwSync::HwSync;
struct State {
std::atomic<GLenum> status{ GL_TIMEOUT_EXPIRED };
std::atomic<OpenGLContext::FenceSync::Status> status{
OpenGLContext::FenceSync::Status::TIMEOUT_EXPIRED };
};
struct {
GLsync sync;
} gl;
OpenGLContext::FenceSync handle{};
std::shared_ptr<State> result{ std::make_shared<GLSync::State>() };
};
@@ -349,7 +349,7 @@ private:
std::vector<GLTexture*> mTexturesWithStreamsAttached;
// the must be accessed from the user thread only
std::vector<GLStream*> mStreamsWithPendingAquiredImage;
std::vector<GLStream*> mStreamsWithPendingAcquiredImage;
void attachStream(GLTexture* t, GLStream* stream) noexcept;
void detachStream(GLTexture* t) noexcept;
@@ -359,12 +359,10 @@ private:
void updateTextureLodRange(GLTexture* texture, int8_t targetLevel) noexcept;
void setExternalTexture(GLTexture* t, void* image);
// tasks executed on the main thread after the fence signaled
void whenGpuCommandsComplete(std::function<void()> fn) noexcept;
void executeGpuCommandsCompleteOps() noexcept;
std::vector<std::pair<GLsync, std::function<void()>>> mGpuCommandCompleteOps;
std::vector<std::pair<OpenGLContext::FenceSync, std::function<void()>>> mGpuCommandCompleteOps;
// tasks regularly executed on the main thread at until they return true
void runEveryNowAndThen(std::function<bool()> fn) noexcept;

View File

@@ -14,16 +14,96 @@
* limitations under the License.
*/
#include "private/backend/OpenGLPlatform.h"
#include <backend/platforms/OpenGLPlatform.h>
#include "OpenGLDriverFactory.h"
namespace filament::backend {
OpenGLPlatform::~OpenGLPlatform() noexcept = default;
Driver* OpenGLPlatform::createDefaultDriver(OpenGLPlatform* platform, void* sharedContext, const Platform::DriverConfig& driverConfig) {
Driver* OpenGLPlatform::createDefaultDriver(OpenGLPlatform* platform,
void* sharedContext, const Platform::DriverConfig& driverConfig) {
return OpenGLDriverFactory::create(platform, sharedContext, driverConfig);
}
OpenGLPlatform::~OpenGLPlatform() noexcept = default;
bool OpenGLPlatform::isSRGBSwapChainSupported() const noexcept {
return false;
}
uint32_t OpenGLPlatform::createDefaultRenderTarget() noexcept {
return 0;
}
void OpenGLPlatform::setPresentationTime(
UTILS_UNUSED int64_t presentationTimeInNanosecond) noexcept {
}
bool OpenGLPlatform::canCreateFence() noexcept {
return false;
}
Platform::Fence* OpenGLPlatform::createFence() noexcept {
return nullptr;
}
void OpenGLPlatform::destroyFence(
UTILS_UNUSED Fence* fence) noexcept {
}
FenceStatus OpenGLPlatform::waitFence(
UTILS_UNUSED Fence* fence,
UTILS_UNUSED uint64_t timeout) noexcept {
return FenceStatus::ERROR;
}
Platform::Stream* OpenGLPlatform::createStream(
UTILS_UNUSED void* nativeStream) noexcept {
return nullptr;
}
void OpenGLPlatform::destroyStream(
UTILS_UNUSED Stream* stream) noexcept {
}
void OpenGLPlatform::attach(
UTILS_UNUSED Stream* stream,
UTILS_UNUSED intptr_t tname) noexcept {
}
void OpenGLPlatform::detach(
UTILS_UNUSED Stream* stream) noexcept {
}
void OpenGLPlatform::updateTexImage(
UTILS_UNUSED Stream* stream,
UTILS_UNUSED int64_t* timestamp) noexcept {
}
OpenGLPlatform::ExternalTexture* OpenGLPlatform::createExternalImageTexture() noexcept {
return nullptr;
}
void OpenGLPlatform::destroyExternalImage(
UTILS_UNUSED ExternalTexture* texture) noexcept {
}
void OpenGLPlatform::retainExternalImage(
UTILS_UNUSED void* externalImage) noexcept {
}
bool OpenGLPlatform::setExternalImage(
UTILS_UNUSED void* externalImage,
UTILS_UNUSED ExternalTexture* texture) noexcept {
return false;
}
AcquiredImage OpenGLPlatform::transformAcquiredImage(AcquiredImage source) noexcept {
return source;
}
} // namespace filament::backend

View File

@@ -121,11 +121,21 @@ void OpenGLProgram::compileShaders(OpenGLContext& context,
UTILS_NOUNROLL
for (size_t i = 0; i < Program::SHADER_TYPE_COUNT; i++) {
const ShaderStage stage = static_cast<ShaderStage>(i);
GLenum glShaderType;
GLenum glShaderType{};
switch (stage) {
case ShaderStage::VERTEX: glShaderType = GL_VERTEX_SHADER; break;
case ShaderStage::FRAGMENT: glShaderType = GL_FRAGMENT_SHADER; break;
case ShaderStage::COMPUTE: glShaderType = GL_COMPUTE_SHADER; break;
case ShaderStage::VERTEX:
glShaderType = GL_VERTEX_SHADER;
break;
case ShaderStage::FRAGMENT:
glShaderType = GL_FRAGMENT_SHADER;
break;
case ShaderStage::COMPUTE:
#if defined(GL_VERSION_4_1) || defined(GL_ES_VERSION_3_1)
glShaderType = GL_COMPUTE_SHADER;
#else
continue;
#endif
break;
}
if (UTILS_LIKELY(!shadersSource[i].empty())) {
@@ -406,11 +416,6 @@ void OpenGLProgram::updateSamplers(OpenGLDriver* gld) const noexcept {
const GLTexture* const t = sb->textureUnitEntries[j].texture;
GLuint const s = sb->textureUnitEntries[j].sampler;
if (t) { // program may not use all samplers of sampler group
if (UTILS_UNLIKELY(t->gl.fence)) {
glWaitSync(t->gl.fence, 0, GL_TIMEOUT_IGNORED);
glDeleteSync(t->gl.fence);
t->gl.fence = nullptr;
}
gld->bindTexture(tmu, t);
gld->bindSampler(tmu, s);
}

View File

@@ -16,7 +16,7 @@
#include "OpenGLTimerQuery.h"
#include "private/backend/OpenGLPlatform.h"
#include <backend/platforms/OpenGLPlatform.h>
#include <utils/compiler.h>
#include <utils/Log.h>
@@ -34,8 +34,9 @@ OpenGLTimerQueryInterface::~OpenGLTimerQueryInterface() = default;
// ------------------------------------------------------------------------------------------------
TimerQueryNative::TimerQueryNative(OpenGLContext& context)
: gl(context) {
#if defined(GL_VERSION_3_3) || defined(GL_EXT_disjoint_timer_query)
TimerQueryNative::TimerQueryNative(OpenGLContext&) {
}
TimerQueryNative::~TimerQueryNative() = default;
@@ -44,12 +45,12 @@ void TimerQueryNative::flush() {
}
void TimerQueryNative::beginTimeElapsedQuery(GLTimerQuery* query) {
gl.beginQuery(GL_TIME_ELAPSED, query->gl.query);
glBeginQuery(GL_TIME_ELAPSED, query->gl.query);
CHECK_GL_ERROR(utils::slog.e)
}
void TimerQueryNative::endTimeElapsedQuery(GLTimerQuery*) {
gl.endQuery(GL_TIME_ELAPSED);
glEndQuery(GL_TIME_ELAPSED);
CHECK_GL_ERROR(utils::slog.e)
}
@@ -62,14 +63,14 @@ bool TimerQueryNative::queryResultAvailable(GLTimerQuery* query) {
uint64_t TimerQueryNative::queryResult(GLTimerQuery* query) {
GLuint64 elapsedTime = 0;
// IOS doesn't have glGetQueryObjectui64v, we'll never end-up here on ios anyways
#ifndef IOS
// we won't end-up here if we're on ES and don't have GL_EXT_disjoint_timer_query
glGetQueryObjectui64v(query->gl.query, GL_QUERY_RESULT, &elapsedTime);
#endif
CHECK_GL_ERROR(utils::slog.e)
return elapsedTime;
}
#endif
// ------------------------------------------------------------------------------------------------
OpenGLTimerQueryFence::OpenGLTimerQueryFence(OpenGLPlatform& platform)
@@ -85,7 +86,7 @@ OpenGLTimerQueryFence::OpenGLTimerQueryFence(OpenGLPlatform& platform)
});
exitRequested = mExitRequested;
if (!queue.empty()) {
Job job(queue.front());
Job const job(queue.front());
queue.erase(queue.begin());
lock.unlock();
job();
@@ -105,7 +106,7 @@ OpenGLTimerQueryFence::~OpenGLTimerQueryFence() {
}
void OpenGLTimerQueryFence::enqueue(OpenGLTimerQueryFence::Job&& job) {
std::unique_lock<utils::Mutex> lock(mLock);
std::unique_lock<utils::Mutex> const lock(mLock);
mQueue.push_back(std::forward<Job>(job));
mCondition.notify_one();
}
@@ -114,9 +115,9 @@ void OpenGLTimerQueryFence::flush() {
// Use calls to flush() as a proxy for when the GPU work started.
GLTimerQuery* query = mActiveQuery;
if (query) {
uint64_t elapsed = query->gl.emulation->elapsed.load(std::memory_order_relaxed);
uint64_t const elapsed = query->gl.emulation->elapsed.load(std::memory_order_relaxed);
if (!elapsed) {
uint64_t now = clock::now().time_since_epoch().count();
uint64_t const now = clock::now().time_since_epoch().count();
query->gl.emulation->elapsed.store(now, std::memory_order_relaxed);
//SYSTRACE_CONTEXT();
//SYSTRACE_ASYNC_BEGIN("gpu", query->gl.query);
@@ -139,7 +140,7 @@ void OpenGLTimerQueryFence::beginTimeElapsedQuery(GLTimerQuery* query) {
void OpenGLTimerQueryFence::endTimeElapsedQuery(GLTimerQuery* query) {
assert_invariant(mActiveQuery);
Platform::Fence* fence = mPlatform.createFence();
std::weak_ptr<GLTimerQuery::State> weak = query->gl.emulation;
std::weak_ptr<GLTimerQuery::State> const weak = query->gl.emulation;
mActiveQuery = nullptr;
//uint32_t cookie = cookie = query->gl.query;
push([&platform = mPlatform, fence, weak]() {

View File

@@ -48,6 +48,8 @@ public:
virtual uint64_t queryResult(GLTimerQuery* query) = 0;
};
#if defined(GL_VERSION_3_3) || defined(GL_EXT_disjoint_timer_query)
class TimerQueryNative : public OpenGLTimerQueryInterface {
public:
explicit TimerQueryNative(OpenGLContext& context);
@@ -58,9 +60,10 @@ private:
void endTimeElapsedQuery(GLTimerQuery* query) override;
bool queryResultAvailable(GLTimerQuery* query) override;
uint64_t queryResult(GLTimerQuery* query) override;
OpenGLContext& gl;
};
#endif
class OpenGLTimerQueryFence : public OpenGLTimerQueryInterface {
public:
explicit OpenGLTimerQueryFence(OpenGLPlatform& platform);

View File

@@ -16,11 +16,17 @@
#include "gl_headers.h"
#if defined(__ANDROID__) || defined(FILAMENT_USE_EXTERNAL_GLES3) || defined(__EMSCRIPTEN__)
#if defined(FILAMENT_IMPORT_ENTRY_POINTS)
#include <EGL/egl.h>
#include <mutex>
// for non EGL platforms, we'd need to implement this differently. Currently, it's not a problem.
template<typename T>
static void getProcAddress(T& pfn, const char* name) noexcept {
pfn = (T)eglGetProcAddress(name);
}
namespace glext {
#ifdef GL_QCOM_tiled_rendering
PFNGLSTARTTILINGQCOMPROC glStartTilingQCOM;
@@ -49,68 +55,48 @@ PFNGLGETQUERYOBJECTUI64VEXTPROC glGetQueryObjectui64v;
PFNGLCLIPCONTROLEXTPROC glClipControl;
#endif
#if defined(__ANDROID__)
// On Android, If we want to support a build system less than ANDROID_API 21, we need to
// use getProcAddress for ES3.1 and above entry points.
PFNGLDISPATCHCOMPUTEPROC glDispatchCompute;
#endif
static std::once_flag sGlExtInitialized;
void importGLESExtensionsEntryPoints() {
std::call_once(sGlExtInitialized, []() {
std::call_once(sGlExtInitialized, +[]() {
#ifdef GL_QCOM_tiled_rendering
glStartTilingQCOM =
(PFNGLSTARTTILINGQCOMPROC)eglGetProcAddress(
"glStartTilingQCOM");
glEndTilingQCOM =
(PFNGLENDTILINGQCOMPROC)eglGetProcAddress(
"glEndTilingQCOM");
getProcAddress(glStartTilingQCOM, "glStartTilingQCOM");
getProcAddress(glEndTilingQCOM, "glEndTilingQCOM");
#endif
#ifdef GL_OES_EGL_image
glEGLImageTargetTexture2DOES =
(PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress(
"glEGLImageTargetTexture2DOES");
getProcAddress(glEGLImageTargetTexture2DOES, "glEGLImageTargetTexture2DOES");
#endif
#if GL_EXT_debug_marker
glInsertEventMarkerEXT =
(PFNGLINSERTEVENTMARKEREXTPROC)eglGetProcAddress(
"glInsertEventMarkerEXT");
glPushGroupMarkerEXT =
(PFNGLPUSHGROUPMARKEREXTPROC)eglGetProcAddress(
"glPushGroupMarkerEXT");
glPopGroupMarkerEXT =
(PFNGLPOPGROUPMARKEREXTPROC)eglGetProcAddress(
"glPopGroupMarkerEXT");
getProcAddress(glInsertEventMarkerEXT, "glInsertEventMarkerEXT");
getProcAddress(glPushGroupMarkerEXT, "glPushGroupMarkerEXT");
getProcAddress(glPopGroupMarkerEXT, "glPopGroupMarkerEXT");
#endif
#if GL_EXT_multisampled_render_to_texture
glFramebufferTexture2DMultisampleEXT =
(PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC)eglGetProcAddress(
"glFramebufferTexture2DMultisampleEXT");
glRenderbufferStorageMultisampleEXT =
(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC)eglGetProcAddress(
"glRenderbufferStorageMultisampleEXT");
getProcAddress(glFramebufferTexture2DMultisampleEXT, "glFramebufferTexture2DMultisampleEXT");
getProcAddress(glRenderbufferStorageMultisampleEXT, "glRenderbufferStorageMultisampleEXT");
#endif
#ifdef GL_KHR_debug
glDebugMessageCallbackKHR =
(PFNGLDEBUGMESSAGECALLBACKKHRPROC)eglGetProcAddress(
"glDebugMessageCallbackKHR");
glGetDebugMessageLogKHR =
(PFNGLGETDEBUGMESSAGELOGKHRPROC)eglGetProcAddress(
"glGetDebugMessageLogKHR");
getProcAddress(glDebugMessageCallbackKHR, "glDebugMessageCallbackKHR");
getProcAddress(glGetDebugMessageLogKHR, "glGetDebugMessageLogKHR");
#endif
#ifdef GL_EXT_disjoint_timer_query
glGetQueryObjectui64v =
(PFNGLGETQUERYOBJECTUI64VEXTPROC)eglGetProcAddress(
"glGetQueryObjectui64vEXT");
getProcAddress(glGetQueryObjectui64v, "glGetQueryObjectui64vEXT");
#endif
#ifdef GL_EXT_clip_control
getProcAddress(glClipControl, "glClipControlEXT");
#endif
#if defined(__ANDROID__)
getProcAddress(glDispatchCompute, "glDispatchCompute");
#endif
});
#ifdef GL_EXT_clip_control
glClipControl =
(PFNGLCLIPCONTROLEXTPROC)eglGetProcAddress(
"glClipControlEXT");
#endif
}
} // namespace glext
#endif
#endif // defined(FILAMENT_IMPORT_ENTRY_POINTS)

View File

@@ -26,42 +26,6 @@
#endif
#include <GLES2/gl2ext.h>
/* The Android NDK doesn't expose extensions, fake it with eglGetProcAddress */
namespace glext {
// importGLESExtensionsEntryPoints is thread-safe and can be called multiple times.
// it is currently called from PlatformEGL.
void importGLESExtensionsEntryPoints();
#ifdef GL_QCOM_tiled_rendering
extern PFNGLSTARTTILINGQCOMPROC glStartTilingQCOM;
extern PFNGLENDTILINGQCOMPROC glEndTilingQCOM;
#endif
#ifdef GL_OES_EGL_image
extern PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
#endif
#ifdef GL_EXT_debug_marker
extern PFNGLINSERTEVENTMARKEREXTPROC glInsertEventMarkerEXT;
extern PFNGLPUSHGROUPMARKEREXTPROC glPushGroupMarkerEXT;
extern PFNGLPOPGROUPMARKEREXTPROC glPopGroupMarkerEXT;
#endif
#ifdef GL_EXT_multisampled_render_to_texture
extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT;
extern PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT;
#endif
#ifdef GL_KHR_debug
extern PFNGLDEBUGMESSAGECALLBACKKHRPROC glDebugMessageCallbackKHR;
extern PFNGLGETDEBUGMESSAGELOGKHRPROC glGetDebugMessageLogKHR;
#endif
#ifdef GL_EXT_disjoint_timer_query
extern PFNGLGETQUERYOBJECTUI64VEXTPROC glGetQueryObjectui64v;
#endif
#ifdef GL_EXT_clip_control
extern PFNGLCLIPCONTROLEXTPROC glClipControl;
#endif
}
using namespace glext;
#elif defined(IOS)
#define GLES_SILENCE_DEPRECATION
@@ -82,111 +46,110 @@
#endif
#if (!defined(GL_ES_VERSION_2_0) && !defined(GL_VERSION_4_1))
#error "Minimum header version must be OpenGL ES 2.0 or OpenGL 4.1"
#endif
/*
* Since we need ES3.1 headers and iOS only has ES3.0, we also define the constants we
* need to avoid many #ifdef in the actual code.
* GLES extensions
*/
#if defined(GL_ES_VERSION_2_0)
#if defined(GL_ES_VERSION_2_0) // this basically means all versions of GLES
#ifdef GL_EXT_disjoint_timer_query
# ifndef GL_TIME_ELAPSED
# define GL_TIME_ELAPSED GL_TIME_ELAPSED_EXT
# endif
#if defined(IOS)
// iOS headers only provide prototypes, nothing to do.
#else
#define FILAMENT_IMPORT_ENTRY_POINTS
/* The Android NDK doesn't expose extensions, fake it with eglGetProcAddress */
namespace glext {
// importGLESExtensionsEntryPoints is thread-safe and can be called multiple times.
// it is currently called from PlatformEGL.
void importGLESExtensionsEntryPoints();
#ifdef GL_QCOM_tiled_rendering
extern PFNGLSTARTTILINGQCOMPROC glStartTilingQCOM;
extern PFNGLENDTILINGQCOMPROC glEndTilingQCOM;
#endif
#ifdef GL_OES_EGL_image
extern PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
#endif
#ifdef GL_EXT_debug_marker
extern PFNGLINSERTEVENTMARKEREXTPROC glInsertEventMarkerEXT;
extern PFNGLPUSHGROUPMARKEREXTPROC glPushGroupMarkerEXT;
extern PFNGLPOPGROUPMARKEREXTPROC glPopGroupMarkerEXT;
#endif
#ifdef GL_EXT_multisampled_render_to_texture
extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT;
extern PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC glFramebufferTexture2DMultisampleEXT;
#endif
#ifdef GL_KHR_debug
extern PFNGLDEBUGMESSAGECALLBACKKHRPROC glDebugMessageCallbackKHR;
extern PFNGLGETDEBUGMESSAGELOGKHRPROC glGetDebugMessageLogKHR;
#endif
#ifdef GL_EXT_clip_control
# ifndef GL_LOWER_LEFT
# define GL_LOWER_LEFT GL_LOWER_LEFT_EXT
# endif
# ifndef GL_ZERO_TO_ONE
# define GL_ZERO_TO_ONE GL_ZERO_TO_ONE_EXT
# endif
extern PFNGLCLIPCONTROLEXTPROC glClipControl;
#endif
#ifdef GL_EXT_disjoint_timer_query
extern PFNGLGETQUERYOBJECTUI64VEXTPROC glGetQueryObjectui64v;
#endif
#if defined(__ANDROID__)
extern PFNGLDISPATCHCOMPUTEPROC glDispatchCompute;
#endif
} // namespace glext
using namespace glext;
#ifndef GL_TEXTURE_CUBE_MAP_ARRAY
# define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
#endif
// Prevent lots of #ifdef's between desktop and mobile
#ifdef GL_EXT_disjoint_timer_query
# define GL_TIME_ELAPSED GL_TIME_ELAPSED_EXT
#endif
#ifdef GL_EXT_clip_control
# define GL_LOWER_LEFT GL_LOWER_LEFT_EXT
# define GL_ZERO_TO_ONE GL_ZERO_TO_ONE_EXT
#endif
// we need GL_TEXTURE_CUBE_MAP_ARRAY defined, but we won't use it if the extension/feature
// is not available.
#if defined(GL_EXT_texture_cube_map_array)
# define GL_TEXTURE_CUBE_MAP_ARRAY GL_TEXTURE_CUBE_MAP_ARRAY_EXT
#else
# define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009
#endif
#if defined(GL_KHR_debug)
# ifndef GL_DEBUG_OUTPUT
# define GL_DEBUG_OUTPUT GL_DEBUG_OUTPUT_KHR
# endif
# ifndef GL_DEBUG_OUTPUT_SYNCHRONOUS
# define GL_DEBUG_OUTPUT_SYNCHRONOUS GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR
# endif
# ifndef GL_DEBUG_SEVERITY_HIGH
# define GL_DEBUG_SEVERITY_HIGH GL_DEBUG_SEVERITY_HIGH_KHR
# endif
# ifndef GL_DEBUG_SEVERITY_MEDIUM
# define GL_DEBUG_SEVERITY_MEDIUM GL_DEBUG_SEVERITY_MEDIUM_KHR
# endif
# ifndef GL_DEBUG_SEVERITY_LOW
# define GL_DEBUG_SEVERITY_LOW GL_DEBUG_SEVERITY_LOW_KHR
# endif
# ifndef GL_DEBUG_SEVERITY_NOTIFICATION
# define GL_DEBUG_SEVERITY_NOTIFICATION GL_DEBUG_SEVERITY_NOTIFICATION_KHR
# endif
# ifndef GL_DEBUG_TYPE_MARKER
# define GL_DEBUG_TYPE_MARKER GL_DEBUG_TYPE_MARKER_KHR
# endif
# ifndef GL_DEBUG_TYPE_ERROR
# define GL_DEBUG_TYPE_ERROR GL_DEBUG_TYPE_ERROR_KHR
# endif
# ifndef GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR
# define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR
# endif
# ifndef GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR
# define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR
# endif
# ifndef GL_DEBUG_TYPE_PORTABILITY
# define GL_DEBUG_TYPE_PORTABILITY GL_DEBUG_TYPE_PORTABILITY_KHR
# endif
# ifndef GL_DEBUG_TYPE_PERFORMANCE
# define GL_DEBUG_TYPE_PERFORMANCE GL_DEBUG_TYPE_PERFORMANCE_KHR
# endif
# ifndef GL_DEBUG_TYPE_OTHER
# define GL_DEBUG_TYPE_OTHER GL_DEBUG_TYPE_OTHER_KHR
# endif
# define glDebugMessageCallback glDebugMessageCallbackKHR
# define GL_DEBUG_OUTPUT GL_DEBUG_OUTPUT_KHR
# define GL_DEBUG_OUTPUT_SYNCHRONOUS GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR
# define GL_DEBUG_SEVERITY_HIGH GL_DEBUG_SEVERITY_HIGH_KHR
# define GL_DEBUG_SEVERITY_MEDIUM GL_DEBUG_SEVERITY_MEDIUM_KHR
# define GL_DEBUG_SEVERITY_LOW GL_DEBUG_SEVERITY_LOW_KHR
# define GL_DEBUG_SEVERITY_NOTIFICATION GL_DEBUG_SEVERITY_NOTIFICATION_KHR
# define GL_DEBUG_TYPE_MARKER GL_DEBUG_TYPE_MARKER_KHR
# define GL_DEBUG_TYPE_ERROR GL_DEBUG_TYPE_ERROR_KHR
# define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR
# define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR
# define GL_DEBUG_TYPE_PORTABILITY GL_DEBUG_TYPE_PORTABILITY_KHR
# define GL_DEBUG_TYPE_PERFORMANCE GL_DEBUG_TYPE_PERFORMANCE_KHR
# define GL_DEBUG_TYPE_OTHER GL_DEBUG_TYPE_OTHER_KHR
# define glDebugMessageCallback glDebugMessageCallbackKHR
#endif
/* The iOS SDK only provides OpenGL ES headers up to 3.0. Filament works with OpenGL 3.0, but
* requires ES3.1 headers */
#if !defined(GL_ES_VERSION_3_1)
#define GL_SHADER_STORAGE_BUFFER 0x90D2
#define GL_COMPUTE_SHADER 0x91B9
#define GL_TEXTURE_2D_MULTISAMPLE 0x9100
// FIXME: The GL_TIME_ELAPSED define is used unconditionally in Filament, but
// requires extension support.
#ifndef GL_TIME_ELAPSED
#define GL_TIME_ELAPSED 0x88BF
#endif
#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A
#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C
#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D
#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E
#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F
#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054
#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F
#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A
#endif
#endif // GL_ES_VERSION_2_0
// This is just to simplify the implementation (i.e. so we don't have to have #ifdefs everywhere)
#ifndef GL_OES_EGL_image_external
#define GL_TEXTURE_EXTERNAL_OES 0x8D65
#endif
// This is an odd duck function that exists in WebGL 2.0 but not in OpenGL ES.
#if defined(__EMSCRIPTEN__)
extern "C" {
@@ -219,11 +182,6 @@ void glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, void *d
# define BACKEND_OPENGL_LEVEL BACKEND_OPENGL_LEVEL_GLES20
#endif
// This is just to simplify the implementation (i.e. so we don't have to have #ifdefs everywhere)
#ifndef GL_OES_EGL_image_external
#define GL_TEXTURE_EXTERNAL_OES 0x8D65
#endif
#include "NullGLES.h"
#endif // TNT_FILAMENT_BACKEND_OPENGL_GL_HEADERS_H

View File

@@ -19,11 +19,13 @@
#include "../gl_headers.h"
#include <backend/platforms/OpenGLPlatform.h>
#include <CoreVideo/CoreVideo.h>
namespace filament::backend {
class CocoaTouchExternalImage final {
class CocoaTouchExternalImage final : public OpenGLPlatform::ExternalTexture {
public:
/**

View File

@@ -1,68 +0,0 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
#include <stdint.h>
#include <backend/DriverEnums.h>
#include "private/backend/OpenGLPlatform.h"
namespace filament::backend {
struct PlatformCocoaGLImpl;
class PlatformCocoaGL final : public OpenGLPlatform {
public:
PlatformCocoaGL();
~PlatformCocoaGL() noexcept final;
Driver* createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept override;
void terminate() noexcept final;
SwapChain* createSwapChain(void* nativewindow, uint64_t& flags) noexcept final;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t& flags) noexcept final;
void destroySwapChain(SwapChain* swapChain) noexcept final;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept final;
void commit(SwapChain* swapChain) noexcept final;
Fence* createFence() noexcept final { return nullptr; }
void destroyFence(Fence* fence) noexcept final {}
FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept final {
return FenceStatus::ERROR;
}
void setPresentationTime(int64_t presentationTimeInNanosecond) noexcept final {}
Stream* createStream(void* nativeStream) noexcept final { return nullptr; }
void destroyStream(Stream* stream) noexcept final {}
void attach(Stream* stream, intptr_t tname) noexcept final {}
void detach(Stream* stream) noexcept final {}
void updateTexImage(Stream* stream, int64_t* timestamp) noexcept final {}
int getOSVersion() const noexcept final { return 0; }
bool pumpEvents() noexcept override;
private:
PlatformCocoaGLImpl* pImpl = nullptr;
};
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H

View File

@@ -17,9 +17,8 @@
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#include "PlatformCocoaGL.h"
#include <backend/platforms/PlatformCocoaGL.h>
#include "opengl/OpenGLDriverFactory.h"
#include "opengl/gl_headers.h"
#include <utils/compiler.h>
@@ -35,7 +34,7 @@ namespace filament::backend {
using namespace backend;
struct CocoaGLSwapChain : public Platform::SwapChain {
CocoaGLSwapChain(NSView* inView);
explicit CocoaGLSwapChain(NSView* inView);
~CocoaGLSwapChain() noexcept;
NSView* view;
@@ -160,7 +159,11 @@ Driver* PlatformCocoaGL::createDriver(void* sharedContext, const Platform::Drive
int result = bluegl::bind();
ASSERT_POSTCONDITION(!result, "Unable to load OpenGL entry points.");
return OpenGLDriverFactory::create(this, sharedContext, driverConfig);
return OpenGLPlatform::createDefaultDriver(this, sharedContext, driverConfig);
}
int PlatformCocoaGL::getOSVersion() const noexcept {
return 0;
}
void PlatformCocoaGL::terminate() noexcept {
@@ -168,9 +171,7 @@ void PlatformCocoaGL::terminate() noexcept {
bluegl::unbind();
}
Platform::SwapChain* PlatformCocoaGL::createSwapChain(void* nativewindow, uint64_t& flags) noexcept {
// Transparent SwapChain is not supported
flags &= ~SWAP_CHAIN_CONFIG_TRANSPARENT;
Platform::SwapChain* PlatformCocoaGL::createSwapChain(void* nativewindow, uint64_t flags) noexcept {
NSView* nsView = (__bridge NSView*)nativewindow;
CocoaGLSwapChain* swapChain = new CocoaGLSwapChain( nsView );
@@ -185,7 +186,7 @@ Platform::SwapChain* PlatformCocoaGL::createSwapChain(void* nativewindow, uint64
return swapChain;
}
Platform::SwapChain* PlatformCocoaGL::createSwapChain(uint32_t width, uint32_t height, uint64_t& flags) noexcept {
Platform::SwapChain* PlatformCocoaGL::createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept {
NSView* nsView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, width, height)];
// adding the pointer to the array retains the NSView

View File

@@ -1,75 +0,0 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_TOUCH_GL_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_TOUCH_GL_H
#include <stdint.h>
#include <backend/DriverEnums.h>
#include "private/backend/OpenGLPlatform.h"
namespace filament::backend {
struct PlatformCocoaTouchGLImpl;
class PlatformCocoaTouchGL final : public OpenGLPlatform {
public:
PlatformCocoaTouchGL();
~PlatformCocoaTouchGL() noexcept final;
Driver* createDriver(void* sharedGLContext, const Platform::DriverConfig& driverConfig) noexcept override;
void terminate() noexcept final;
SwapChain* createSwapChain(void* nativewindow, uint64_t& flags) noexcept final;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t& flags) noexcept final;
void destroySwapChain(SwapChain* swapChain) noexcept final;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept final;
void commit(SwapChain* swapChain) noexcept final;
void createDefaultRenderTarget(uint32_t& framebuffer, uint32_t& colorbuffer,
uint32_t& depthbuffer) noexcept final;
Fence* createFence() noexcept final { return nullptr; }
void destroyFence(Fence* fence) noexcept final {}
FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept final {
return FenceStatus::ERROR;
}
void setPresentationTime(int64_t time) noexcept final override {}
Stream* createStream(void* nativeStream) noexcept final { return nullptr; }
void destroyStream(Stream* stream) noexcept final {}
void attach(Stream* stream, intptr_t tname) noexcept final {}
void detach(Stream* stream) noexcept final {}
void updateTexImage(Stream* stream, int64_t* timestamp) noexcept final {}
int getOSVersion() const noexcept final { return 0; }
bool setExternalImage(void* externalImage, void* texture) noexcept final;
void retainExternalImage(void* externalImage) noexcept final;
void releaseExternalImage(void* externalImage) noexcept final;
void createExternalImageTexture(void* texture) noexcept final;
void destroyExternalImage(void* texture) noexcept final;
private:
PlatformCocoaTouchGLImpl* pImpl = nullptr;
};
using ContextManager = PlatformCocoaTouchGL;
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_TOUCH_GL_H

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "PlatformCocoaTouchGL.h"
#include <backend/platforms/PlatformCocoaTouchGL.h>
#define GLES_SILENCE_DEPRECATION
#include <OpenGLES/EAGL.h>
@@ -30,9 +30,6 @@
#include <utils/Panic.h>
#include "../OpenGLDriverFactory.h"
#include "../OpenGLDriver.h"
#include "CocoaTouchExternalImage.h"
namespace filament::backend {
@@ -87,13 +84,13 @@ Driver* PlatformCocoaTouchGL::createDriver(void* const sharedGLContext, const Pl
pImpl->mDefaultColorbuffer = renderbuffer[0];
pImpl->mDefaultDepthbuffer = renderbuffer[1];
CVReturn success = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, nullptr,
pImpl->mGLContext, nullptr, &pImpl->mTextureCache);
UTILS_UNUSED_IN_RELEASE CVReturn success = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault,
nullptr, pImpl->mGLContext, nullptr, &pImpl->mTextureCache);
assert_invariant(success == kCVReturnSuccess);
pImpl->mExternalImageSharedGl = new CocoaTouchExternalImage::SharedGl();
return OpenGLDriverFactory::create(this, sharedGLContext, driverConfig);
return OpenGLPlatform::createDefaultDriver(this, sharedGLContext, driverConfig);
}
void PlatformCocoaTouchGL::terminate() noexcept {
@@ -102,13 +99,11 @@ void PlatformCocoaTouchGL::terminate() noexcept {
delete pImpl->mExternalImageSharedGl;
}
Platform::SwapChain* PlatformCocoaTouchGL::createSwapChain(void* nativewindow, uint64_t& flags) noexcept {
// Transparent swap chain is not supported
flags &= ~SWAP_CHAIN_CONFIG_TRANSPARENT;
Platform::SwapChain* PlatformCocoaTouchGL::createSwapChain(void* nativewindow, uint64_t flags) noexcept {
return (SwapChain*) nativewindow;
}
Platform::SwapChain* PlatformCocoaTouchGL::createSwapChain(uint32_t width, uint32_t height, uint64_t& flags) noexcept {
Platform::SwapChain* PlatformCocoaTouchGL::createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept {
CAEAGLLayer* glLayer = [CAEAGLLayer layer];
glLayer.frame = CGRectMake(0, 0, width, height);
@@ -133,11 +128,8 @@ void PlatformCocoaTouchGL::destroySwapChain(Platform::SwapChain* swapChain) noex
}
}
void PlatformCocoaTouchGL::createDefaultRenderTarget(uint32_t& framebuffer, uint32_t& colorbuffer,
uint32_t& depthbuffer) noexcept {
framebuffer = pImpl->mDefaultFramebuffer;
colorbuffer = pImpl->mDefaultColorbuffer;
depthbuffer = pImpl->mDefaultDepthbuffer;
uint32_t PlatformCocoaTouchGL::createDefaultRenderTarget() noexcept {
return pImpl->mDefaultFramebuffer;
}
void PlatformCocoaTouchGL::makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept {
@@ -180,23 +172,18 @@ void PlatformCocoaTouchGL::commit(Platform::SwapChain* swapChain) noexcept {
CVOpenGLESTextureCacheFlush(pImpl->mTextureCache, 0);
}
bool PlatformCocoaTouchGL::setExternalImage(void* externalImage, void* texture) noexcept {
CVPixelBufferRef cvPixelBuffer = (CVPixelBufferRef) externalImage;
auto* driverTexture = (OpenGLDriver::GLTexture*) texture;
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;
}
CocoaTouchExternalImage* cocoaExternalImage = (CocoaTouchExternalImage*) driverTexture->platformPImpl;
if (!cocoaExternalImage->set(cvPixelBuffer)) {
return false;
}
driverTexture->gl.id = cocoaExternalImage->getGlTexture();
driverTexture->gl.internalFormat = cocoaExternalImage->getInternalFormat();
driverTexture->gl.target = cocoaExternalImage->getTarget();
driverTexture->gl.baseLevel = 0;
driverTexture->gl.maxLevel = 0;
return true;
void PlatformCocoaTouchGL::destroyExternalImage(ExternalTexture* texture) noexcept {
auto* p = static_cast<CocoaTouchExternalImage*>(texture);
delete p;
}
void PlatformCocoaTouchGL::retainExternalImage(void* externalImage) noexcept {
@@ -206,22 +193,17 @@ void PlatformCocoaTouchGL::retainExternalImage(void* externalImage) noexcept {
CVPixelBufferRetain(pixelBuffer);
}
void PlatformCocoaTouchGL::releaseExternalImage(void* externalImage) noexcept {
CVPixelBufferRef pixelBuffer = (CVPixelBufferRef) externalImage;
CVPixelBufferRelease(pixelBuffer);
}
void PlatformCocoaTouchGL::createExternalImageTexture(void* texture) noexcept {
auto* driverTexture = (OpenGLDriver::GLTexture*) texture;
driverTexture->platformPImpl = new CocoaTouchExternalImage(pImpl->mTextureCache,
*pImpl->mExternalImageSharedGl);
}
void PlatformCocoaTouchGL::destroyExternalImage(void* texture) noexcept {
auto* driverTexture = (OpenGLDriver::GLTexture*) texture;
auto* p = (CocoaTouchExternalImage*) driverTexture->platformPImpl;
delete p;
bool PlatformCocoaTouchGL::setExternalImage(void* externalImage, ExternalTexture* texture) noexcept {
CVPixelBufferRef cvPixelBuffer = (CVPixelBufferRef) externalImage;
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

View File

@@ -14,11 +14,9 @@
* limitations under the License.
*/
#include "PlatformEGL.h"
#include <backend/platforms/PlatformEGL.h>
#include "opengl/OpenGLDriver.h"
#include "opengl/OpenGLContext.h"
#include "opengl/OpenGLDriverFactory.h"
#include "opengl/GLUtils.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
@@ -31,7 +29,7 @@ using namespace utils;
namespace filament::backend {
using namespace backend;
// The Android NDK doesn't exposes extensions, fake it with eglGetProcAddress
// The Android NDK doesn't expose extensions, fake it with eglGetProcAddress
namespace glext {
UTILS_PRIVATE PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR = {};
UTILS_PRIVATE PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR = {};
@@ -70,7 +68,7 @@ void PlatformEGL::logEglError(const char* name) noexcept {
void PlatformEGL::clearGlError() noexcept {
// clear GL error that may have been set by previous calls
GLenum error = glGetError();
GLenum const error = glGetError();
if (error != GL_NO_ERROR) {
slog.w << "Ignoring pending GL error " << io::hex << error << io::endl;
}
@@ -80,25 +78,31 @@ void PlatformEGL::clearGlError() noexcept {
PlatformEGL::PlatformEGL() noexcept = default;
int PlatformEGL::getOSVersion() const noexcept {
return 0;
}
Driver* PlatformEGL::createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept {
mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
assert_invariant(mEGLDisplay != EGL_NO_DISPLAY);
EGLint major, minor;
EGLBoolean initialized = eglInitialize(mEGLDisplay, &major, &minor);
EGLBoolean const initialized = eglInitialize(mEGLDisplay, &major, &minor);
if (UTILS_UNLIKELY(!initialized)) {
slog.e << "eglInitialize failed" << io::endl;
return nullptr;
}
#if defined(__ANDROID__) || defined(FILAMENT_USE_EXTERNAL_GLES3) || defined(__EMSCRIPTEN__)
// PlatofrmEGL is used with and without GLES, but this function is only
// meaningful when GLES is used.
#if defined(FILAMENT_IMPORT_ENTRY_POINTS)
importGLESExtensionsEntryPoints();
#endif
auto extensions = GLUtils::split(eglQueryString(mEGLDisplay, EGL_EXTENSIONS));
ext.egl.KHR_no_config_context = extensions.has("EGL_KHR_no_config_context");
ext.egl.KHR_gl_colorspace = extensions.has("EGL_KHR_gl_colorspace");
eglCreateSyncKHR = (PFNEGLCREATESYNCKHRPROC) eglGetProcAddress("eglCreateSyncKHR");
eglDestroySyncKHR = (PFNEGLDESTROYSYNCKHRPROC) eglGetProcAddress("eglDestroySyncKHR");
eglClientWaitSyncKHR = (PFNEGLCLIENTWAITSYNCKHRPROC) eglGetProcAddress("eglClientWaitSyncKHR");
@@ -112,7 +116,7 @@ Driver* PlatformEGL::createDriver(void* sharedContext, const Platform::DriverCon
EGL_RED_SIZE, 8, // 2
EGL_GREEN_SIZE, 8, // 4
EGL_BLUE_SIZE, 8, // 6
EGL_ALPHA_SIZE, 0, // 8 : reserved to set ALPHA_SIZE below
EGL_ALPHA_SIZE, 8, // 8
EGL_DEPTH_SIZE, 24, // 10
EGL_RECORDABLE_ANDROID, 1, // 12
EGL_NONE // 14
@@ -131,7 +135,7 @@ Driver* PlatformEGL::createDriver(void* sharedContext, const Platform::DriverCon
};
#ifdef NDEBUG
// When we don't have a shared context and we're in release mode, we always activate the
// When we don't have a shared context, and we're in release mode, we always activate the
// EGL_KHR_create_context_no_error extension.
if (!sharedContext && extensions.has("EGL_KHR_create_context_no_error")) {
contextAttribs[2] = EGL_CONTEXT_OPENGL_NO_ERROR_KHR;
@@ -139,66 +143,46 @@ Driver* PlatformEGL::createDriver(void* sharedContext, const Platform::DriverCon
}
#endif
EGLConfig eglConfig = nullptr;
// config use for creating the context
EGLConfig eglConfig = EGL_NO_CONFIG_KHR;
// find an opaque config
// find a config we can use if we don't have "EGL_KHR_no_config_context" and that we can use
// for the dummy pbuffer surface.
if (!eglChooseConfig(mEGLDisplay, configAttribs, &mEGLConfig, 1, &configsCount)) {
logEglError("eglChooseConfig");
goto error;
}
if (configsCount == 0) {
// warn and retry without EGL_RECORDABLE_ANDROID
logEglError("eglChooseConfig(..., EGL_RECORDABLE_ANDROID) failed. Continuing without it.");
configAttribs[12] = EGL_RECORDABLE_ANDROID;
configAttribs[13] = EGL_DONT_CARE;
if (!eglChooseConfig(mEGLDisplay, configAttribs, &mEGLConfig, 1, &configsCount) ||
configsCount == 0) {
logEglError("eglChooseConfig");
goto error;
}
}
// find a transparent config
configAttribs[8] = EGL_ALPHA_SIZE;
configAttribs[9] = 8;
if (!eglChooseConfig(mEGLDisplay, configAttribs, &mEGLTransparentConfig, 1, &configsCount) ||
(configAttribs[13] == EGL_DONT_CARE && configsCount == 0)) {
logEglError("eglChooseConfig");
goto error;
}
if (configsCount == 0) {
// warn and retry without EGL_RECORDABLE_ANDROID
// warn and retry without EGL_RECORDABLE_ANDROID
logEglError("eglChooseConfig(..., EGL_RECORDABLE_ANDROID) failed. Continuing without it.");
// this is not fatal
configAttribs[12] = EGL_RECORDABLE_ANDROID;
configAttribs[13] = EGL_DONT_CARE;
if (!eglChooseConfig(mEGLDisplay, configAttribs, &mEGLTransparentConfig, 1, &configsCount) ||
configsCount == 0) {
logEglError("eglChooseConfig");
goto error;
}
// this is not fatal
configAttribs[12] = EGL_RECORDABLE_ANDROID;
configAttribs[13] = EGL_DONT_CARE;
if (!eglChooseConfig(mEGLDisplay, configAttribs, &mEGLConfig, 1, &configsCount) ||
configsCount == 0) {
logEglError("eglChooseConfig");
goto error;
}
}
if (!extensions.has("EGL_KHR_no_config_context")) {
// if we have the EGL_KHR_no_config_context, we don't need to worry about the config
// when creating the context, otherwise, we must always pick a transparent config.
eglConfig = mEGLConfig = mEGLTransparentConfig;
if (UTILS_UNLIKELY(!ext.egl.KHR_no_config_context)) {
// if we don't have the EGL_KHR_no_config_context the context must be created with
// the same config as the swapchain, so we have no choice but to create a
// transparent config.
eglConfig = mEGLConfig;
}
// the pbuffer dummy surface is always created with a transparent surface because
// either we have EGL_KHR_no_config_context and it doesn't matter, or we don't and
// we must use a transparent surface
mEGLDummySurface = eglCreatePbufferSurface(mEGLDisplay, mEGLTransparentConfig, pbufferAttribs);
if (mEGLDummySurface == EGL_NO_SURFACE) {
// create the dummy surface, just for being able to make the context current.
mEGLDummySurface = eglCreatePbufferSurface(mEGLDisplay, mEGLConfig, pbufferAttribs);
if (UTILS_UNLIKELY(mEGLDummySurface == EGL_NO_SURFACE)) {
logEglError("eglCreatePbufferSurface");
goto error;
}
mEGLContext = eglCreateContext(mEGLDisplay, eglConfig, (EGLContext)sharedContext, contextAttribs);
if (mEGLContext == EGL_NO_CONTEXT && sharedContext &&
extensions.has("EGL_KHR_create_context_no_error")) {
if (UTILS_UNLIKELY(mEGLContext == EGL_NO_CONTEXT && sharedContext &&
extensions.has("EGL_KHR_create_context_no_error"))) {
// context creation could fail because of EGL_CONTEXT_OPENGL_NO_ERROR_KHR
// not matching the sharedContext. Try with it.
contextAttribs[2] = EGL_CONTEXT_OPENGL_NO_ERROR_KHR;
@@ -211,7 +195,7 @@ Driver* PlatformEGL::createDriver(void* sharedContext, const Platform::DriverCon
goto error;
}
if (!makeCurrent(mEGLDummySurface, mEGLDummySurface)) {
if (UTILS_UNLIKELY(!makeCurrent(mEGLDummySurface, mEGLDummySurface))) {
// eglMakeCurrent failed
logEglError("eglMakeCurrent");
goto error;
@@ -223,7 +207,7 @@ Driver* PlatformEGL::createDriver(void* sharedContext, const Platform::DriverCon
clearGlError();
// success!!
return OpenGLDriverFactory::create(this, sharedContext, driverConfig);
return OpenGLPlatform::createDefaultDriver(this, sharedContext, driverConfig);
error:
// if we're here, we've failed
@@ -260,36 +244,115 @@ void PlatformEGL::terminate() noexcept {
eglReleaseThread();
}
EGLConfig PlatformEGL::findSwapChainConfig(uint64_t flags) const {
EGLConfig config = EGL_NO_CONFIG_KHR;
EGLint configsCount;
EGLint configAttribs[] = {
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, (flags & SWAP_CHAIN_CONFIG_TRANSPARENT) ? 8 : 0,
EGL_DEPTH_SIZE, 24,
EGL_RECORDABLE_ANDROID, 1,
EGL_NONE
};
if (UTILS_UNLIKELY(
!eglChooseConfig(mEGLDisplay, configAttribs, &config, 1, &configsCount))) {
logEglError("eglChooseConfig");
return EGL_NO_CONFIG_KHR;
}
if (UTILS_UNLIKELY(configsCount == 0)) {
// warn and retry without EGL_RECORDABLE_ANDROID
logEglError(
"eglChooseConfig(..., EGL_RECORDABLE_ANDROID) failed. Continuing without it.");
configAttribs[12] = EGL_RECORDABLE_ANDROID;
configAttribs[13] = EGL_DONT_CARE;
if (UTILS_UNLIKELY(
!eglChooseConfig(mEGLDisplay, configAttribs, &config, 1, &configsCount) ||
configsCount == 0)) {
logEglError("eglChooseConfig");
return EGL_NO_CONFIG_KHR;
}
}
return config;
}
bool PlatformEGL::isSRGBSwapChainSupported() const noexcept {
return ext.egl.KHR_gl_colorspace;
}
Platform::SwapChain* PlatformEGL::createSwapChain(
void* nativeWindow, uint64_t& flags) noexcept {
EGLSurface sur = eglCreateWindowSurface(mEGLDisplay,
(flags & SWAP_CHAIN_CONFIG_TRANSPARENT) ?
mEGLTransparentConfig : mEGLConfig,
(EGLNativeWindowType)nativeWindow, nullptr);
void* nativeWindow, uint64_t flags) noexcept {
EGLConfig config = EGL_NO_CONFIG_KHR;
if (UTILS_LIKELY(ext.egl.KHR_no_config_context)) {
config = findSwapChainConfig(flags);
} else {
config = mEGLConfig;
}
if (UTILS_UNLIKELY(config == EGL_NO_CONFIG_KHR)) {
return nullptr;
}
EGLint attribs[] = {
EGL_NONE, EGL_NONE,
EGL_NONE
};
if (ext.egl.KHR_gl_colorspace) {
if (flags & SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) {
attribs[0] = EGL_GL_COLORSPACE_KHR;
attribs[1] = EGL_GL_COLORSPACE_SRGB_KHR;
}
}
EGLSurface sur = eglCreateWindowSurface(mEGLDisplay, config,
(EGLNativeWindowType)nativeWindow, attribs);
if (UTILS_UNLIKELY(sur == EGL_NO_SURFACE)) {
logEglError("eglCreateWindowSurface");
return nullptr;
}
if (!eglSurfaceAttrib(mEGLDisplay, sur, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED)) {
logEglError("eglSurfaceAttrib(..., EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED)");
// this is not fatal
}
// this is not fatal
eglSurfaceAttrib(mEGLDisplay, sur, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED);
return (SwapChain*)sur;
}
Platform::SwapChain* PlatformEGL::createSwapChain(
uint32_t width, uint32_t height, uint64_t& flags) noexcept {
uint32_t width, uint32_t height, uint64_t flags) noexcept {
EGLConfig config = EGL_NO_CONFIG_KHR;
if (UTILS_LIKELY(ext.egl.KHR_no_config_context)) {
config = findSwapChainConfig(flags);
} else {
config = mEGLConfig;
}
if (UTILS_UNLIKELY(config == EGL_NO_CONFIG_KHR)) {
return nullptr;
}
EGLint attribs[] = {
EGL_WIDTH, EGLint(width),
EGL_HEIGHT, EGLint(height),
EGL_NONE, EGL_NONE,
EGL_NONE
};
EGLSurface sur = eglCreatePbufferSurface(mEGLDisplay,
(flags & SWAP_CHAIN_CONFIG_TRANSPARENT) ?
mEGLTransparentConfig : mEGLConfig, attribs);
if (ext.egl.KHR_gl_colorspace) {
if (flags & SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) {
attribs[4] = EGL_GL_COLORSPACE_KHR;
attribs[5] = EGL_GL_COLORSPACE_SRGB_KHR;
}
}
EGLSurface sur = eglCreatePbufferSurface(mEGLDisplay, config, attribs);
if (UTILS_UNLIKELY(sur == EGL_NO_SURFACE)) {
logEglError("eglCreatePbufferSurface");
@@ -322,6 +385,10 @@ void PlatformEGL::commit(Platform::SwapChain* swapChain) noexcept {
}
}
bool PlatformEGL::canCreateFence() noexcept {
return true;
}
Platform::Fence* PlatformEGL::createFence() noexcept {
Fence* f = nullptr;
#ifdef EGL_KHR_reusable_sync
@@ -356,24 +423,34 @@ FenceStatus PlatformEGL::waitFence(
return FenceStatus::ERROR;
}
void PlatformEGL::createExternalImageTexture(void* texture) noexcept {
auto* t = (OpenGLDriver::GLTexture*) texture;
glGenTextures(1, &t->gl.id);
if (UTILS_LIKELY(ext.OES_EGL_image_external_essl3)) {
t->gl.target = GL_TEXTURE_EXTERNAL_OES;
t->gl.targetIndex = (uint8_t)
OpenGLContext::getIndexForTextureTarget(GL_TEXTURE_EXTERNAL_OES);
OpenGLPlatform::ExternalTexture* PlatformEGL::createExternalImageTexture() noexcept {
ExternalTexture* outTexture = new 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
t->gl.target = GL_TEXTURE_2D;
t->gl.targetIndex = (uint8_t)
OpenGLContext::getIndexForTextureTarget(GL_TEXTURE_2D);
outTexture->target = GL_TEXTURE_2D;
}
return outTexture;
}
void PlatformEGL::destroyExternalImage(void* texture) noexcept {
auto* t = (OpenGLDriver::GLTexture*) texture;
glDeleteTextures(1, &t->gl.id);
void PlatformEGL::destroyExternalImage(ExternalTexture* texture) noexcept {
glDeleteTextures(1, &texture->id);
delete texture;
}
bool PlatformEGL::setExternalImage(void* externalImage,
UTILS_UNUSED_IN_RELEASE ExternalTexture* texture) noexcept {
if (UTILS_LIKELY(ext.gl.OES_EGL_image_external_essl3)) {
assert_invariant(texture->target == GL_TEXTURE_EXTERNAL_OES);
// the texture is guaranteed to be bound here.
#ifdef GL_OES_EGL_image
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES,
static_cast<GLeglImageOES>(externalImage));
#endif
}
return true;
}
void PlatformEGL::initializeGlExtensions() noexcept {
@@ -384,7 +461,7 @@ void PlatformEGL::initializeGlExtensions() noexcept {
const char * const extension = (const char*) glGetStringi(GL_EXTENSIONS, (GLuint)i);
glExtensions.insert(extension);
}
ext.OES_EGL_image_external_essl3 = glExtensions.has("GL_OES_EGL_image_external_essl3");
ext.gl.OES_EGL_image_external_essl3 = glExtensions.has("GL_OES_EGL_image_external_essl3");
}
} // namespace filament::backend

View File

@@ -14,13 +14,10 @@
* limitations under the License.
*/
#include "PlatformEGLAndroid.h"
#include "opengl/OpenGLDriver.h"
#include "opengl/OpenGLContext.h"
#include <backend/platforms/PlatformEGLAndroid.h>
#include "opengl/GLUtils.h"
#include "ExternalStreamManagerAndroid.h"
#include "private/backend/VirtualMachineEnv.h"
#include <android/api-level.h>
@@ -32,10 +29,7 @@
#include <sys/system_properties.h>
#include <jni.h>
// We require filament to be built with a API 19 toolchain, before that, OpenGLES 3.0 didn't exist
// We require filament to be built with an API 19 toolchain, before that, OpenGLES 3.0 didn't exist
// Actually, OpenGL ES 3.0 was added to API 18, but API 19 is the better target and
// the minimum for Jetpack at the time of this comment.
#if __ANDROID_API__ < 19
@@ -47,7 +41,7 @@ using namespace utils;
namespace filament::backend {
using namespace backend;
// The Android NDK doesn't exposes extensions, fake it with eglGetProcAddress
// The Android NDK doesn't expose extensions, fake it with eglGetProcAddress
namespace glext {
extern PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR;
@@ -76,7 +70,7 @@ PlatformEGLAndroid::PlatformEGLAndroid() noexcept
char scratch[PROP_VALUE_MAX + 1];
int length = __system_property_get("ro.build.version.release", scratch);
int androidVersion = length >= 0 ? atoi(scratch) : 1;
int const androidVersion = length >= 0 ? atoi(scratch) : 1;
if (!androidVersion) {
mOSVersion = 1000; // if androidVersion is 0, it means "future"
} else {
@@ -105,7 +99,8 @@ void PlatformEGLAndroid::terminate() noexcept {
PlatformEGL::terminate();
}
Driver* PlatformEGLAndroid::createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept {
Driver* PlatformEGLAndroid::createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) noexcept {
Driver* driver = PlatformEGL::createDriver(sharedContext, driverConfig);
auto extensions = GLUtils::split(eglQueryString(mEGLDisplay, EGL_EXTENSIONS));

View File

@@ -1,55 +0,0 @@
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H
#include "PlatformEGL.h"
namespace filament::backend {
class ExternalStreamManagerAndroid;
class PlatformEGLAndroid final : public PlatformEGL {
public:
PlatformEGLAndroid() noexcept;
~PlatformEGLAndroid() noexcept override;
void terminate() noexcept override;
Driver* createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept final;
int getOSVersion() const noexcept final;
void setPresentationTime(int64_t presentationTimeInNanosecond) noexcept final;
Stream* createStream(void* nativeStream) noexcept final;
void destroyStream(Stream* stream) noexcept final;
void attach(Stream* stream, intptr_t tname) noexcept final;
void detach(Stream* stream) noexcept final;
void updateTexImage(Stream* stream, int64_t* timestamp) noexcept final;
AcquiredImage transformAcquiredImage(AcquiredImage source) noexcept final;
private:
int mOSVersion;
ExternalStreamManagerAndroid& mExternalStreamManager;
};
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H

View File

@@ -14,11 +14,9 @@
* limitations under the License.
*/
#include "PlatformEGLHeadless.h"
#include <backend/platforms/PlatformEGLHeadless.h>
#include "opengl/OpenGLDriver.h"
#include "opengl/OpenGLContext.h"
#include "opengl/OpenGLDriverFactory.h"
#include "opengl/GLUtils.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
@@ -47,7 +45,8 @@ PlatformEGLHeadless::PlatformEGLHeadless() noexcept
: PlatformEGL() {
}
backend::Driver* PlatformEGLHeadless::createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept {
backend::Driver* PlatformEGLHeadless::createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) noexcept {
EGLBoolean bindAPI = eglBindAPI(EGL_OPENGL_API);
if (UTILS_UNLIKELY(!bindAPI)) {
slog.e << "eglBindAPI EGL_OPENGL_API failed" << io::endl;
@@ -199,7 +198,7 @@ backend::Driver* PlatformEGLHeadless::createDriver(void* sharedContext, const Pl
clearGlError();
// success!!
return OpenGLDriverFactory::create(this, sharedContext, driverConfig);
return OpenGLPlatform::createDefaultDriver(this, sharedContext, driverConfig);
error:
// if we're here, we've failed

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "PlatformGLX.h"
#include <backend/platforms/PlatformGLX.h>
#include <utils/Log.h>
#include <utils/Panic.h>
@@ -23,8 +23,6 @@
#include <GL/glx.h>
#include <GL/glxext.h>
#include "../OpenGLDriverFactory.h"
#include <dlfcn.h>
#define LIBRARY_GLX "libGL.so.1"
@@ -130,7 +128,8 @@ namespace filament::backend {
using namespace backend;
Driver* PlatformGLX::createDriver(void* const sharedGLContext, const DriverConfig& driverConfig) noexcept {
Driver* PlatformGLX::createDriver(void* const sharedGLContext,
const DriverConfig& driverConfig) noexcept {
loadLibraries();
// Get the display device
mGLXDisplay = g_x11.openDisplay(NULL);
@@ -229,7 +228,7 @@ Driver* PlatformGLX::createDriver(void* const sharedGLContext, const DriverConfi
int result = bluegl::bind();
ASSERT_POSTCONDITION(!result, "Unable to load OpenGL entry points.");
return OpenGLDriverFactory::create(this, sharedGLContext, driverConfig);
return OpenGLPlatform::createDefaultDriver(this, sharedGLContext, driverConfig);
}
void PlatformGLX::terminate() noexcept {
@@ -240,16 +239,12 @@ void PlatformGLX::terminate() noexcept {
bluegl::unbind();
}
Platform::SwapChain* PlatformGLX::createSwapChain(void* nativeWindow, uint64_t& flags) noexcept {
// Transparent swap chain is not supported
flags &= ~SWAP_CHAIN_CONFIG_TRANSPARENT;
Platform::SwapChain* PlatformGLX::createSwapChain(void* nativeWindow, uint64_t flags) noexcept {
return (SwapChain*)nativeWindow;
}
Platform::SwapChain* PlatformGLX::createSwapChain(
uint32_t width, uint32_t height, uint64_t& flags) noexcept {
// Transparent swap chain is not supported
flags &= ~SWAP_CHAIN_CONFIG_TRANSPARENT;
uint32_t width, uint32_t height, uint64_t flags) noexcept {
int pbufferAttribs[] = {
GLX_PBUFFER_WIDTH, int(width),
GLX_PBUFFER_HEIGHT, int(height),
@@ -280,18 +275,4 @@ void PlatformGLX::commit(Platform::SwapChain* swapChain) noexcept {
g_glx.swapBuffers(mGLXDisplay, (GLXDrawable)swapChain);
}
// TODO Implement GLX fences
Platform::Fence* PlatformGLX::createFence() noexcept {
Fence* f = new Fence();
return f;
}
void PlatformGLX::destroyFence(Fence* fence) noexcept {
delete fence;
}
FenceStatus PlatformGLX::waitFence(Fence* fence, uint64_t timeout) noexcept {
return FenceStatus::CONDITION_SATISFIED;
}
} // namespace filament::backend

View File

@@ -14,12 +14,10 @@
* limitations under the License.
*/
#include "PlatformWGL.h"
#include <backend/platforms/PlatformWGL.h>
#include <Wingdi.h>
#include "../OpenGLDriverFactory.h"
#ifdef _MSC_VER
// this variable is checked in BlueGL.h (included from "gl_headers.h" right after this),
// and prevents duplicate definition of OpenGL apis when building this file.
@@ -76,7 +74,8 @@ struct WGLSwapChain {
bool isHeadless = false;
};
Driver* PlatformWGL::createDriver(void* const sharedGLContext, const Platform::DriverConfig& driverConfig) noexcept {
Driver* PlatformWGL::createDriver(void* const sharedGLContext,
const Platform::DriverConfig& driverConfig) noexcept {
int result = 0;
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs = nullptr;
int pixelFormat = 0;
@@ -146,7 +145,8 @@ Driver* PlatformWGL::createDriver(void* const sharedGLContext, const Platform::D
result = bluegl::bind();
ASSERT_POSTCONDITION(!result, "Unable to load OpenGL entry points.");
return OpenGLDriverFactory::create(this, sharedGLContext, driverConfig);
return OpenGLPlatform::createDefaultDriver(this, sharedGLContext, driverConfig);
error:
if (tempContext) {
@@ -175,7 +175,7 @@ void PlatformWGL::terminate() noexcept {
bluegl::unbind();
}
Platform::SwapChain* PlatformWGL::createSwapChain(void* nativeWindow, uint64_t& flags) noexcept {
Platform::SwapChain* PlatformWGL::createSwapChain(void* nativeWindow, uint64_t flags) noexcept {
auto* swapChain = new WGLSwapChain();
swapChain->isHeadless = false;
@@ -194,7 +194,7 @@ Platform::SwapChain* PlatformWGL::createSwapChain(void* nativeWindow, uint64_t&
return (Platform::SwapChain*) swapChain;
}
Platform::SwapChain* PlatformWGL::createSwapChain(uint32_t width, uint32_t height, uint64_t& flags) noexcept {
Platform::SwapChain* PlatformWGL::createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept {
auto* swapChain = new WGLSwapChain();
swapChain->isHeadless = true;
@@ -256,16 +256,4 @@ void PlatformWGL::commit(Platform::SwapChain* swapChain) noexcept {
}
}
//TODO Implement WGL fences
Platform::Fence* PlatformWGL::createFence() noexcept {
return nullptr;
}
void PlatformWGL::destroyFence(Fence* fence) noexcept {
}
FenceStatus PlatformWGL::waitFence(Fence* fence, uint64_t timeout) noexcept {
return FenceStatus::ERROR;
}
} // namespace filament::backend

View File

@@ -14,27 +14,31 @@
* limitations under the License.
*/
#include "PlatformWebGL.h"
#include "../OpenGLDriverFactory.h"
#include <backend/platforms/PlatformWebGL.h>
namespace filament::backend {
using namespace backend;
Driver* PlatformWebGL::createDriver(void* const sharedGLContext, const Platform::DriverConfig& driverConfig) noexcept {
return OpenGLDriverFactory::create(this, sharedGLContext, driverConfig);
Driver* PlatformWebGL::createDriver(void* const sharedGLContext,
const Platform::DriverConfig& driverConfig) noexcept {
return OpenGLPlatform::createDefaultDriver(this, sharedGLContext, driverConfig);
}
int PlatformWebGL::getOSVersion() const noexcept {
return 0;
}
void PlatformWebGL::terminate() noexcept {
}
Platform::SwapChain* PlatformWebGL::createSwapChain(
void* nativeWindow, uint64_t& flags) noexcept {
void* nativeWindow, uint64_t flags) noexcept {
return (SwapChain*)nativeWindow;
}
Platform::SwapChain* PlatformWebGL::createSwapChain(
uint32_t width, uint32_t height, uint64_t& flags) noexcept {
uint32_t width, uint32_t height, uint64_t flags) noexcept {
// TODO: implement headless SwapChain
return nullptr;
}
@@ -49,17 +53,4 @@ void PlatformWebGL::makeCurrent(Platform::SwapChain* drawSwapChain,
void PlatformWebGL::commit(Platform::SwapChain* swapChain) noexcept {
}
Platform::Fence* PlatformWebGL::createFence() noexcept {
Fence* f = new Fence();
return f;
}
void PlatformWebGL::destroyFence(Fence* fence) noexcept {
delete fence;
}
FenceStatus PlatformWebGL::waitFence(Fence* fence, uint64_t timeout) noexcept {
return FenceStatus::CONDITION_SATISFIED;
}
} // namespace filament::backend

View File

@@ -1,60 +0,0 @@
/*
* 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_BACKEND_OPENGL_OPENGL_PLATFORM_WEBGL_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_WEBGL_H
#include <stdint.h>
#include <backend/DriverEnums.h>
#include "private/backend/OpenGLPlatform.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
namespace filament::backend {
class PlatformWebGL final : public OpenGLPlatform {
public:
Driver* createDriver(void* const sharedGLContext, const Platform::DriverConfig& driverConfig) noexcept override;
void terminate() noexcept override;
SwapChain* createSwapChain(void* nativewindow, uint64_t& flags) noexcept final override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t& flags) noexcept final override;
void destroySwapChain(SwapChain* swapChain) noexcept final override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept final override;
void commit(SwapChain* swapChain) noexcept final override;
Fence* createFence() noexcept final override;
void destroyFence(Fence* fence) noexcept final override;
FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept final override;
void setPresentationTime(int64_t time) 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, int64_t* timestamp) noexcept final override {}
int getOSVersion() const noexcept final override { return 0; }
};
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_WEBGL_H

View File

@@ -29,23 +29,32 @@ using namespace bluevk;
namespace filament::backend {
Driver* PlatformVkAndroid::createDriver(void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept {
using SurfaceBundle = VulkanPlatform::SurfaceBundle;
Driver* PlatformVkAndroid::createDriver(void* const sharedContext,
const Platform::DriverConfig& driverConfig) noexcept {
ASSERT_PRECONDITION(sharedContext == nullptr, "Vulkan does not support shared contexts.");
static const char* requiredInstanceExtensions[] = { "VK_KHR_android_surface" };
return VulkanDriverFactory::create(this, requiredInstanceExtensions, 1, driverConfig);
}
void* PlatformVkAndroid::createVkSurfaceKHR(void* nativeWindow, void* vkinstance, uint64_t flags) noexcept {
SurfaceBundle PlatformVkAndroid::createVkSurfaceKHR(void* nativeWindow, void* vkinstance,
uint64_t flags) noexcept {
const VkInstance instance = (VkInstance) vkinstance;
ANativeWindow* aNativeWindow = (ANativeWindow*) nativeWindow;
VkAndroidSurfaceCreateInfoKHR createInfo {
.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
.window = aNativeWindow
};
VkSurfaceKHR surface = VK_NULL_HANDLE;
VkResult result = vkCreateAndroidSurfaceKHR(instance, &createInfo, VKALLOC, &surface);
SurfaceBundle bundle {
.surface = VK_NULL_HANDLE,
.width = 0,
.height = 0
};
VkResult result = vkCreateAndroidSurfaceKHR(instance, &createInfo, VKALLOC,
(VkSurfaceKHR*) &bundle.surface);
ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkCreateAndroidSurfaceKHR error.");
return (void*) surface;
return bundle;
}
} // namespace filament::backend

View File

@@ -20,7 +20,7 @@
#include <stdint.h>
#include <backend/DriverEnums.h>
#include "VulkanPlatform.h"
#include <backend/platforms/VulkanPlatform.h>
namespace filament::backend {
@@ -29,7 +29,8 @@ public:
Driver* createDriver(void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept override;
void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override;
VulkanPlatform::SurfaceBundle createVkSurfaceKHR(void* nativeWindow, void* instance,
uint64_t flags) noexcept override;
int getOSVersion() const noexcept override { return 0; }
};

View File

@@ -20,14 +20,15 @@
#include <stdint.h>
#include <backend/DriverEnums.h>
#include "VulkanPlatform.h"
#include <backend/platforms/VulkanPlatform.h>
namespace filament::backend {
class PlatformVkCocoa final : public VulkanPlatform {
public:
Driver* createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept override;
void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override;
VulkanPlatform::SurfaceBundle createVkSurfaceKHR(void* nativeWindow, void* instance,
uint64_t flags) noexcept override;
int getOSVersion() const noexcept override { return 0; }
};

View File

@@ -34,6 +34,8 @@ using namespace bluevk;
namespace filament::backend {
using SurfaceBundle = VulkanPlatform::SurfaceBundle;
Driver* PlatformVkCocoa::createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept {
ASSERT_PRECONDITION(sharedContext == nullptr, "Vulkan does not support shared contexts.");
static const char* requiredInstanceExtensions[] = {
@@ -42,21 +44,28 @@ Driver* PlatformVkCocoa::createDriver(void* sharedContext, const Platform::Drive
return VulkanDriverFactory::create(this, requiredInstanceExtensions, 1, driverConfig);
}
void* PlatformVkCocoa::createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept {
SurfaceBundle PlatformVkCocoa::createVkSurfaceKHR(void* nativeWindow, void* instance,
uint64_t flags) noexcept {
// Obtain the CAMetalLayer-backed view.
NSView* nsview = (__bridge NSView*) nativeWindow;
ASSERT_POSTCONDITION(nsview, "Unable to obtain Metal-backed NSView.");
// Create the VkSurface.
ASSERT_POSTCONDITION(vkCreateMacOSSurfaceMVK, "Unable to load vkCreateMacOSSurfaceMVK.");
VkSurfaceKHR surface = nullptr;
VkMacOSSurfaceCreateInfoMVK createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
createInfo.pView = (__bridge void*) nsview;
VkResult result = vkCreateMacOSSurfaceMVK((VkInstance) instance, &createInfo, VKALLOC, &surface);
SurfaceBundle bundle {
.surface = nullptr,
.width = 0,
.height = 0
};
VkResult result = vkCreateMacOSSurfaceMVK((VkInstance) instance, &createInfo, VKALLOC,
(VkSurfaceKHR*) &bundle.surface);
ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkCreateMacOSSurfaceMVK error.");
return surface;
return bundle;
}
} // namespace filament::backend

View File

@@ -20,14 +20,15 @@
#include <stdint.h>
#include <backend/DriverEnums.h>
#include "VulkanPlatform.h"
#include <backend/platforms/VulkanPlatform.h>
namespace filament::backend {
class PlatformVkCocoaTouch final : public VulkanPlatform {
public:
Driver* createDriver(void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept override;
void* createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept override;
VulkanPlatform::SurfaceBundle createVkSurfaceKHR(void* nativeWindow, void* instance,
uint64_t flags) noexcept override;
int getOSVersion() const noexcept override { return 0; }
};

View File

@@ -39,31 +39,37 @@ using namespace bluevk;
namespace filament::backend {
using SurfaceBundle = VulkanPlatform::SurfaceBundle;
Driver* PlatformVkCocoaTouch::createDriver(void* const sharedContext, const Platform::DriverConfig& driverConfig) noexcept {
ASSERT_PRECONDITION(sharedContext == nullptr, "Vulkan does not support shared contexts.");
static const char* requestedExtensions[] = {"VK_MVK_ios_surface"};
return VulkanDriverFactory::create(this, requestedExtensions, 1, driverConfig);
}
void* PlatformVkCocoaTouch::createVkSurfaceKHR(void* nativeWindow, void* instance, uint64_t flags) noexcept {
SurfaceBundle PlatformVkCocoaTouch::createVkSurfaceKHR(void* nativeWindow, void* instance,
uint64_t flags) noexcept {
SurfaceBundle bundle {
.surface = nullptr,
.width = 0,
.height = 0
};
#if METAL_AVAILABLE
CAMetalLayer* metalLayer = (CAMetalLayer*) nativeWindow;
// Create the VkSurface.
ASSERT_POSTCONDITION(vkCreateIOSSurfaceMVK, "Unable to load vkCreateIOSSurfaceMVK function.");
VkSurfaceKHR surface = nullptr;
VkIOSSurfaceCreateInfoMVK createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IOS_SURFACE_CREATE_INFO_MVK;
createInfo.pNext = NULL;
createInfo.flags = 0;
createInfo.pView = metalLayer;
VkResult result = vkCreateIOSSurfaceMVK((VkInstance) instance, &createInfo, VKALLOC, &surface);
ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkCreateIOSSurfaceMVK error.");
return surface;
#else
return nullptr;
VkResult result = vkCreateIOSSurfaceMVK((VkInstance) instance, &createInfo, VKALLOC,
(VkSurfaceKHR*) &bundle.surface);
ASSERT_POSTCONDITION(result == VK_SUCCESS, "vkCreateIOSSurfaceMVK error.");
#endif
return bundle;
}
} // namespace filament::backend

View File

@@ -28,6 +28,8 @@ using namespace bluevk;
namespace filament::backend {
using SurfaceBundle = VulkanPlatform::SurfaceBundle;
Driver* PlatformVkLinuxGGP::createDriver(
void* const sharedContext,
const Platform::DriverConfig& driverConfig) noexcept {
@@ -46,8 +48,13 @@ Driver* PlatformVkLinuxGGP::createDriver(
#endif
}
void* PlatformVkLinuxGGP::createVkSurfaceKHR(void* nativeWindow, void* instance,
uint64_t flags) noexcept {
SurfaceBundle PlatformVkLinuxGGP::createVkSurfaceKHR(void* nativeWindow, void* instance,
uint64_t flags) noexcept {
SurfaceBundle bundle {
.surface = nullptr,
.width = 0,
.height = 0
};
#if defined(FILAMENT_SUPPORTS_GGP)
VkStreamDescriptorSurfaceCreateInfoGGP surface_create_info = {
VK_STRUCTURE_TYPE_STREAM_DESCRIPTOR_SURFACE_CREATE_INFO_GGP};
@@ -59,16 +66,14 @@ void* PlatformVkLinuxGGP::createVkSurfaceKHR(void* nativeWindow, void* instance,
ASSERT_PRECONDITION(fpCreateStreamDescriptorSurfaceGGP != nullptr,
"Error getting VkInstance "
"function vkCreateStreamDescriptorSurfaceGGP");
VkSurfaceKHR surface = nullptr;
VkResult res = fpCreateStreamDescriptorSurfaceGGP(
static_cast<VkInstance>(instance), &surface_create_info, nullptr,
&surface);
(VkSurfaceKHR*) &bundle.surface);
ASSERT_PRECONDITION(res == VK_SUCCESS, "Error in vulkan: %d", res);
return surface;
#else
PANIC_PRECONDITION("Filament does not support GGP.");
return nullptr;
#endif
return bundle;
}
} // namespace filament::backend

Some files were not shown because too many files have changed in this diff Show More