Compare commits
94 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44125926d1 | ||
|
|
fbfd5ec0ec | ||
|
|
a74a95cc65 | ||
|
|
bc0ea16ff0 | ||
|
|
b2dc8aa84c | ||
|
|
9987e8b6ab | ||
|
|
0d9bdcc008 | ||
|
|
81fa33abeb | ||
|
|
af7f87e19b | ||
|
|
3073b03d56 | ||
|
|
23dab0a013 | ||
|
|
fd68144ba2 | ||
|
|
51e92cd142 | ||
|
|
50f33f7196 | ||
|
|
b5c634045e | ||
|
|
1f05531d53 | ||
|
|
88f382f0e3 | ||
|
|
3e59925900 | ||
|
|
1182d30fb9 | ||
|
|
095179eeb3 | ||
|
|
69b48eaadb | ||
|
|
4031c6f0d3 | ||
|
|
7a22f7dfc5 | ||
|
|
728ebf5023 | ||
|
|
62476d2f06 | ||
|
|
ea404f8d4f | ||
|
|
602a550d93 | ||
|
|
12abbe2d23 | ||
|
|
5fea428243 | ||
|
|
fb0ee97588 | ||
|
|
56ef48c9c3 | ||
|
|
47c3dd3dd1 | ||
|
|
9a3c9ccbf3 | ||
|
|
ef4dfcecd6 | ||
|
|
5943382d23 | ||
|
|
c181648bfa | ||
|
|
0cf78b3abe | ||
|
|
1dcf347b87 | ||
|
|
47714007f7 | ||
|
|
22889a7ad9 | ||
|
|
a14451d0ac | ||
|
|
5dfdab10b7 | ||
|
|
54277572d2 | ||
|
|
52f2c0e107 | ||
|
|
59abc8cc20 | ||
|
|
e15796b348 | ||
|
|
1711eaa4d6 | ||
|
|
acbd6a5ca8 | ||
|
|
775090fdda | ||
|
|
0915b86927 | ||
|
|
c10f7b01f4 | ||
|
|
84142ac506 | ||
|
|
ff190847a1 | ||
|
|
3ceec28189 | ||
|
|
d6f2e3b8e9 | ||
|
|
481038152f | ||
|
|
60bd72730d | ||
|
|
df30517743 | ||
|
|
8f80643c1a | ||
|
|
eabfd08473 | ||
|
|
a66af0ac58 | ||
|
|
15187e9d99 | ||
|
|
681e8f8b59 | ||
|
|
fbb406ca7d | ||
|
|
5aea9be2fb | ||
|
|
aacaf5055e | ||
|
|
a5dbddfd12 | ||
|
|
764a0df669 | ||
|
|
f04864c216 | ||
|
|
11a1b31a4c | ||
|
|
fb86a77cf8 | ||
|
|
d512357928 | ||
|
|
b850bc827e | ||
|
|
0229077293 | ||
|
|
23f2679bbe | ||
|
|
e6243b3df3 | ||
|
|
375b46d866 | ||
|
|
4577c8d57f | ||
|
|
24d1e9c3d2 | ||
|
|
f7a630d614 | ||
|
|
1c1cb11cf5 | ||
|
|
3ac8a6a21c | ||
|
|
c524c39867 | ||
|
|
ad02e483d0 | ||
|
|
e203edc12a | ||
|
|
5447baab00 | ||
|
|
904989f7f4 | ||
|
|
4846ccd86d | ||
|
|
0fd1c3182e | ||
|
|
7d80052dae | ||
|
|
b71ee48477 | ||
|
|
7a285dc55a | ||
|
|
a0f3a4d9bb | ||
|
|
304090d39f |
3
.github/workflows/mac-continuous.yml
vendored
3
.github/workflows/mac-continuous.yml
vendored
@@ -21,3 +21,6 @@ jobs:
|
||||
with:
|
||||
name: filament-mac
|
||||
path: out/filament-release-darwin.tgz
|
||||
- name: Check public headers
|
||||
run: |
|
||||
build/common/check-headers.sh out/release/filament/include
|
||||
|
||||
@@ -291,11 +291,11 @@ Alternatively you can build the AAR from the command line by executing the follo
|
||||
`android/` directory:
|
||||
|
||||
```
|
||||
$ ./gradlew -Pfilament_dist_dir=../../out/android-release/filament assembleRelease
|
||||
$ ./gradlew -Pcom.google.android.filament.dist-dir=../../out/android-release/filament assembleRelease
|
||||
```
|
||||
|
||||
The `-Pfilament_dist_dir` can be used to specify a different installation directory (it must match
|
||||
the CMake install prefix used in the previous steps).
|
||||
The `-Pcom.google.android.filament.dist-dir` can be used to specify a different installation
|
||||
directory (it must match the CMake install prefix used in the previous steps).
|
||||
|
||||
#### Using Filament's AAR
|
||||
|
||||
|
||||
@@ -502,11 +502,15 @@ function(list_licenses OUTPUT MODULES)
|
||||
foreach(module ${_MODULES})
|
||||
set(license_path "../../third_party/${module}/LICENSE")
|
||||
get_filename_component(fullname "${license_path}" ABSOLUTE)
|
||||
string(APPEND CONTENT "${STR_OPENER}License and copyrights for ${module}:\n${STR_CLOSER},\n")
|
||||
file(READ ${license_path} license_long)
|
||||
string(REPLACE "\n" "${STR_CLOSER},\n${STR_OPENER}" license ${license_long})
|
||||
string(APPEND CONTENT ${STR_OPENER}${license}\n${STR_CLOSER},)
|
||||
string(APPEND CONTENT "\n\n")
|
||||
if(EXISTS ${fullname})
|
||||
string(APPEND CONTENT "${STR_OPENER}License and copyrights for ${module}:\n${STR_CLOSER},\n")
|
||||
file(READ ${license_path} license_long)
|
||||
string(REPLACE "\n" "${STR_CLOSER},\n${STR_OPENER}" license ${license_long})
|
||||
string(APPEND CONTENT ${STR_OPENER}${license}\n${STR_CLOSER},)
|
||||
string(APPEND CONTENT "\n\n")
|
||||
else()
|
||||
message(AUTHOR_WARNING "${license_path} not found. You can ignore this warning if you have devendored ${module}.")
|
||||
endif()
|
||||
endforeach()
|
||||
configure_file(${FILAMENT}/build/licenses.inc.in ${OUTPUT})
|
||||
endfunction(list_licenses)
|
||||
@@ -522,7 +526,12 @@ function(combine_static_libs TARGET OUTPUT DEPS)
|
||||
# Loop through the dependent libraries and query their location on disk.
|
||||
set(DEPS_FILES )
|
||||
foreach(DEPENDENCY ${DEPS})
|
||||
list(APPEND DEPS_FILES "$<TARGET_FILE:${DEPENDENCY}>")
|
||||
if(TARGET ${DEPENDENCY})
|
||||
get_property(dep_type TARGET ${DEPENDENCY} PROPERTY TYPE)
|
||||
if(dep_type STREQUAL "STATIC_LIBRARY")
|
||||
list(APPEND DEPS_FILES "$<TARGET_FILE:${DEPENDENCY}>")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
add_custom_command(
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.12.7'
|
||||
implementation 'com.google.android.filament:filament-android:1.13.0'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -52,7 +52,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.12.7'
|
||||
pod 'Filament', '~> 1.13.0'
|
||||
```
|
||||
|
||||
### Snapshots
|
||||
|
||||
@@ -3,7 +3,52 @@
|
||||
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.
|
||||
|
||||
## v1.12.8 (currently main branch)
|
||||
## v1.13.1 (currently main branch)
|
||||
|
||||
## v1.13.0
|
||||
|
||||
- Android: Gradle configuration caching is now enabled.
|
||||
- Android: Filament's Gradle properties have all been renamed to `com.google.android.filament.xxx`
|
||||
where `xxx` is the property name. See `android/build.gradle` for a complete list [⚠️]
|
||||
- Android: The Gradle property `filament_tools_dir` (now called
|
||||
`com.google.android.filament.tools-dir`) does not have a default value anymore. Please specify one
|
||||
in your `gradle.properties` if you reuse the Gradle plugin in your projects [⚠️]
|
||||
- engine: Fix spotlights direction and falloff [⚠️ **Material breakage**].
|
||||
- engine: Improvements to VSM and spotlight shadows.
|
||||
|
||||
## v1.12.11
|
||||
|
||||
- Metal: Color grading performance improvement on M1 devices.
|
||||
- samples: Fix glitchy animation seen in gltf-viewer iOS sample.
|
||||
|
||||
## v1.12.10
|
||||
|
||||
- engine: rewrite dynamic resolution scaling controller for better accuracy and less jittering.
|
||||
- Java: fix missing ASTC texture enum.
|
||||
- tools: Fix normal map issues in mipgen.
|
||||
- WebGL: expose some `SurfaceOrientation` functions.
|
||||
|
||||
## v1.12.9
|
||||
|
||||
- engine: New API: `MultiSampleAntiAliasingOptions` and HDR-aware MSAA resolve. When `customResolve`
|
||||
is enabled, improves anti-aliasing quality [**NEW API**].
|
||||
- engine: Fixes and improvements for FSR.
|
||||
- engine: All APIs that take a callback as argument now also take a `CallbackHandler*`, a new
|
||||
interface that provides more flexibility around callback dispatch [**NEW API**].
|
||||
- Android: Fix JNI bindings for `DepthOfFieldOptions`.
|
||||
- Android: workarounds for Adreno-specific fraembuffer issue.
|
||||
- JavaScript: updates to JS bindings.
|
||||
|
||||
## v1.12.8
|
||||
|
||||
- engine: Added picking API to `View` [⚠️ **Materials need to be rebuilt to access this new feature**].
|
||||
- engine: A new `Engine::pumpMessageQueues()` method can be used to trigger all pending user
|
||||
callbacks right away [**NEW API**].
|
||||
- engine: new inline helpers to more easily use lambdas, functors and method callbacks with
|
||||
`{Pixel}BufferDescriptor`.
|
||||
- Vulkan: fix vertical offset for `readPixels`.
|
||||
- Vulkan: various internal improvements.
|
||||
- Metal: support integer formats with `readPixels`.
|
||||
|
||||
## v1.12.7
|
||||
|
||||
|
||||
@@ -122,20 +122,20 @@ The Gradle project used to generate the AAR is located at `<filament>\android`.
|
||||
|
||||
```
|
||||
cd android
|
||||
gradlew -Pfilament_dist_dir=..\out\android-release\filament assembleRelease
|
||||
gradlew -Pcom.google.android.filament.dist-dir=..\out\android-release\filament assembleRelease
|
||||
copy filament-android\build\outputs\aar\filament-android-release.aar ..\..\out\
|
||||
```
|
||||
|
||||
If you're only interested in building for a single ABI, you'll need to pass a `filament_abis` parameter:
|
||||
If you're only interested in building for a single ABI, you'll need to pass a `com.google.android.filament.abis` parameter:
|
||||
|
||||
```
|
||||
gradlew -Pfilament_dist_dir=..\out\android-release\filament assembleRelease -Pfilament_abis=x86
|
||||
gradlew -Pcom.google.android.filament.dist-dir=..\out\android-release\filament assembleRelease -Pcom.google.android.filament.abis=x86
|
||||
```
|
||||
|
||||
If you're only interested in building SDK, you may skip samples build by passing a `filament_skip_samples` flag:
|
||||
If you're only interested in building SDK, you may skip samples build by passing a `com.google.android.filament.skip-samples` flag:
|
||||
|
||||
```
|
||||
gradlew -Pfilament_dist_dir=..\out\android-release\filament assembleRelease -Pfilament_skip_samples
|
||||
gradlew -Pcom.google.android.filament.dist-dir=..\out\android-release\filament assembleRelease -Pfilament_skip_samples
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
// This script accepts the following parameters:
|
||||
//
|
||||
// filament_dist_dir
|
||||
// com.google.android.filament.dist-dir
|
||||
// Path to the Filament distribution/install directory for Android
|
||||
// (produced by make/ninja install). This directory must contain lib/arm64-v8a/ etc.
|
||||
//
|
||||
// filament_tools_dir
|
||||
// com.google.android.filament.tools-dir
|
||||
// Path to the Filament distribution/install directory for desktop.
|
||||
// This directory must contain bin/matc.
|
||||
//
|
||||
// filament_exclude_vulkan
|
||||
// com.google.android.filament.exclude-vulkan
|
||||
// When set, support for Vulkan will be excluded.
|
||||
//
|
||||
// filament_skip_samples
|
||||
// com.google.android.filament.skip-samples
|
||||
// Exclude samples from the project. Useful to speed up compilation.
|
||||
//
|
||||
// filament_abis
|
||||
// com.google.android.filament.abis
|
||||
// List of supported ABIs to build as a comma separated list. Available options are:
|
||||
// arm64-v8a, armeabi-v7a, x86_64, x86, all
|
||||
// Defaults to all.
|
||||
//
|
||||
// Example:
|
||||
// ./gradlew -Pfilament_dist_dir=../dist-android-release assembleRelease -Pfilament_abis=x86
|
||||
// ./gradlew -Pcom.google.android.filament.dist-dir=../dist-android-release \
|
||||
// -Pcom.google.android.filament.abis=x86 \
|
||||
// assembleRelease
|
||||
|
||||
// Publishing to Maven Central:
|
||||
// - Build and upload artifacts with ./gradlew publish
|
||||
@@ -41,19 +43,19 @@
|
||||
|
||||
buildscript {
|
||||
def filamentPath = file("../out/android-release/filament").absolutePath
|
||||
if (project.hasProperty("filament_dist_dir")) {
|
||||
filamentPath = file(project.property("filament_dist_dir")).absolutePath
|
||||
if (project.hasProperty("com.google.android.filament.dist-dir")) {
|
||||
filamentPath = file(project.property("com.google.android.filament.dist-dir")).absolutePath
|
||||
}
|
||||
// Our CMake scripts require a forward-slash path for the FILAMENT_DIST_DIR
|
||||
// variable, so here we convert the native path to a forward-slash path.
|
||||
filamentPath = filamentPath.replace(File.separator, '/')
|
||||
|
||||
// Warning: changing this property does not work well with incremental builds.
|
||||
def excludeVulkan = project.hasProperty("filament_exclude_vulkan")
|
||||
def excludeVulkan = project.hasProperty("com.google.android.filament.exclude-vulkan")
|
||||
|
||||
def abis = ["arm64-v8a", "armeabi-v7a", "x86_64", "x86"]
|
||||
if (project.hasProperty("filament_abis")) {
|
||||
def newAbis = project.property("filament_abis").split(',')
|
||||
if (project.hasProperty("com.google.android.filament.abis")) {
|
||||
def newAbis = project.property("com.google.android.filament.abis").split(',')
|
||||
if (!newAbis.contains("all")) {
|
||||
abis = newAbis
|
||||
}
|
||||
@@ -63,7 +65,7 @@ buildscript {
|
||||
'minSdk': 19,
|
||||
'targetSdk': 30,
|
||||
'compileSdk': 30,
|
||||
'kotlin': '1.5.30',
|
||||
'kotlin': '1.5.31',
|
||||
'buildTools': '30.0.3',
|
||||
'ndk': '22.1.7171670'
|
||||
]
|
||||
@@ -77,7 +79,7 @@ buildscript {
|
||||
]
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.0.2'
|
||||
classpath 'com.android.tools.build:gradle:7.0.3'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
|
||||
}
|
||||
|
||||
@@ -187,7 +189,8 @@ subprojects {
|
||||
gradle.taskGraph.whenReady {
|
||||
gradle.taskGraph.allTasks.each {
|
||||
it.onlyIf {
|
||||
!it.project.ext.has('isSample') || !project.hasProperty('filament_skip_samples')
|
||||
!it.project.ext.has('isSample') ||
|
||||
!project.hasProperty('com.google.android.filament.skip-samples')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
|
||||
plugins {
|
||||
id 'groovy-gradle-plugin'
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
create("filament-tools-plugin") {
|
||||
id = "filament-tools-plugin"
|
||||
implementationClass = "FilamentToolsPlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
// This plugin accepts the following parameters:
|
||||
//
|
||||
// filament_tools_dir
|
||||
// com.google.android.filament.tools-dir
|
||||
// Path to the Filament distribution/install directory for desktop.
|
||||
// This directory must contain bin/matc.
|
||||
//
|
||||
// filament_exclude_vulkan
|
||||
// com.google.android.filament.exclude-vulkan
|
||||
// When set, support for Vulkan will be excluded.
|
||||
//
|
||||
// Example:
|
||||
// ./gradlew -Pfilament_tools_dir=../../dist-release assembleDebug
|
||||
// ./gradlew -Pcom.google.android.filament.tools-dir=../../dist-release assembleDebug
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.provider.ProviderFactory
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.file.FileSystemOperations
|
||||
import org.gradle.api.file.FileType
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.logging.LogLevel
|
||||
@@ -27,14 +29,18 @@ import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.OutputDirectory
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import org.gradle.api.tasks.incremental.InputFileDetails
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
import org.gradle.process.ExecOperations
|
||||
import org.gradle.work.ChangeType
|
||||
import org.gradle.work.Incremental
|
||||
import org.gradle.work.InputChanges
|
||||
|
||||
import java.nio.file.Paths
|
||||
|
||||
class TaskWithBinary extends DefaultTask {
|
||||
import javax.inject.Inject
|
||||
|
||||
abstract class TaskWithBinary extends DefaultTask {
|
||||
private final String binaryName
|
||||
private Property<String> binaryPath = null
|
||||
|
||||
@@ -42,15 +48,23 @@ class TaskWithBinary extends DefaultTask {
|
||||
binaryName = name
|
||||
}
|
||||
|
||||
@Inject abstract ObjectFactory getObjects()
|
||||
@Inject abstract ProviderFactory getProviders()
|
||||
|
||||
@Input
|
||||
Property<String> getBinary() {
|
||||
if (binaryPath == null) {
|
||||
def tool = ["/bin/${binaryName}.exe", "/bin/${binaryName}"]
|
||||
def fullPath = tool.collect { path ->
|
||||
Paths.get(project.ext.filamentToolsPath.absolutePath, path).toFile()
|
||||
def filamentToolsPath = providers
|
||||
.gradleProperty("com.google.android.filament.tools-dir")
|
||||
.forUseAtConfigurationTime().get()
|
||||
def directory = objects.fileProperty()
|
||||
.fileValue(new File(filamentToolsPath)).getAsFile().get()
|
||||
Paths.get(directory.absolutePath, path).toFile()
|
||||
}
|
||||
|
||||
binaryPath = project.objects.property(String.class)
|
||||
binaryPath = objects.property(String.class)
|
||||
binaryPath.set(
|
||||
(OperatingSystem.current().isWindows() ? fullPath[0] : fullPath[1]).toString())
|
||||
}
|
||||
@@ -84,6 +98,11 @@ abstract class MaterialCompiler extends TaskWithBinary {
|
||||
@OutputDirectory
|
||||
abstract DirectoryProperty getOutputDir()
|
||||
|
||||
@Inject abstract FileSystemOperations getFs()
|
||||
@Inject abstract ExecOperations getExec()
|
||||
@Inject abstract ObjectFactory getObjects()
|
||||
@Inject abstract ProviderFactory getProviders()
|
||||
|
||||
MaterialCompiler() {
|
||||
super("matc")
|
||||
}
|
||||
@@ -91,7 +110,9 @@ abstract class MaterialCompiler extends TaskWithBinary {
|
||||
@TaskAction
|
||||
void execute(InputChanges inputs) {
|
||||
if (!inputs.incremental) {
|
||||
project.delete(project.fileTree(outputDir.asFile.get()).matching { include '*.filamat' })
|
||||
fs.delete({
|
||||
delete(objects.fileTree().from(outputDir).matching { include '*.filamat' })
|
||||
})
|
||||
}
|
||||
|
||||
inputs.getFileChanges(inputDir).each { InputFileDetails change ->
|
||||
@@ -115,12 +136,15 @@ abstract class MaterialCompiler extends TaskWithBinary {
|
||||
}
|
||||
|
||||
def matcArgs = []
|
||||
if (!project.hasProperty("filament_exclude_vulkan")) {
|
||||
def exclude_vulkan = providers
|
||||
.gradleProperty("com.google.android.filament.exclude-vulkan")
|
||||
.forUseAtConfigurationTime().present
|
||||
if (!exclude_vulkan) {
|
||||
matcArgs += ['-a', 'vulkan']
|
||||
}
|
||||
matcArgs += ['-a', 'opengl', '-p', 'mobile', '-o', getOutputFile(file), file]
|
||||
|
||||
project.exec {
|
||||
exec.exec {
|
||||
standardOutput out
|
||||
errorOutput err
|
||||
executable "${binary.get()}"
|
||||
@@ -149,6 +173,10 @@ abstract class IblGenerator extends TaskWithBinary {
|
||||
@OutputDirectory
|
||||
abstract DirectoryProperty getOutputDir()
|
||||
|
||||
@Inject abstract FileSystemOperations getFs()
|
||||
@Inject abstract ExecOperations getExec()
|
||||
@Inject abstract ObjectFactory getObjects()
|
||||
|
||||
IblGenerator() {
|
||||
super("cmgen")
|
||||
}
|
||||
@@ -156,7 +184,9 @@ abstract class IblGenerator extends TaskWithBinary {
|
||||
@TaskAction
|
||||
void execute(InputChanges inputs) {
|
||||
if (!inputs.incremental) {
|
||||
project.delete(project.fileTree(outputDir.asFile.get()).matching { include '*' })
|
||||
fs.delete({
|
||||
delete(objects.fileTree().from(outputDir).matching { include '*' })
|
||||
})
|
||||
}
|
||||
|
||||
inputs.getFileChanges(inputFile).each { InputFileDetails change ->
|
||||
@@ -188,7 +218,7 @@ abstract class IblGenerator extends TaskWithBinary {
|
||||
}
|
||||
commandArgs = commandArgs + " " + file
|
||||
|
||||
project.exec {
|
||||
exec.exec {
|
||||
standardOutput out
|
||||
errorOutput err
|
||||
executable "${binary.get()}"
|
||||
@@ -213,6 +243,9 @@ abstract class MeshCompiler extends TaskWithBinary {
|
||||
@OutputDirectory
|
||||
abstract DirectoryProperty getOutputDir()
|
||||
|
||||
@Inject abstract FileSystemOperations getFs()
|
||||
@Inject abstract ExecOperations getExec()
|
||||
|
||||
MeshCompiler() {
|
||||
super("filamesh")
|
||||
}
|
||||
@@ -220,7 +253,9 @@ abstract class MeshCompiler extends TaskWithBinary {
|
||||
@TaskAction
|
||||
void execute(InputChanges inputs) {
|
||||
if (!inputs.incremental) {
|
||||
project.delete(project.fileTree(outputDir.asFile.get()).matching { include '*.filamesh' })
|
||||
fs.delete({
|
||||
delete(objects.fileTree().from(outputDir).matching { include '*.filamesh' })
|
||||
})
|
||||
}
|
||||
|
||||
inputs.getFileChanges(inputFile).each { InputFileDetails change ->
|
||||
@@ -243,7 +278,7 @@ abstract class MeshCompiler extends TaskWithBinary {
|
||||
" Ensure Filament has been built/installed before building this app.")
|
||||
}
|
||||
|
||||
project.exec {
|
||||
exec.exec {
|
||||
standardOutput out
|
||||
errorOutput err
|
||||
executable "${binary.get()}"
|
||||
@@ -280,11 +315,6 @@ class FilamentToolsPlugin implements Plugin<Project> {
|
||||
extension.meshInputFile = project.objects.fileProperty()
|
||||
extension.meshOutputDir = project.objects.directoryProperty()
|
||||
|
||||
project.ext.filamentToolsPath = project.file("../../../out/release/filament")
|
||||
if (project.hasProperty("filament_tools_dir")) {
|
||||
project.ext.filamentToolsPath = project.file(project.property("filament_tools_dir"))
|
||||
}
|
||||
|
||||
project.tasks.register("filamentCompileMaterials", MaterialCompiler) {
|
||||
enabled =
|
||||
extension.materialInputDir.isPresent() &&
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
#include "CallbackUtils.h"
|
||||
|
||||
#include "private/backend/VirtualMachineEnv.h"
|
||||
|
||||
void acquireCallbackJni(JNIEnv* env, CallbackJni& callbackUtils) {
|
||||
#ifdef ANDROID
|
||||
callbackUtils.handlerClass = env->FindClass("android/os/Handler");
|
||||
@@ -49,53 +51,6 @@ void releaseCallbackJni(JNIEnv* env, CallbackJni callbackUtils, jobject handler,
|
||||
env->DeleteGlobalRef(callbackUtils.executorClass);
|
||||
}
|
||||
|
||||
JniBufferCallback* JniBufferCallback::make(filament::Engine* engine,
|
||||
JNIEnv* env, jobject handler, jobject callback, AutoBuffer&& buffer) {
|
||||
return new JniBufferCallback(env, handler, callback, std::move(buffer));
|
||||
}
|
||||
|
||||
JniBufferCallback::JniBufferCallback(JNIEnv* env, jobject handler, jobject callback,
|
||||
AutoBuffer&& buffer)
|
||||
: mEnv(env)
|
||||
, mHandler(env->NewGlobalRef(handler))
|
||||
, mCallback(env->NewGlobalRef(callback))
|
||||
, mBuffer(std::move(buffer)) {
|
||||
acquireCallbackJni(env, mCallbackUtils);
|
||||
}
|
||||
|
||||
JniBufferCallback::~JniBufferCallback() {
|
||||
releaseCallbackJni(mEnv, mCallbackUtils, mHandler, mCallback);
|
||||
}
|
||||
|
||||
void JniBufferCallback::invoke(void*, size_t, void* user) {
|
||||
JniBufferCallback* data = reinterpret_cast<JniBufferCallback*>(user);
|
||||
delete data;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
JniImageCallback* JniImageCallback::make(filament::Engine* engine,
|
||||
JNIEnv* env, jobject handler, jobject callback, long image) {
|
||||
return new JniImageCallback(env, handler, callback, image);
|
||||
}
|
||||
|
||||
JniImageCallback::JniImageCallback(JNIEnv* env, jobject handler, jobject callback, long image)
|
||||
: mEnv(env)
|
||||
, mHandler(env->NewGlobalRef(handler))
|
||||
, mCallback(env->NewGlobalRef(callback))
|
||||
, mImage(image) {
|
||||
acquireCallbackJni(env, mCallbackUtils);
|
||||
}
|
||||
|
||||
JniImageCallback::~JniImageCallback() {
|
||||
releaseCallbackJni(mEnv, mCallbackUtils, mHandler, mCallback);
|
||||
}
|
||||
|
||||
void JniImageCallback::invoke(void*, void* user) {
|
||||
JniImageCallback* data = reinterpret_cast<JniImageCallback*>(user);
|
||||
delete data;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
JniCallback* JniCallback::make(JNIEnv* env, jobject handler, jobject callback) {
|
||||
@@ -103,17 +58,65 @@ JniCallback* JniCallback::make(JNIEnv* env, jobject handler, jobject callback) {
|
||||
}
|
||||
|
||||
JniCallback::JniCallback(JNIEnv* env, jobject handler, jobject callback)
|
||||
: mEnv(env)
|
||||
, mHandler(env->NewGlobalRef(handler))
|
||||
, mCallback(env->NewGlobalRef(callback)) {
|
||||
: mHandler(env->NewGlobalRef(handler)),
|
||||
mCallback(env->NewGlobalRef(callback)) {
|
||||
acquireCallbackJni(env, mCallbackUtils);
|
||||
}
|
||||
|
||||
JniCallback::~JniCallback() {
|
||||
releaseCallbackJni(mEnv, mCallbackUtils, mHandler, mCallback);
|
||||
JniCallback::~JniCallback() = default;
|
||||
|
||||
void JniCallback::post(void* user, filament::backend::CallbackHandler::Callback callback) {
|
||||
callback(user);
|
||||
}
|
||||
|
||||
void JniCallback::invoke(void* user) {
|
||||
JniCallback* data = reinterpret_cast<JniCallback*>(user);
|
||||
delete data;
|
||||
void JniCallback::postToJavaAndDestroy(JniCallback* callback) {
|
||||
JNIEnv* env = filament::VirtualMachineEnv::get().getEnvironment();
|
||||
releaseCallbackJni(env, callback->mCallbackUtils, callback->mHandler, callback->mCallback);
|
||||
delete callback;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
JniBufferCallback* JniBufferCallback::make(filament::Engine*,
|
||||
JNIEnv* env, jobject handler, jobject callback, AutoBuffer&& buffer) {
|
||||
return new JniBufferCallback(env, handler, callback, std::move(buffer));
|
||||
}
|
||||
|
||||
JniBufferCallback::JniBufferCallback(JNIEnv* env, jobject handler, jobject callback,
|
||||
AutoBuffer&& buffer)
|
||||
: JniCallback(env, handler, callback),
|
||||
mBuffer(std::move(buffer)) {
|
||||
acquireCallbackJni(env, mCallbackUtils);
|
||||
}
|
||||
|
||||
JniBufferCallback::~JniBufferCallback() = default;
|
||||
|
||||
void JniBufferCallback::postToJavaAndDestroy(void*, size_t, void* user) {
|
||||
JniBufferCallback* callback = (JniBufferCallback*)user;
|
||||
JNIEnv* env = filament::VirtualMachineEnv::get().getEnvironment();
|
||||
callback->mBuffer.attachToJniThread(env);
|
||||
releaseCallbackJni(env, callback->mCallbackUtils, callback->mHandler, callback->mCallback);
|
||||
delete callback;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------
|
||||
|
||||
JniImageCallback* JniImageCallback::make(filament::Engine*,
|
||||
JNIEnv* env, jobject handler, jobject callback, long image) {
|
||||
return new JniImageCallback(env, handler, callback, image);
|
||||
}
|
||||
|
||||
JniImageCallback::JniImageCallback(JNIEnv* env, jobject handler, jobject callback, long image)
|
||||
: JniCallback(env, handler, callback),
|
||||
mImage(image) {
|
||||
acquireCallbackJni(env, mCallbackUtils);
|
||||
}
|
||||
|
||||
JniImageCallback::~JniImageCallback() = default;
|
||||
|
||||
void JniImageCallback::postToJavaAndDestroy(void*, void* user) {
|
||||
JniImageCallback* callback = (JniImageCallback*)user;
|
||||
JNIEnv* env = filament::VirtualMachineEnv::get().getEnvironment();
|
||||
releaseCallbackJni(env, callback->mCallbackUtils, callback->mHandler, callback->mCallback);
|
||||
delete callback;
|
||||
}
|
||||
|
||||
@@ -18,9 +18,10 @@
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "common/CallbackUtils.h"
|
||||
#include "common/NioUtils.h"
|
||||
|
||||
#include <backend/CallbackHandler.h>
|
||||
|
||||
#include <filament/Engine.h>
|
||||
|
||||
struct CallbackJni {
|
||||
@@ -35,57 +36,49 @@ struct CallbackJni {
|
||||
void acquireCallbackJni(JNIEnv* env, CallbackJni& callbackUtils);
|
||||
void releaseCallbackJni(JNIEnv* env, CallbackJni callbackUtils, jobject handler, jobject callback);
|
||||
|
||||
struct JniBufferCallback {
|
||||
struct JniCallback : private filament::backend::CallbackHandler {
|
||||
JniCallback(JniCallback const &) = delete;
|
||||
JniCallback(JniCallback&&) = delete;
|
||||
|
||||
static JniCallback* make(JNIEnv* env, jobject handler, jobject runnable);
|
||||
|
||||
static void postToJavaAndDestroy(JniCallback* callback);
|
||||
|
||||
void post(void* user, Callback callback) override;
|
||||
|
||||
filament::backend::CallbackHandler* getHandler() noexcept { return this; }
|
||||
|
||||
jobject getCallbackObject() { return mCallback; }
|
||||
|
||||
protected:
|
||||
JniCallback(JNIEnv* env, jobject handler, jobject runnable);
|
||||
virtual ~JniCallback();
|
||||
jobject mHandler;
|
||||
jobject mCallback;
|
||||
CallbackJni mCallbackUtils;
|
||||
};
|
||||
|
||||
|
||||
struct JniBufferCallback : public JniCallback {
|
||||
static JniBufferCallback* make(filament::Engine* engine,
|
||||
JNIEnv* env, jobject handler, jobject callback, AutoBuffer&& buffer);
|
||||
|
||||
static void invoke(void* buffer, size_t n, void* user);
|
||||
static void postToJavaAndDestroy(void*, size_t, void* user);
|
||||
|
||||
private:
|
||||
JniBufferCallback(JNIEnv* env, jobject handler, jobject callback, AutoBuffer&& buffer);
|
||||
JniBufferCallback(JniBufferCallback const &) = delete;
|
||||
JniBufferCallback(JniBufferCallback&&) = delete;
|
||||
~JniBufferCallback();
|
||||
|
||||
JNIEnv* mEnv;
|
||||
jobject mHandler;
|
||||
jobject mCallback;
|
||||
virtual ~JniBufferCallback();
|
||||
AutoBuffer mBuffer;
|
||||
CallbackJni mCallbackUtils;
|
||||
};
|
||||
|
||||
struct JniImageCallback {
|
||||
struct JniImageCallback : public JniCallback {
|
||||
static JniImageCallback* make(filament::Engine* engine, JNIEnv* env, jobject handler,
|
||||
jobject runnable, long image);
|
||||
|
||||
static void invoke(void* image, void* user);
|
||||
static void postToJavaAndDestroy(void*, void* user);
|
||||
|
||||
private:
|
||||
JniImageCallback(JNIEnv* env, jobject handler, jobject runnable, long image);
|
||||
JniImageCallback(JniImageCallback const &) = delete;
|
||||
JniImageCallback(JniImageCallback&&) = delete;
|
||||
~JniImageCallback();
|
||||
|
||||
JNIEnv* mEnv;
|
||||
jobject mHandler;
|
||||
jobject mCallback;
|
||||
virtual ~JniImageCallback();
|
||||
long mImage;
|
||||
CallbackJni mCallbackUtils;
|
||||
};
|
||||
|
||||
struct JniCallback {
|
||||
static JniCallback* make(JNIEnv* env, jobject handler, jobject runnable);
|
||||
|
||||
static void invoke(void* user);
|
||||
|
||||
private:
|
||||
JniCallback(JNIEnv* env, jobject handler, jobject runnable);
|
||||
JniCallback(JniCallback const &) = delete;
|
||||
JniCallback(JniCallback&&) = delete;
|
||||
~JniCallback();
|
||||
|
||||
JNIEnv* mEnv;
|
||||
jobject mHandler;
|
||||
jobject mCallback;
|
||||
CallbackJni mCallbackUtils;
|
||||
};
|
||||
|
||||
@@ -38,6 +38,10 @@ public:
|
||||
AutoBuffer(AutoBuffer&& rhs) noexcept;
|
||||
~AutoBuffer() noexcept;
|
||||
|
||||
void attachToJniThread(JNIEnv* env) noexcept {
|
||||
mEnv = env;
|
||||
}
|
||||
|
||||
void* getData() const noexcept {
|
||||
return mUserData;
|
||||
}
|
||||
|
||||
@@ -125,6 +125,7 @@ target_link_libraries(filament-jni
|
||||
target_include_directories(filament-jni PRIVATE
|
||||
..
|
||||
${FILAMENT_DIR}/include
|
||||
../../filament/backend/include
|
||||
../../third_party/robin-map
|
||||
../../libs/utils/include)
|
||||
|
||||
|
||||
@@ -91,7 +91,8 @@ Java_com_google_android_filament_BufferObject_nSetBuffer(JNIEnv *env, jclass typ
|
||||
|
||||
auto* callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
|
||||
|
||||
BufferDescriptor desc(data, sizeInBytes, &JniBufferCallback::invoke, callback);
|
||||
BufferDescriptor desc(data, sizeInBytes,
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
bufferObject->setBuffer(*engine, std::move(desc), (uint32_t) destOffsetInBytes);
|
||||
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
namespace filament {
|
||||
extern jint JNI_OnLoad(JavaVM* vm, void* reserved);
|
||||
};
|
||||
#include "private/backend/VirtualMachineEnv.h"
|
||||
|
||||
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
JNIEnv* env;
|
||||
@@ -26,9 +24,9 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if ANDROID
|
||||
::filament::JNI_OnLoad(vm, reserved);
|
||||
#endif
|
||||
// This must be called when the library is loaded. We need this to get a reference to the
|
||||
// global VM
|
||||
::filament::VirtualMachineEnv::JNI_OnLoad(vm);
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
@@ -91,7 +91,8 @@ Java_com_google_android_filament_IndexBuffer_nSetBuffer(JNIEnv *env, jclass type
|
||||
|
||||
auto* callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
|
||||
|
||||
BufferDescriptor desc(data, sizeInBytes, &JniBufferCallback::invoke, callback);
|
||||
BufferDescriptor desc(data, sizeInBytes,
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
indexBuffer->setBuffer(*engine, std::move(desc), (uint32_t) destOffsetInBytes);
|
||||
|
||||
|
||||
@@ -97,7 +97,8 @@ Java_com_google_android_filament_Renderer_nReadPixels(JNIEnv *env, jclass,
|
||||
|
||||
PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
|
||||
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
|
||||
(uint32_t) stride, &JniBufferCallback::invoke, callback);
|
||||
(uint32_t) stride,
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
renderer->readPixels(uint32_t(xoffset), uint32_t(yoffset), uint32_t(width), uint32_t(height),
|
||||
std::move(desc));
|
||||
@@ -132,7 +133,8 @@ Java_com_google_android_filament_Renderer_nReadPixelsEx(JNIEnv *env, jclass,
|
||||
|
||||
PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
|
||||
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
|
||||
(uint32_t) stride, &JniBufferCallback::invoke, callback);
|
||||
(uint32_t) stride,
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
renderer->readPixels(renderTarget,
|
||||
uint32_t(xoffset), uint32_t(yoffset), uint32_t(width), uint32_t(height),
|
||||
|
||||
@@ -169,7 +169,8 @@ Java_com_google_android_filament_Stream_nReadPixels(JNIEnv *env, jclass,
|
||||
|
||||
PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
|
||||
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
|
||||
(uint32_t) stride, &JniBufferCallback::invoke, callback);
|
||||
(uint32_t) stride,
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
stream->readPixels(uint32_t(xoffset), uint32_t(yoffset), uint32_t(width), uint32_t(height),
|
||||
std::move(desc));
|
||||
@@ -221,5 +222,6 @@ Java_com_google_android_filament_Stream_nSetAcquiredImage(JNIEnv* env, jclass, j
|
||||
|
||||
#endif
|
||||
|
||||
stream->setAcquiredImage((void*) nativeBuffer, &JniImageCallback::invoke, callback);
|
||||
stream->setAcquiredImage((void*) nativeBuffer,
|
||||
callback->getHandler(), &JniImageCallback::postToJavaAndDestroy, callback);
|
||||
}
|
||||
|
||||
@@ -27,5 +27,8 @@ Java_com_google_android_filament_SwapChain_nSetFrameCompletedCallback(JNIEnv* en
|
||||
jlong nativeSwapChain, jobject handler, jobject runnable) {
|
||||
SwapChain* swapChain = (SwapChain*) nativeSwapChain;
|
||||
auto *callback = JniCallback::make(env, handler, runnable);
|
||||
swapChain->setFrameCompletedCallback(&JniCallback::invoke, callback);
|
||||
swapChain->setFrameCompletedCallback([](void* user) {
|
||||
JniCallback* callback = (JniCallback*)user;
|
||||
JniCallback::postToJavaAndDestroy(callback);
|
||||
}, callback);
|
||||
}
|
||||
|
||||
@@ -210,7 +210,8 @@ Java_com_google_android_filament_Texture_nSetImage(JNIEnv* env, jclass, jlong na
|
||||
|
||||
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
|
||||
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
|
||||
(uint32_t) stride, &JniBufferCallback::invoke, callback);
|
||||
(uint32_t) stride,
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
texture->setImage(*engine, (size_t) level, (uint32_t) xoffset, (uint32_t) yoffset,
|
||||
(uint32_t) width, (uint32_t) height, std::move(desc));
|
||||
@@ -240,7 +241,7 @@ Java_com_google_android_filament_Texture_nSetImageCompressed(JNIEnv *env, jclass
|
||||
|
||||
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes,
|
||||
(backend::CompressedPixelDataType) compressedFormat, (uint32_t) compressedSizeInBytes,
|
||||
&JniBufferCallback::invoke, callback);
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
texture->setImage(*engine, (size_t) level, (uint32_t) xoffset, (uint32_t) yoffset,
|
||||
(uint32_t) width, (uint32_t) height, std::move(desc));
|
||||
@@ -274,7 +275,8 @@ Java_com_google_android_filament_Texture_nSetImage3D(JNIEnv* env, jclass, jlong
|
||||
|
||||
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
|
||||
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
|
||||
(uint32_t) stride, &JniBufferCallback::invoke, callback);
|
||||
(uint32_t) stride,
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
texture->setImage(*engine, (size_t) level,
|
||||
(uint32_t) xoffset, (uint32_t) yoffset, (uint32_t) zoffset,
|
||||
@@ -308,7 +310,7 @@ Java_com_google_android_filament_Texture_nSetImage3DCompressed(JNIEnv *env, jcla
|
||||
|
||||
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes,
|
||||
(backend::CompressedPixelDataType) compressedFormat, (uint32_t) compressedSizeInBytes,
|
||||
&JniBufferCallback::invoke, callback);
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
texture->setImage(*engine, (size_t) level,
|
||||
(uint32_t) xoffset, (uint32_t) yoffset, (uint32_t) zoffset,
|
||||
@@ -346,7 +348,8 @@ Java_com_google_android_filament_Texture_nSetImageCubemap(JNIEnv *env, jclass,
|
||||
|
||||
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
|
||||
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
|
||||
(uint32_t) stride, &JniBufferCallback::invoke, callback);
|
||||
(uint32_t) stride,
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
texture->setImage(*engine, (size_t) level, std::move(desc), faceOffsets);
|
||||
|
||||
@@ -381,7 +384,7 @@ Java_com_google_android_filament_Texture_nSetImageCubemapCompressed(JNIEnv *env,
|
||||
|
||||
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes,
|
||||
(backend::CompressedPixelDataType) compressedFormat, (uint32_t) compressedSizeInBytes,
|
||||
&JniBufferCallback::invoke, callback);
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
texture->setImage(*engine, (size_t) level, std::move(desc), faceOffsets);
|
||||
|
||||
@@ -454,7 +457,7 @@ Java_com_google_android_filament_Texture_nGeneratePrefilterMipmap(JNIEnv *env, j
|
||||
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
|
||||
(backend::PixelDataType) type, (uint8_t) alignment,
|
||||
(uint32_t) left, (uint32_t) top, (uint32_t) stride,
|
||||
&JniBufferCallback::invoke, callback);
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
Texture::PrefilterOptions options;
|
||||
options.sampleCount = sampleCount;
|
||||
@@ -563,7 +566,7 @@ private:
|
||||
jobject mBitmap = nullptr;
|
||||
jobject mHandler = nullptr;
|
||||
jobject mCallback = nullptr;
|
||||
AndroidBitmapInfo mInfo;
|
||||
AndroidBitmapInfo mInfo{};
|
||||
CallbackJni mCallbackUtils;
|
||||
};
|
||||
|
||||
|
||||
@@ -32,40 +32,40 @@ using namespace filament::math;
|
||||
using namespace backend;
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_VertexBuffer_nCreateBuilder(JNIEnv *env, jclass type) {
|
||||
Java_com_google_android_filament_VertexBuffer_nCreateBuilder(JNIEnv*, jclass) {
|
||||
return (jlong) new VertexBuffer::Builder();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_VertexBuffer_nDestroyBuilder(JNIEnv *env, jclass type,
|
||||
Java_com_google_android_filament_VertexBuffer_nDestroyBuilder(JNIEnv*, jclass,
|
||||
jlong nativeBuilder) {
|
||||
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
|
||||
delete builder;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_VertexBuffer_nBuilderVertexCount(JNIEnv *env, jclass type,
|
||||
Java_com_google_android_filament_VertexBuffer_nBuilderVertexCount(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, jint vertexCount) {
|
||||
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
|
||||
builder->vertexCount((uint32_t) vertexCount);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_VertexBuffer_nBuilderEnableBufferObjects(JNIEnv *env, jclass type,
|
||||
Java_com_google_android_filament_VertexBuffer_nBuilderEnableBufferObjects(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, jboolean enabled) {
|
||||
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
|
||||
builder->enableBufferObjects(enabled);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_VertexBuffer_nBuilderBufferCount(JNIEnv *env, jclass type,
|
||||
Java_com_google_android_filament_VertexBuffer_nBuilderBufferCount(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, jint bufferCount) {
|
||||
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
|
||||
builder->bufferCount((uint8_t) bufferCount);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_VertexBuffer_nBuilderAttribute(JNIEnv *env, jclass type,
|
||||
Java_com_google_android_filament_VertexBuffer_nBuilderAttribute(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, jint attribute, jint bufferIndex, jint attributeType, jint byteOffset,
|
||||
jint byteStride) {
|
||||
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
|
||||
@@ -75,14 +75,14 @@ Java_com_google_android_filament_VertexBuffer_nBuilderAttribute(JNIEnv *env, jcl
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_VertexBuffer_nBuilderNormalized(JNIEnv *env, jclass type,
|
||||
Java_com_google_android_filament_VertexBuffer_nBuilderNormalized(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, jint attribute, jboolean normalized) {
|
||||
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
|
||||
builder->normalized((VertexAttribute) attribute, normalized);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_VertexBuffer_nBuilderBuild(JNIEnv *env, jclass type,
|
||||
Java_com_google_android_filament_VertexBuffer_nBuilderBuild(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, jlong nativeEngine) {
|
||||
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
|
||||
Engine *engine = (Engine *) nativeEngine;
|
||||
@@ -90,14 +90,14 @@ Java_com_google_android_filament_VertexBuffer_nBuilderBuild(JNIEnv *env, jclass
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_VertexBuffer_nGetVertexCount(JNIEnv *env, jclass type,
|
||||
Java_com_google_android_filament_VertexBuffer_nGetVertexCount(JNIEnv*, jclass,
|
||||
jlong nativeVertexBuffer) {
|
||||
VertexBuffer *vertexBuffer = (VertexBuffer *) nativeVertexBuffer;
|
||||
return (jint) vertexBuffer->getVertexCount();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_VertexBuffer_nSetBufferAt(JNIEnv *env, jclass type,
|
||||
Java_com_google_android_filament_VertexBuffer_nSetBufferAt(JNIEnv *env, jclass,
|
||||
jlong nativeVertexBuffer, jlong nativeEngine, jint bufferIndex,
|
||||
jobject buffer, jint remaining,
|
||||
jint destOffsetInBytes, jint count, jobject handler, jobject runnable) {
|
||||
@@ -114,7 +114,8 @@ Java_com_google_android_filament_VertexBuffer_nSetBufferAt(JNIEnv *env, jclass t
|
||||
|
||||
auto* callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
|
||||
|
||||
BufferDescriptor desc(data, sizeInBytes, &JniBufferCallback::invoke, callback);
|
||||
BufferDescriptor desc(data, sizeInBytes,
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
vertexBuffer->setBufferAt(*engine, (uint8_t) bufferIndex, std::move(desc),
|
||||
(uint32_t) destOffsetInBytes);
|
||||
@@ -123,7 +124,7 @@ Java_com_google_android_filament_VertexBuffer_nSetBufferAt(JNIEnv *env, jclass t
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_VertexBuffer_nSetBufferObjectAt(JNIEnv *env, jclass type,
|
||||
Java_com_google_android_filament_VertexBuffer_nSetBufferObjectAt(JNIEnv*, jclass,
|
||||
jlong nativeVertexBuffer, jlong nativeEngine, jint bufferIndex, jlong nativeBufferObject) {
|
||||
VertexBuffer *vertexBuffer = (VertexBuffer *) nativeVertexBuffer;
|
||||
Engine *engine = (Engine *) nativeEngine;
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
#include <filament/View.h>
|
||||
#include <filament/Viewport.h>
|
||||
|
||||
#include "common/CallbackUtils.h"
|
||||
|
||||
#include "private/backend/VirtualMachineEnv.h"
|
||||
|
||||
using namespace filament;
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
@@ -82,13 +86,19 @@ Java_com_google_android_filament_View_nSetRenderTarget(JNIEnv*, jclass,
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetSampleCount(JNIEnv*, jclass, jlong nativeView, jint count) {
|
||||
View* view = (View*) nativeView;
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
view->setSampleCount((uint8_t) count);
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_View_nGetSampleCount(JNIEnv*, jclass, jlong nativeView) {
|
||||
View* view = (View*) nativeView;
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
return view->getSampleCount();
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
@@ -321,8 +331,8 @@ Java_com_google_android_filament_View_nSetBlendMode(JNIEnv *, jclass , jlong nat
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetDepthOfFieldOptions(JNIEnv *, jclass ,
|
||||
jlong nativeView, jfloat focusDistance, jfloat cocScale, jfloat maxApertureDiameter, jboolean enabled, jint filter,
|
||||
Java_com_google_android_filament_View_nSetDepthOfFieldOptions(JNIEnv *, jclass,
|
||||
jlong nativeView, jfloat cocScale, jfloat maxApertureDiameter, jboolean enabled, jint filter,
|
||||
jboolean nativeResolution, jint foregroundRingCount, jint backgroundRingCount, jint fastGatherRingCount,
|
||||
jint maxForegroundCOC, jint maxBackgroundCOC) {
|
||||
View* view = (View*) nativeView;
|
||||
@@ -351,6 +361,17 @@ Java_com_google_android_filament_View_nSetVignetteOptions(JNIEnv*, jclass, jlong
|
||||
.color = LinearColorA{r, g, b, a}, .enabled = (bool)enabled});
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetMultiSampleAntiAliasingOptions(JNIEnv* env, jclass clazz,
|
||||
jlong nativeView, jboolean enabled, jint sampleCount, jboolean customResolve) {
|
||||
View* view = (View*) nativeView;
|
||||
view->setMultiSampleAntiAliasingOptions({
|
||||
.enabled = (bool)enabled,
|
||||
.sampleCount = (uint8_t)sampleCount,
|
||||
.customResolve = (bool)customResolve});
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetTemporalAntiAliasingOptions(JNIEnv *, jclass,
|
||||
@@ -382,3 +403,42 @@ Java_com_google_android_filament_View_nIsScreenSpaceRefractionEnabled(JNIEnv *,
|
||||
View* view = (View*) nativeView;
|
||||
return (jboolean)view->isScreenSpaceRefractionEnabled();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nPick(JNIEnv* env, jclass,
|
||||
jlong nativeView,
|
||||
jint x, jint y, jobject handler, jobject internalCallback) {
|
||||
|
||||
// jniState will be initialized the first time this method is called
|
||||
static const struct JniState {
|
||||
jclass internalOnPickCallbackClass;
|
||||
jfieldID renderableFieldId;
|
||||
jfieldID depthFieldId;
|
||||
jfieldID fragCoordXFieldId;
|
||||
jfieldID fragCoordYFieldId;
|
||||
jfieldID fragCoordZFieldId;
|
||||
explicit JniState(JNIEnv* env) noexcept {
|
||||
internalOnPickCallbackClass = env->FindClass("com/google/android/filament/View$InternalOnPickCallback");
|
||||
renderableFieldId = env->GetFieldID(internalOnPickCallbackClass, "mRenderable", "I");
|
||||
depthFieldId = env->GetFieldID(internalOnPickCallbackClass, "mDepth", "F");
|
||||
fragCoordXFieldId = env->GetFieldID(internalOnPickCallbackClass, "mFragCoordsX", "F");
|
||||
fragCoordYFieldId = env->GetFieldID(internalOnPickCallbackClass, "mFragCoordsY", "F");
|
||||
fragCoordZFieldId = env->GetFieldID(internalOnPickCallbackClass, "mFragCoordsZ", "F");
|
||||
}
|
||||
} jniState(env);
|
||||
|
||||
View* view = (View*) nativeView;
|
||||
JniCallback *callback = JniCallback::make(env, handler, internalCallback);
|
||||
view->pick(x, y, [callback](View::PickingQueryResult const& result) {
|
||||
// this is executed on the backend/service thread
|
||||
jobject obj = callback->getCallbackObject();
|
||||
JNIEnv* env = filament::VirtualMachineEnv::get().getEnvironment();
|
||||
env->SetIntField(obj, jniState.renderableFieldId, (jint)result.renderable.getId());
|
||||
env->SetFloatField(obj, jniState.depthFieldId, result.depth);
|
||||
env->SetFloatField(obj, jniState.fragCoordXFieldId, result.fragCoords.x);
|
||||
env->SetFloatField(obj, jniState.fragCoordYFieldId, result.fragCoords.y);
|
||||
env->SetFloatField(obj, jniState.fragCoordZFieldId, result.fragCoords.z);
|
||||
JniCallback::postToJavaAndDestroy(callback);
|
||||
}, callback->getHandler());
|
||||
}
|
||||
|
||||
@@ -631,7 +631,7 @@ public class Engine {
|
||||
|
||||
/**
|
||||
* Kicks the hardware thread (e.g.: the OpenGL, Vulkan or Metal thread) and blocks until
|
||||
* all commands to this point are executed. Note that this doesn't guarantee that the
|
||||
* all commands to this point are executed. Note that this does guarantee that the
|
||||
* hardware is actually finished.
|
||||
*
|
||||
* <p>This is typically used right after destroying the <code>SwapChain</code>,
|
||||
|
||||
@@ -107,12 +107,12 @@ public class Renderer {
|
||||
/**
|
||||
* Rate at which the scale will change to reach the target frame rate.
|
||||
*/
|
||||
public float scaleRate = 0.125f;
|
||||
public float scaleRate = 1.0f / 15.0f;
|
||||
|
||||
/**
|
||||
* History size. higher values, tend to filter more (clamped to 30).
|
||||
* History size. higher values, tend to filter more (clamped to 31).
|
||||
*/
|
||||
public int history = 9;
|
||||
public int history = 15;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -216,7 +216,38 @@ public class Texture {
|
||||
ETC2_EAC_RGBA8, ETC2_EAC_SRGBA8,
|
||||
|
||||
// Available everywhere except Android/iOS
|
||||
DXT1_RGB, DXT1_RGBA, DXT3_RGBA, DXT5_RGBA
|
||||
DXT1_RGB, DXT1_RGBA, DXT3_RGBA, DXT5_RGBA,
|
||||
DXT1_SRGB, DXT1_SRGBA, DXT3_SRGBA, DXT5_SRGBA,
|
||||
|
||||
// ASTC formats are available with a GLES extension
|
||||
RGBA_ASTC_4x4,
|
||||
RGBA_ASTC_5x4,
|
||||
RGBA_ASTC_5x5,
|
||||
RGBA_ASTC_6x5,
|
||||
RGBA_ASTC_6x6,
|
||||
RGBA_ASTC_8x5,
|
||||
RGBA_ASTC_8x6,
|
||||
RGBA_ASTC_8x8,
|
||||
RGBA_ASTC_10x5,
|
||||
RGBA_ASTC_10x6,
|
||||
RGBA_ASTC_10x8,
|
||||
RGBA_ASTC_10x10,
|
||||
RGBA_ASTC_12x10,
|
||||
RGBA_ASTC_12x12,
|
||||
SRGB8_ALPHA8_ASTC_4x4,
|
||||
SRGB8_ALPHA8_ASTC_5x4,
|
||||
SRGB8_ALPHA8_ASTC_5x5,
|
||||
SRGB8_ALPHA8_ASTC_6x5,
|
||||
SRGB8_ALPHA8_ASTC_6x6,
|
||||
SRGB8_ALPHA8_ASTC_8x5,
|
||||
SRGB8_ALPHA8_ASTC_8x6,
|
||||
SRGB8_ALPHA8_ASTC_8x8,
|
||||
SRGB8_ALPHA8_ASTC_10x5,
|
||||
SRGB8_ALPHA8_ASTC_10x6,
|
||||
SRGB8_ALPHA8_ASTC_10x8,
|
||||
SRGB8_ALPHA8_ASTC_10x10,
|
||||
SRGB8_ALPHA8_ASTC_12x10,
|
||||
SRGB8_ALPHA8_ASTC_12x12
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,7 +262,38 @@ public class Texture {
|
||||
ETC2_EAC_RGBA8, ETC2_EAC_SRGBA8,
|
||||
|
||||
// Available everywhere except Android/iOS
|
||||
DXT1_RGB, DXT1_RGBA, DXT3_RGBA, DXT5_RGBA
|
||||
DXT1_RGB, DXT1_RGBA, DXT3_RGBA, DXT5_RGBA,
|
||||
DXT1_SRGB, DXT1_SRGBA, DXT3_SRGBA, DXT5_SRGBA,
|
||||
|
||||
// ASTC formats are available with a GLES extension
|
||||
RGBA_ASTC_4x4,
|
||||
RGBA_ASTC_5x4,
|
||||
RGBA_ASTC_5x5,
|
||||
RGBA_ASTC_6x5,
|
||||
RGBA_ASTC_6x6,
|
||||
RGBA_ASTC_8x5,
|
||||
RGBA_ASTC_8x6,
|
||||
RGBA_ASTC_8x8,
|
||||
RGBA_ASTC_10x5,
|
||||
RGBA_ASTC_10x6,
|
||||
RGBA_ASTC_10x8,
|
||||
RGBA_ASTC_10x10,
|
||||
RGBA_ASTC_12x10,
|
||||
RGBA_ASTC_12x12,
|
||||
SRGB8_ALPHA8_ASTC_4x4,
|
||||
SRGB8_ALPHA8_ASTC_5x4,
|
||||
SRGB8_ALPHA8_ASTC_5x5,
|
||||
SRGB8_ALPHA8_ASTC_6x5,
|
||||
SRGB8_ALPHA8_ASTC_6x6,
|
||||
SRGB8_ALPHA8_ASTC_8x5,
|
||||
SRGB8_ALPHA8_ASTC_8x6,
|
||||
SRGB8_ALPHA8_ASTC_8x8,
|
||||
SRGB8_ALPHA8_ASTC_10x5,
|
||||
SRGB8_ALPHA8_ASTC_10x6,
|
||||
SRGB8_ALPHA8_ASTC_10x8,
|
||||
SRGB8_ALPHA8_ASTC_10x10,
|
||||
SRGB8_ALPHA8_ASTC_12x10,
|
||||
SRGB8_ALPHA8_ASTC_12x12
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -75,6 +75,7 @@ public class View {
|
||||
private VignetteOptions mVignetteOptions;
|
||||
private ColorGrading mColorGrading;
|
||||
private TemporalAntiAliasingOptions mTemporalAntiAliasingOptions;
|
||||
private MultiSampleAntiAliasingOptions mMultiSampleAntiAliasingOptions;
|
||||
private VsmShadowOptions mVsmShadowOptions;
|
||||
|
||||
/**
|
||||
@@ -291,6 +292,29 @@ public class View {
|
||||
public boolean ssctEnabled = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for Multi-sample Anti-aliasing (MSAA)
|
||||
* @see View#setMultiSampleAntiAliasingOptions
|
||||
*/
|
||||
public static class MultiSampleAntiAliasingOptions {
|
||||
/** enables or disables temporal anti-aliasing */
|
||||
public boolean enabled = false;
|
||||
|
||||
/**
|
||||
* number of samples to use for multi-sampled anti-aliasing.\n
|
||||
* 0: treated as 1
|
||||
* 1: no anti-aliasing
|
||||
* n: sample count. Effective sample could be different depending on the
|
||||
* GPU capabilities.
|
||||
*/
|
||||
public int sampleCount = 4;
|
||||
|
||||
/**
|
||||
* custom resolve improves quality for HDR scenes, but may impact performance.
|
||||
*/
|
||||
public boolean customResolve = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Options for Temporal Anti-aliasing (TAA)
|
||||
* @see View#setTemporalAntiAliasingOptions
|
||||
@@ -1047,7 +1071,10 @@ public class View {
|
||||
* </p>
|
||||
*
|
||||
* @param count number of samples to use for multi-sampled anti-aliasing.
|
||||
*
|
||||
* @deprecated use setMultiSampleAntiAliasingOptions instead
|
||||
*/
|
||||
@Deprecated
|
||||
public void setSampleCount(int count) {
|
||||
nSetSampleCount(getNativeObject(), count);
|
||||
}
|
||||
@@ -1060,7 +1087,10 @@ public class View {
|
||||
* </p>
|
||||
*
|
||||
* @return value set by {@link #setSampleCount}
|
||||
*
|
||||
* @deprecated use getMultiSampleAntiAliasingOptions instead
|
||||
*/
|
||||
@Deprecated
|
||||
public int getSampleCount() {
|
||||
return nGetSampleCount(getNativeObject());
|
||||
}
|
||||
@@ -1089,6 +1119,30 @@ public class View {
|
||||
return AntiAliasing.values()[nGetAntiAliasing(getNativeObject())];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disable multi-sample anti-aliasing (MSAA). Disabled by default.
|
||||
*
|
||||
* @param options multi-sample anti-aliasing options
|
||||
*/
|
||||
public void setMultiSampleAntiAliasingOptions(@NonNull MultiSampleAntiAliasingOptions options) {
|
||||
mMultiSampleAntiAliasingOptions = options;
|
||||
nSetMultiSampleAntiAliasingOptions(getNativeObject(),
|
||||
options.enabled, options.sampleCount, options.customResolve);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns multi-sample anti-aliasing options.
|
||||
*
|
||||
* @return multi-sample anti-aliasing options
|
||||
*/
|
||||
@NonNull
|
||||
public MultiSampleAntiAliasingOptions getMultiSampleAntiAliasingOptions() {
|
||||
if (mMultiSampleAntiAliasingOptions == null) {
|
||||
mMultiSampleAntiAliasingOptions = new MultiSampleAntiAliasingOptions();
|
||||
}
|
||||
return mMultiSampleAntiAliasingOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disable temporal anti-aliasing (TAA). Disabled by default.
|
||||
*
|
||||
@@ -1548,6 +1602,71 @@ public class View {
|
||||
return mDepthOfFieldOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* A class containing the result of a picking query
|
||||
*/
|
||||
public static class PickingQueryResult {
|
||||
/** The entity of the renderable at the picking query location */
|
||||
@Entity public int renderable;
|
||||
/** The value of the depth buffer at the picking query location */
|
||||
public float depth;
|
||||
/** The fragment coordinate in GL convention at the picking query location */
|
||||
@NonNull public float[] fragCoords = new float[3];
|
||||
};
|
||||
|
||||
/**
|
||||
* An interface to implement a custom class to receive results of picking queries.
|
||||
*/
|
||||
public interface OnPickCallback {
|
||||
/**
|
||||
* onPick() is called by the specified Handler in {@link View#pick} when the picking query
|
||||
* result is available.
|
||||
* @param result An instance of {@link PickingQueryResult}.
|
||||
*/
|
||||
void onPick(@NonNull PickingQueryResult result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a picking query. Multiple queries can be created (e.g.: multi-touch).
|
||||
* Picking queries are all executed when {@link Renderer#render} is called on this View.
|
||||
* The provided callback is guaranteed to be called at some point in the future.
|
||||
*
|
||||
* Typically it takes a couple frames to receive the result of a picking query.
|
||||
*
|
||||
* @param x Horizontal coordinate to query in the viewport with origin on the left.
|
||||
* @param y Vertical coordinate to query on the viewport with origin at the bottom.
|
||||
* @param handler An {@link java.util.concurrent.Executor Executor}.
|
||||
* On Android this can also be a {@link android.os.Handler Handler}.
|
||||
* @param callback User callback executed by <code>handler</code> when the picking query
|
||||
* result is available.
|
||||
*/
|
||||
public void pick(int x, int y,
|
||||
@Nullable Object handler, @Nullable OnPickCallback callback) {
|
||||
InternalOnPickCallback internalCallback = new InternalOnPickCallback(callback);
|
||||
nPick(getNativeObject(), x, y, handler, internalCallback);
|
||||
}
|
||||
|
||||
private static class InternalOnPickCallback implements Runnable {
|
||||
public InternalOnPickCallback(OnPickCallback mUserCallback) {
|
||||
this.mUserCallback = mUserCallback;
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
mPickingQueryResult.renderable = mRenderable;
|
||||
mPickingQueryResult.depth = mDepth;
|
||||
mPickingQueryResult.fragCoords[0] = mFragCoordsX;
|
||||
mPickingQueryResult.fragCoords[1] = mFragCoordsY;
|
||||
mPickingQueryResult.fragCoords[2] = mFragCoordsZ;
|
||||
mUserCallback.onPick(mPickingQueryResult);
|
||||
}
|
||||
private final OnPickCallback mUserCallback;
|
||||
private final PickingQueryResult mPickingQueryResult = new PickingQueryResult();
|
||||
@Entity int mRenderable;
|
||||
float mDepth;
|
||||
float mFragCoordsX;
|
||||
float mFragCoordsY;
|
||||
float mFragCoordsZ;
|
||||
}
|
||||
|
||||
public long getNativeObject() {
|
||||
if (mNativeObject == 0) {
|
||||
@@ -1595,7 +1714,9 @@ public class View {
|
||||
boolean nativeResolution, int foregroundRingCount, int backgroundRingCount, int fastGatherRingCount, int maxForegroundCOC, int maxBackgroundCOC);
|
||||
private static native void nSetVignetteOptions(long nativeView, float midPoint, float roundness, float feather, float r, float g, float b, float a, boolean enabled);
|
||||
private static native void nSetTemporalAntiAliasingOptions(long nativeView, float feedback, float filterWidth, boolean enabled);
|
||||
private static native void nSetMultiSampleAntiAliasingOptions(long nativeView, boolean enabled, int sampleCount, boolean customResolve);
|
||||
private static native boolean nIsShadowingEnabled(long nativeView);
|
||||
private static native void nSetScreenSpaceRefractionEnabled(long nativeView, boolean enabled);
|
||||
private static native boolean nIsScreenSpaceRefractionEnabled(long nativeView);
|
||||
private static native void nPick(long nativeView, int x, int y, Object handler, InternalOnPickCallback internalCallback);
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ target_compile_definitions(filament-utils-jni PUBLIC IMAGEIO_LITE=1)
|
||||
target_include_directories(filament-utils-jni PRIVATE
|
||||
${FILAMENT_DIR}/include
|
||||
..
|
||||
../../filament/backend/include
|
||||
${IMAGEIO_DIR}/include
|
||||
../../libs/utils/include)
|
||||
|
||||
|
||||
@@ -76,6 +76,8 @@ set(GLTFIO_INCLUDE_DIRS
|
||||
..
|
||||
${FILAMENT_DIR}/include
|
||||
${FILAMENT_DIR}/include/gltfio/resources
|
||||
../../filament/backend/include
|
||||
../../libs/gltfio/include
|
||||
../../third_party/cgltf
|
||||
../../third_party/robin-map
|
||||
../../third_party/hat-trie
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.12.7
|
||||
VERSION_NAME=1.13.0
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
@@ -18,3 +18,7 @@ POM_DEVELOPER_NAME=Filament Team
|
||||
org.gradle.jvmargs=-Xmx1536m
|
||||
|
||||
android.useAndroidX=true
|
||||
|
||||
org.gradle.unsafe.configuration-cache=false
|
||||
|
||||
com.google.android.filament.tools-dir=../../../out/release/filament
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'filament-tools-plugin'
|
||||
}
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
|
||||
@@ -96,15 +96,36 @@ class MainActivity : Activity() {
|
||||
setStatusText("To load a new model, go to the above URL on your host machine.")
|
||||
|
||||
val view = modelViewer.view
|
||||
|
||||
/*
|
||||
* Note: The settings below are overriden when connecting to the remote UI.
|
||||
*/
|
||||
|
||||
// on mobile, better use lower quality color buffer
|
||||
view.renderQuality = view.renderQuality.apply {
|
||||
hdrColorBuffer = View.QualityLevel.MEDIUM
|
||||
}
|
||||
|
||||
// dynamic resolution often helps a lot
|
||||
view.dynamicResolutionOptions = view.dynamicResolutionOptions.apply {
|
||||
enabled = true
|
||||
quality = View.QualityLevel.MEDIUM
|
||||
}
|
||||
|
||||
// MSAA is needed with dynamic resolution MEDIUM
|
||||
view.multiSampleAntiAliasingOptions = view.multiSampleAntiAliasingOptions.apply {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
// FXAA is pretty cheap and helps a lot
|
||||
view.antiAliasing = View.AntiAliasing.FXAA;
|
||||
|
||||
// ambient occlusion is the cheapest effect that adds a lot of quality
|
||||
view.ambientOcclusionOptions = view.ambientOcclusionOptions.apply {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
// bloom is pretty expensive but adds a fair amount of realism
|
||||
view.bloomOptions = view.bloomOptions.apply {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'filament-tools-plugin'
|
||||
}
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
@@ -17,7 +19,7 @@ android {
|
||||
compileSdkVersion versions.compileSdk
|
||||
defaultConfig {
|
||||
applicationId "com.google.android.filament.hellocamera"
|
||||
minSdkVersion versions.minSdk
|
||||
minSdkVersion 23
|
||||
targetSdkVersion versions.targetSdk
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,9 @@ import android.graphics.ImageFormat
|
||||
import android.hardware.HardwareBuffer
|
||||
import android.media.ImageReader
|
||||
import android.opengl.Matrix
|
||||
import android.view.Display
|
||||
import android.os.Build
|
||||
import android.os.Looper
|
||||
import androidx.annotation.RequiresApi
|
||||
|
||||
import com.google.android.filament.*
|
||||
|
||||
@@ -44,7 +46,7 @@ import java.util.concurrent.TimeUnit
|
||||
* Toy class that handles all interaction with the Android camera2 API.
|
||||
* Sets the "textureTransform" and "videoTexture" parameters on the given Filament material.
|
||||
*/
|
||||
class CameraHelper(val activity: Activity, private val filamentEngine: Engine, private val filamentMaterial: MaterialInstance, private val display: Display) {
|
||||
class CameraHelper(val activity: Activity, private val filamentEngine: Engine, private val filamentMaterial: MaterialInstance) {
|
||||
private lateinit var cameraId: String
|
||||
private lateinit var captureRequest: CaptureRequest
|
||||
|
||||
@@ -63,6 +65,20 @@ class CameraHelper(val activity: Activity, private val filamentEngine: Engine, p
|
||||
kImageReaderMaxImages,
|
||||
HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE)
|
||||
|
||||
@Suppress("deprecation")
|
||||
private val display = if (Build.VERSION.SDK_INT >= 30) {
|
||||
Api30Impl.getDisplay(activity)
|
||||
} else {
|
||||
activity.windowManager.defaultDisplay!!
|
||||
}
|
||||
|
||||
@RequiresApi(30)
|
||||
class Api30Impl {
|
||||
companion object {
|
||||
fun getDisplay(context: Context) = context.display!!
|
||||
}
|
||||
}
|
||||
|
||||
private val cameraCallback = object : CameraDevice.StateCallback() {
|
||||
override fun onOpened(cameraDevice: CameraDevice) {
|
||||
cameraOpenCloseLock.release()
|
||||
@@ -87,7 +103,9 @@ class CameraHelper(val activity: Activity, private val filamentEngine: Engine, p
|
||||
val stream = filamentStream
|
||||
if (stream != null) {
|
||||
imageReader.acquireLatestImage()?.also {
|
||||
stream.setAcquiredImage(it.hardwareBuffer, Handler()) { it.close() }
|
||||
stream.setAcquiredImage(it.hardwareBuffer, Handler(Looper.getMainLooper())) {
|
||||
it.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
|
||||
setupView()
|
||||
setupScene()
|
||||
|
||||
cameraHelper = CameraHelper(this, engine, materialInstance, windowManager.defaultDisplay)
|
||||
cameraHelper = CameraHelper(this, engine, materialInstance)
|
||||
cameraHelper.openCamera()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'filament-tools-plugin'
|
||||
}
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'filament-tools-plugin'
|
||||
}
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'filament-tools-plugin'
|
||||
}
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
|
||||
@@ -14,5 +14,6 @@ android {
|
||||
|
||||
dependencies {
|
||||
implementation deps.kotlin
|
||||
implementation deps.androidx.annotations
|
||||
implementation project(':filament-android')
|
||||
}
|
||||
|
||||
@@ -18,19 +18,21 @@ package com.google.android.filament.livewallpaper
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.graphics.Color
|
||||
import android.graphics.PixelFormat
|
||||
import android.os.Build
|
||||
import android.service.wallpaper.WallpaperService
|
||||
import android.view.Choreographer
|
||||
import android.view.Surface
|
||||
import android.view.SurfaceHolder
|
||||
import android.view.WindowManager
|
||||
import android.view.animation.LinearInterpolator
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.google.android.filament.*
|
||||
import com.google.android.filament.android.DisplayHelper
|
||||
import com.google.android.filament.android.UiHelper
|
||||
|
||||
|
||||
class FilamentLiveWallpaper : WallpaperService() {
|
||||
// Make sure to initialize Filament first
|
||||
// This loads the JNI library needed by most API calls
|
||||
@@ -196,9 +198,14 @@ class FilamentLiveWallpaper : WallpaperService() {
|
||||
override fun onNativeWindowChanged(surface: Surface) {
|
||||
swapChain?.let { engine.destroySwapChain(it) }
|
||||
swapChain = engine.createSwapChain(surface)
|
||||
val display =
|
||||
(application.getSystemService(Service.WINDOW_SERVICE) as WindowManager)
|
||||
.defaultDisplay
|
||||
|
||||
@Suppress("deprecation")
|
||||
val display = if (Build.VERSION.SDK_INT >= 30) {
|
||||
Api30Impl.getDisplay(displayContext!!)
|
||||
} else {
|
||||
(getSystemService(Service.WINDOW_SERVICE) as WindowManager).defaultDisplay
|
||||
}
|
||||
|
||||
displayHelper.attach(renderer, display)
|
||||
}
|
||||
|
||||
@@ -222,4 +229,11 @@ class FilamentLiveWallpaper : WallpaperService() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresApi(30)
|
||||
class Api30Impl {
|
||||
companion object {
|
||||
fun getDisplay(context: Context) = context.display!!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'filament-tools-plugin'
|
||||
}
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'filament-tools-plugin'
|
||||
}
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'filament-tools-plugin'
|
||||
}
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
|
||||
@@ -70,11 +70,11 @@ public class MainActivity extends Activity
|
||||
private Page mPage;
|
||||
private PageMaterials mPageMaterials;
|
||||
private Scene mScene;
|
||||
private Texture[] mTextures = new Texture[2];
|
||||
private final Texture[] mTextures = new Texture[2];
|
||||
private @Entity int mLight;
|
||||
private IndirectLight mIndirectLight;
|
||||
|
||||
private float[] mTouchDownPoint = new float[2];
|
||||
private final float[] mTouchDownPoint = new float[2];
|
||||
private float mTouchDownValue = 0;
|
||||
private float mPageAnimationRadians = 0;
|
||||
private float mPageAnimationValue = 0;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'filament-tools-plugin'
|
||||
}
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
@@ -17,7 +19,7 @@ android {
|
||||
compileSdkVersion versions.compileSdk
|
||||
defaultConfig {
|
||||
applicationId "com.google.android.filament.streamtest"
|
||||
minSdkVersion versions.minSdk
|
||||
minSdkVersion 23
|
||||
targetSdkVersion versions.targetSdk
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.google.android.filament.streamtest
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.Choreographer
|
||||
import android.view.Surface
|
||||
@@ -33,7 +34,9 @@ import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
import java.nio.channels.Channels
|
||||
import android.opengl.*
|
||||
import android.os.Build
|
||||
import android.view.MotionEvent
|
||||
import androidx.annotation.RequiresApi
|
||||
import com.google.android.filament.android.DisplayHelper
|
||||
|
||||
|
||||
@@ -78,6 +81,13 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
|
||||
|
||||
private var externalTextureID: Int = 0
|
||||
|
||||
@RequiresApi(30)
|
||||
class Api30Impl {
|
||||
companion object {
|
||||
fun getDisplay(context: Context) = context.display!!
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@@ -94,7 +104,15 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
|
||||
setupScene()
|
||||
|
||||
externalTextureID = createExternalTexture()
|
||||
streamHelper = StreamHelper(engine, materialInstance, windowManager.defaultDisplay, externalTextureID)
|
||||
|
||||
@Suppress("deprecation")
|
||||
val display = if (Build.VERSION.SDK_INT >= 30) {
|
||||
Api30Impl.getDisplay(this)
|
||||
} else {
|
||||
windowManager.defaultDisplay!!
|
||||
}
|
||||
|
||||
streamHelper = StreamHelper(engine, materialInstance, display, externalTextureID)
|
||||
this.title = streamHelper.getTestName()
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.view.Surface
|
||||
import android.graphics.*
|
||||
import android.media.ImageReader
|
||||
import android.opengl.Matrix
|
||||
import android.os.Looper
|
||||
import android.view.Display
|
||||
|
||||
import com.google.android.filament.*
|
||||
@@ -32,7 +33,12 @@ import com.google.android.filament.*
|
||||
/**
|
||||
* Demonstrates Filament's various texture sharing mechanisms.
|
||||
*/
|
||||
class StreamHelper(private val filamentEngine: Engine, private val filamentMaterial: MaterialInstance, private val display: Display, private val externalTextureId: Int) {
|
||||
class StreamHelper(
|
||||
private val filamentEngine: Engine,
|
||||
private val filamentMaterial: MaterialInstance,
|
||||
private val display: Display,
|
||||
private val externalTextureId: Int
|
||||
) {
|
||||
/**
|
||||
* The StreamSource configures the source data for the texture.
|
||||
*
|
||||
@@ -50,7 +56,7 @@ class StreamHelper(private val filamentEngine: Engine, private val filamentMater
|
||||
}
|
||||
|
||||
private var streamSource = StreamSource.CANVAS_STREAM_NATIVE
|
||||
private val directImageHandler = Handler()
|
||||
private val directImageHandler = Handler(Looper.getMainLooper())
|
||||
private var resolution = Size(640, 480)
|
||||
private var surfaceTexture: SurfaceTexture? = null
|
||||
private var imageReader: ImageReader? = null
|
||||
@@ -93,11 +99,30 @@ class StreamHelper(private val filamentEngine: Engine, private val filamentMater
|
||||
val canvas = surface.lockCanvas(null)
|
||||
|
||||
val movingPaint = Paint()
|
||||
movingPaint.shader = LinearGradient(kGradientOffset, 0.0f, kGradientOffset + kGradientScale, 0.0f, kGradientColors, kGradientStops, Shader.TileMode.REPEAT)
|
||||
canvas.drawRect(Rect(0, resolution.height / 2, resolution.width, resolution.height), movingPaint)
|
||||
movingPaint.shader = LinearGradient(
|
||||
kGradientOffset,
|
||||
0.0f,
|
||||
kGradientOffset + kGradientScale,
|
||||
0.0f,
|
||||
kGradientColors,
|
||||
kGradientStops,
|
||||
Shader.TileMode.REPEAT
|
||||
)
|
||||
canvas.drawRect(
|
||||
Rect(0, resolution.height / 2, resolution.width, resolution.height),
|
||||
movingPaint
|
||||
)
|
||||
|
||||
val staticPaint = Paint()
|
||||
staticPaint.shader = LinearGradient(0.0f, 0.0f, kGradientScale, 0.0f, kGradientColors, kGradientStops, Shader.TileMode.REPEAT)
|
||||
staticPaint.shader = LinearGradient(
|
||||
0.0f,
|
||||
0.0f,
|
||||
kGradientScale,
|
||||
0.0f,
|
||||
kGradientColors,
|
||||
kGradientStops,
|
||||
Shader.TileMode.REPEAT
|
||||
)
|
||||
canvas.drawRect(Rect(0, 0, resolution.width, resolution.height / 2), staticPaint)
|
||||
|
||||
surface.unlockCanvasAndPost(canvas)
|
||||
@@ -108,7 +133,10 @@ class StreamHelper(private val filamentEngine: Engine, private val filamentMater
|
||||
|
||||
if (streamSource == StreamSource.CANVAS_STREAM_ACQUIRED) {
|
||||
val image = imageReader!!.acquireLatestImage()
|
||||
filamentStream!!.setAcquiredImage(image.hardwareBuffer!!, directImageHandler) { image.close() }
|
||||
filamentStream!!.setAcquiredImage(
|
||||
image.hardwareBuffer!!,
|
||||
directImageHandler
|
||||
) { image.close() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,7 +164,9 @@ class StreamHelper(private val filamentEngine: Engine, private val filamentMater
|
||||
|
||||
val filamentTexture = this.filamentTexture!!
|
||||
|
||||
val sampler = TextureSampler(TextureSampler.MinFilter.LINEAR, TextureSampler.MagFilter.LINEAR, TextureSampler.WrapMode.REPEAT)
|
||||
val sampler = TextureSampler(
|
||||
TextureSampler.MinFilter.LINEAR, TextureSampler.MagFilter.LINEAR,
|
||||
TextureSampler.WrapMode.REPEAT)
|
||||
|
||||
// We are texturing a front-facing square shape so we need to generate a matrix that transforms (u, v, 0, 1)
|
||||
// into a new UV coordinate according to the screen rotation and the aspect ratio of the camera image.
|
||||
@@ -164,7 +194,8 @@ class StreamHelper(private val filamentEngine: Engine, private val filamentMater
|
||||
|
||||
// Connect the Stream to the Texture and the Texture to the MaterialInstance.
|
||||
filamentMaterial.setParameter("videoTexture", filamentTexture, sampler)
|
||||
filamentMaterial.setParameter("textureTransform", MaterialInstance.FloatElement.MAT4, textureTransform, 0, 1)
|
||||
filamentMaterial.setParameter("textureTransform",
|
||||
MaterialInstance.FloatElement.MAT4, textureTransform, 0, 1)
|
||||
|
||||
if (streamSource == StreamSource.CANVAS_STREAM_NATIVE) {
|
||||
|
||||
@@ -207,7 +238,9 @@ class StreamHelper(private val filamentEngine: Engine, private val filamentMater
|
||||
|
||||
filamentTexture.setExternalStream(filamentEngine, filamentStream!!)
|
||||
|
||||
this.imageReader = ImageReader.newInstance(resolution.width, resolution.height, ImageFormat.RGB_565, kImageReaderMaxImages).apply {
|
||||
this.imageReader = ImageReader.newInstance(
|
||||
resolution.width, resolution.height, ImageFormat.RGB_565, kImageReaderMaxImages
|
||||
).apply {
|
||||
canvasSurface = surface
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'filament-tools-plugin'
|
||||
}
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'filament-tools-plugin'
|
||||
}
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: FilamentToolsPlugin
|
||||
plugins {
|
||||
id 'com.android.application'
|
||||
id 'kotlin-android'
|
||||
id 'filament-tools-plugin'
|
||||
}
|
||||
|
||||
project.ext.isSample = true
|
||||
|
||||
|
||||
26
build.sh
26
build.sh
@@ -453,23 +453,23 @@ function build_android {
|
||||
|
||||
if [[ "${ISSUE_DEBUG_BUILD}" == "true" ]]; then
|
||||
./gradlew \
|
||||
-Pfilament_dist_dir=../out/android-debug/filament \
|
||||
-Pfilament_abis=${ABI_GRADLE_OPTION} \
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
${VULKAN_ANDROID_GRADLE_OPTION} \
|
||||
:filament-android:assembleDebug \
|
||||
:gltfio-android:assembleDebug \
|
||||
:filament-utils-android:assembleDebug
|
||||
|
||||
./gradlew \
|
||||
-Pfilament_dist_dir=../out/android-debug/filament \
|
||||
-Pfilament_abis=${ABI_GRADLE_OPTION} \
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
:filamat-android:assembleDebug
|
||||
|
||||
if [[ "${BUILD_ANDROID_SAMPLES}" == "true" ]]; then
|
||||
for sample in ${ANDROID_SAMPLES}; do
|
||||
./gradlew \
|
||||
-Pfilament_dist_dir=../out/android-debug/filament \
|
||||
-Pfilament_abis=${ABI_GRADLE_OPTION} \
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
:samples:${sample}:assembleDebug
|
||||
done
|
||||
fi
|
||||
@@ -502,23 +502,23 @@ function build_android {
|
||||
|
||||
if [[ "${ISSUE_RELEASE_BUILD}" == "true" ]]; then
|
||||
./gradlew \
|
||||
-Pfilament_dist_dir=../out/android-release/filament \
|
||||
-Pfilament_abis=${ABI_GRADLE_OPTION} \
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
${VULKAN_ANDROID_GRADLE_OPTION} \
|
||||
:filament-android:assembleRelease \
|
||||
:gltfio-android:assembleRelease \
|
||||
:filament-utils-android:assembleRelease
|
||||
|
||||
./gradlew \
|
||||
-Pfilament_dist_dir=../out/android-release/filament \
|
||||
-Pfilament_abis=${ABI_GRADLE_OPTION} \
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
:filamat-android:assembleRelease
|
||||
|
||||
if [[ "${BUILD_ANDROID_SAMPLES}" == "true" ]]; then
|
||||
for sample in ${ANDROID_SAMPLES}; do
|
||||
./gradlew \
|
||||
-Pfilament_dist_dir=../out/android-release/filament \
|
||||
-Pfilament_abis=${ABI_GRADLE_OPTION} \
|
||||
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \
|
||||
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
|
||||
:samples:${sample}:assembleRelease
|
||||
done
|
||||
fi
|
||||
@@ -831,7 +831,7 @@ while getopts ":hacCfijmp:q:uvslwtdk:" opt; do
|
||||
;;
|
||||
v)
|
||||
VULKAN_ANDROID_OPTION="-DFILAMENT_SUPPORTS_VULKAN=OFF"
|
||||
VULKAN_ANDROID_GRADLE_OPTION="-Pfilament_exclude_vulkan"
|
||||
VULKAN_ANDROID_GRADLE_OPTION="-Pcom.google.android.filament.exclude-vulkan"
|
||||
echo "Disabling support for Vulkan in the core Filament library."
|
||||
echo "Consider using -c after changing this option to clear the Gradle cache."
|
||||
;;
|
||||
|
||||
61
build/common/check-headers.sh
Executable file
61
build/common/check-headers.sh
Executable file
@@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
function print_help {
|
||||
local SELF_NAME
|
||||
SELF_NAME=$(basename "$0")
|
||||
echo "$SELF_NAME. Check that public headers compile independently."
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " $SELF_NAME <public include directory>"
|
||||
echo ""
|
||||
echo "Example:"
|
||||
echo " $SELF_NAME out/release/filament/include"
|
||||
echo ""
|
||||
echo "Dependencies: clang"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -h"
|
||||
echo " Print this help message and exit."
|
||||
}
|
||||
|
||||
while getopts "h" opt; do
|
||||
case ${opt} in
|
||||
h)
|
||||
print_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
print_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if [[ "$#" -ne 1 ]]; then
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FILAMENT_HEADERS="$1"
|
||||
|
||||
includes=()
|
||||
pushd "$FILAMENT_HEADERS" >/dev/null
|
||||
for f in $(find . -name '*.h'); do
|
||||
include_path="${f#./}" # strip leading ./
|
||||
includes+=("${include_path}")
|
||||
done
|
||||
popd >/dev/null
|
||||
|
||||
rm -rf out/check-headers
|
||||
mkdir -p out/check-headers
|
||||
|
||||
echo "Checking that public headers compile independently..."
|
||||
for include in "${includes[@]}"; do
|
||||
echo "Checking ${include}"
|
||||
echo "#include <${include}>" >> out/check-headers/temp.cpp
|
||||
clang -std=c++17 -I "${FILAMENT_HEADERS}" out/check-headers/temp.cpp -c -o /dev/null
|
||||
done
|
||||
echo "Done!"
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -116,6 +116,7 @@ set(PRIVATE_HDRS
|
||||
src/Intersections.h
|
||||
src/MaterialParser.h
|
||||
src/PerViewUniforms.h
|
||||
src/PIDController.h
|
||||
src/PostProcessManager.h
|
||||
src/RenderPass.h
|
||||
src/RenderPrimitive.h
|
||||
@@ -176,6 +177,7 @@ set(MATERIAL_SRCS
|
||||
src/materials/fsr/fsr_rcas.mat
|
||||
src/materials/colorGrading/colorGrading.mat
|
||||
src/materials/colorGrading/colorGradingAsSubpass.mat
|
||||
src/materials/colorGrading/customResolveAsSubpass.mat
|
||||
src/materials/defaultMaterial.mat
|
||||
src/materials/dof/dof.mat
|
||||
src/materials/dof/dofCoc.mat
|
||||
@@ -273,6 +275,7 @@ add_custom_command(
|
||||
OUTPUT "${MATERIAL_DIR}/colorGrading.filamat"
|
||||
DEPENDS ../shaders/src/dithering.fs
|
||||
DEPENDS ../shaders/src/vignette.fs
|
||||
DEPENDS src/materials/colorGrading/colorGrading.fs
|
||||
APPEND
|
||||
)
|
||||
|
||||
@@ -280,6 +283,7 @@ add_custom_command(
|
||||
OUTPUT "${MATERIAL_DIR}/colorGradingAsSubpass.filamat"
|
||||
DEPENDS ../shaders/src/dithering.fs
|
||||
DEPENDS ../shaders/src/vignette.fs
|
||||
DEPENDS src/materials/colorGrading/colorGrading.fs
|
||||
APPEND
|
||||
)
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ set(GENERATION_ROOT ${CMAKE_CURRENT_BINARY_DIR})
|
||||
# ==================================================================================================
|
||||
set(PUBLIC_HDRS
|
||||
include/backend/BufferDescriptor.h
|
||||
include/backend/CallbackHandler.h
|
||||
include/backend/DriverEnums.h
|
||||
include/backend/Handle.h
|
||||
include/backend/PipelineState.h
|
||||
@@ -21,6 +22,7 @@ set(PUBLIC_HDRS
|
||||
set(SRCS
|
||||
src/BackendUtils.cpp
|
||||
src/Callable.cpp
|
||||
src/CallbackHandler.cpp
|
||||
src/CircularBuffer.cpp
|
||||
src/CommandBufferQueue.cpp
|
||||
src/CommandStream.cpp
|
||||
@@ -77,26 +79,30 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMEN
|
||||
include/private/backend/OpenGLPlatform.h
|
||||
)
|
||||
if (EGL)
|
||||
list(APPEND SRCS src/opengl/PlatformEGL.cpp)
|
||||
list(APPEND SRCS src/opengl/platforms/PlatformEGL.cpp)
|
||||
endif()
|
||||
if (ANDROID)
|
||||
list(APPEND SRCS src/android/ExternalStreamManagerAndroid.cpp)
|
||||
# FIXME: this should be included when we build for JAVA (which is implied by ANDROID)
|
||||
# but is not specific to ANDROID
|
||||
list(APPEND SRCS src/VirtualMachineEnv.cpp)
|
||||
endif ()
|
||||
if (ANDROID)
|
||||
list(APPEND SRCS src/opengl/platforms/ExternalStreamManagerAndroid.cpp)
|
||||
list(APPEND SRCS src/android/ExternalTextureManagerAndroid.cpp)
|
||||
list(APPEND SRCS src/android/VirtualMachineEnv.cpp)
|
||||
list(APPEND SRCS src/opengl/PlatformEGLAndroid.cpp)
|
||||
list(APPEND SRCS src/opengl/platforms/PlatformEGLAndroid.cpp)
|
||||
elseif (IOS)
|
||||
list(APPEND SRCS src/opengl/PlatformCocoaTouchGL.mm)
|
||||
list(APPEND SRCS src/opengl/CocoaTouchExternalImage.mm)
|
||||
list(APPEND SRCS src/opengl/platforms/PlatformCocoaTouchGL.mm)
|
||||
list(APPEND SRCS src/opengl/platforms/CocoaTouchExternalImage.mm)
|
||||
elseif (APPLE)
|
||||
list(APPEND SRCS src/opengl/PlatformCocoaGL.mm)
|
||||
list(APPEND SRCS src/opengl/platforms/PlatformCocoaGL.mm)
|
||||
elseif (WEBGL)
|
||||
list(APPEND SRCS src/opengl/PlatformWebGL.cpp)
|
||||
list(APPEND SRCS src/opengl/platforms/PlatformWebGL.cpp)
|
||||
elseif (LINUX)
|
||||
list(APPEND SRCS src/opengl/PlatformGLX.cpp)
|
||||
list(APPEND SRCS src/opengl/platforms/PlatformGLX.cpp)
|
||||
elseif (WIN32)
|
||||
list(APPEND SRCS src/opengl/PlatformWGL.cpp)
|
||||
list(APPEND SRCS src/opengl/platforms/PlatformWGL.cpp)
|
||||
else()
|
||||
list(APPEND SRCS src/opengl/PlatformDummyGL.cpp)
|
||||
list(APPEND SRCS src/opengl/platforms/PlatformDummyGL.cpp)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -127,9 +133,9 @@ if (FILAMENT_SUPPORTS_METAL)
|
||||
# Objective-C++ sources need an additional compiler flag on iOS to disable exceptions.
|
||||
set_property(SOURCE
|
||||
${METAL_SRCS}
|
||||
src/opengl/PlatformCocoaTouchGL.mm
|
||||
src/opengl/CocoaTouchExternalImage.mm
|
||||
src/opengl/PlatformCocoaGL.mm
|
||||
src/opengl/platforms/PlatformCocoaTouchGL.mm
|
||||
src/opengl/platforms/CocoaTouchExternalImage.mm
|
||||
src/opengl/platforms/PlatformCocoaGL.mm
|
||||
PROPERTY COMPILE_FLAGS -fno-objc-exceptions)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class CallbackHandler;
|
||||
|
||||
/**
|
||||
* A CPU memory-buffer descriptor, typically used to transfer data from the CPU to the GPU.
|
||||
*
|
||||
@@ -53,8 +55,8 @@ public:
|
||||
|
||||
//! calls the callback to advertise BufferDescriptor no-longer owns the buffer
|
||||
~BufferDescriptor() noexcept {
|
||||
if (callback) {
|
||||
callback(buffer, size, user);
|
||||
if (mCallback) {
|
||||
mCallback(buffer, size, mUser);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,19 +64,21 @@ public:
|
||||
BufferDescriptor& operator=(const BufferDescriptor& rhs) = delete;
|
||||
|
||||
BufferDescriptor(BufferDescriptor&& rhs) noexcept
|
||||
: buffer(rhs.buffer), size(rhs.size), callback(rhs.callback), user(rhs.user) {
|
||||
: buffer(rhs.buffer), size(rhs.size),
|
||||
mCallback(rhs.mCallback), mUser(rhs.mUser), mHandler(rhs.mHandler) {
|
||||
rhs.buffer = nullptr;
|
||||
rhs.callback = nullptr;
|
||||
rhs.mCallback = nullptr;
|
||||
}
|
||||
|
||||
BufferDescriptor& operator=(BufferDescriptor&& rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
buffer = rhs.buffer;
|
||||
size = rhs.size;
|
||||
callback = rhs.callback;
|
||||
user = rhs.user;
|
||||
mCallback = rhs.mCallback;
|
||||
mUser = rhs.mUser;
|
||||
mHandler = rhs.mHandler;
|
||||
rhs.buffer = nullptr;
|
||||
rhs.callback = nullptr;
|
||||
rhs.mCallback = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -88,30 +92,113 @@ public:
|
||||
*/
|
||||
BufferDescriptor(void const* buffer, size_t size,
|
||||
Callback callback = nullptr, void* user = nullptr) noexcept
|
||||
: buffer(const_cast<void*>(buffer)), size(size), callback(callback), user(user) {
|
||||
: buffer(const_cast<void*>(buffer)), size(size), mCallback(callback), mUser(user) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BufferDescriptor that references a CPU memory-buffer
|
||||
* @param buffer Memory address of the CPU buffer to reference
|
||||
* @param size Size of the CPU buffer in bytes
|
||||
* @param callback A callback used to release the CPU buffer from this BufferDescriptor
|
||||
* @param user An opaque user pointer passed to the callback function when it's called
|
||||
*/
|
||||
BufferDescriptor(void const* buffer, size_t size,
|
||||
CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept
|
||||
: buffer(const_cast<void*>(buffer)), size(size),
|
||||
mCallback(callback), mUser(user), mHandler(handler) {
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Helper to create a BufferDescriptor that uses a KNOWN method pointer w/ object passed
|
||||
* by pointer as the callback. e.g.:
|
||||
* auto bd = BufferDescriptor::make(buffer, size, &Foo::method, foo);
|
||||
*
|
||||
* @param buffer Memory address of the CPU buffer to reference
|
||||
* @param size Size of the CPU buffer in bytes
|
||||
* @param handler Handler to use to dispatch the callback, or nullptr for the default handler
|
||||
* @return a new BufferDescriptor
|
||||
*/
|
||||
template<typename T, void(T::*method)(void const*, size_t)>
|
||||
static BufferDescriptor make(
|
||||
void const* buffer, size_t size, T* data, CallbackHandler* handler = nullptr) noexcept {
|
||||
return {
|
||||
buffer, size,
|
||||
handler, [](void* b, size_t s, void* u) {
|
||||
(*static_cast<T**>(u)->*method)(b, s);
|
||||
}, data
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to create a BufferDescriptor that uses a functor as the callback.
|
||||
*
|
||||
* Caveats:
|
||||
* - DO NOT CALL setCallback() when using this helper.
|
||||
* - This make a heap allocation
|
||||
*
|
||||
* @param buffer Memory address of the CPU buffer to reference
|
||||
* @param size Size of the CPU buffer in bytes
|
||||
* @param functor functor of type f(void const* buffer, size_t size)
|
||||
* @param handler Handler to use to dispatch the callback, or nullptr for the default handler
|
||||
* @return a new BufferDescriptor
|
||||
*/
|
||||
template<typename T>
|
||||
static BufferDescriptor make(
|
||||
void const* buffer, size_t size, T&& functor, CallbackHandler* handler = nullptr) noexcept {
|
||||
return {
|
||||
buffer, size,
|
||||
handler, [](void* b, size_t s, void* u) {
|
||||
T& that = *static_cast<T*>(u);
|
||||
that(b, s);
|
||||
delete &that;
|
||||
},
|
||||
new T(std::forward<T>(functor))
|
||||
};
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Set or replace the release callback function
|
||||
* @param callback The new callback function
|
||||
* @param user An opaque user pointer passed to the callbeck function when it's called
|
||||
*/
|
||||
void setCallback(Callback callback, void* user = nullptr) noexcept {
|
||||
this->callback = callback;
|
||||
this->user = user;
|
||||
this->mCallback = callback;
|
||||
this->mUser = user;
|
||||
this->mHandler = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or replace the release callback function
|
||||
* @param handler The Handler to use to dispatch the callback
|
||||
* @param callback The new callback function
|
||||
* @param user An opaque user pointer passed to the callbeck function when it's called
|
||||
*/
|
||||
void setCallback(CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept {
|
||||
mCallback = callback;
|
||||
mUser = user;
|
||||
mHandler = handler;
|
||||
}
|
||||
|
||||
//! Returns whether a release callback is set
|
||||
bool hasCallback() const noexcept { return callback != nullptr; }
|
||||
bool hasCallback() const noexcept { return mCallback != nullptr; }
|
||||
|
||||
//! Returns the currently set release callback function
|
||||
Callback getCallback() const noexcept {
|
||||
return callback;
|
||||
return mCallback;
|
||||
}
|
||||
|
||||
//! Returns the handler for this callback or nullptr if the default handler is to be used.
|
||||
CallbackHandler* getHandler() const noexcept {
|
||||
return mHandler;
|
||||
}
|
||||
|
||||
//! Returns the user opaque pointer associated to this BufferDescriptor
|
||||
void* getUser() const noexcept {
|
||||
return user;
|
||||
return mUser;
|
||||
}
|
||||
|
||||
//! CPU mempry-buffer virtual address
|
||||
@@ -122,8 +209,9 @@ public:
|
||||
|
||||
private:
|
||||
// callback when the buffer is consumed.
|
||||
Callback callback = nullptr;
|
||||
void* user = nullptr;
|
||||
Callback mCallback = nullptr;
|
||||
void* mUser = nullptr;
|
||||
CallbackHandler* mHandler = nullptr;
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
74
filament/backend/include/backend/CallbackHandler.h
Normal file
74
filament/backend/include/backend/CallbackHandler.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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_CALLBACKHANDLER_H
|
||||
#define TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
/**
|
||||
* A generic interface to dispatch callbacks.
|
||||
*
|
||||
* All APIs that take a callback as argument also take a
|
||||
* CallbackHandler* which is used to dispatch the
|
||||
* callback: CallbackHandler::post() method is called from a service thread as soon
|
||||
* as possible (this will NEVER be the main thread), CallbackHandler::post()
|
||||
* is responsible for scheduling the callback onto the thread the
|
||||
* user desires.
|
||||
*
|
||||
* This is intended to make callbacks interoperate with
|
||||
* the platform/OS's own messaging system.
|
||||
*
|
||||
* CallbackHandler* can always be nullptr in which case the default handler is used. The
|
||||
* default handler always dispatches callbacks on filament's main thread opportunistically.
|
||||
*
|
||||
* Life time:
|
||||
* ---------
|
||||
*
|
||||
* Filament make no attempts to manage the life time of the CallbackHandler* and never takes
|
||||
* ownership.
|
||||
* In particular, this means that the CallbackHandler instance must stay valid until all
|
||||
* pending callbacks are been dispatched.
|
||||
*
|
||||
* Similarly, when shutting down filament, care must be taken to ensure that all pending callbacks
|
||||
* that might access filament's state have been dispatched. Filament can no longer ensure this
|
||||
* because callback execution is the responsibility of the CallbackHandler, which is external to
|
||||
* filament.
|
||||
* Typically, the concrete CallbackHandler would have a mechanism to drain and/or wait for all
|
||||
* callbacks to be processed.
|
||||
*
|
||||
*/
|
||||
class CallbackHandler {
|
||||
public:
|
||||
using Callback = void(*)(void* user);
|
||||
|
||||
/**
|
||||
* Schedules the callback to be called onto the appropriate thread.
|
||||
* Typically this will be the application's main thead.
|
||||
*
|
||||
* Must be thread-safe.
|
||||
*/
|
||||
virtual void post(void* user, Callback callback) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~CallbackHandler();
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H
|
||||
@@ -320,7 +320,7 @@ enum class PixelDataType : uint8_t {
|
||||
BYTE, //!< signed byte
|
||||
USHORT, //!< unsigned short (16-bit)
|
||||
SHORT, //!< signed short (16-bit)
|
||||
UINT, //!< unsigned int (16-bit)
|
||||
UINT, //!< unsigned int (32-bit)
|
||||
INT, //!< signed int (32-bit)
|
||||
HALF, //!< half-float (16-bit float)
|
||||
FLOAT, //!< float (32-bits float)
|
||||
@@ -563,6 +563,48 @@ static constexpr bool isDepthFormat(TextureFormat format) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr bool isUnsignedIntFormat(TextureFormat format) {
|
||||
switch (format) {
|
||||
case TextureFormat::R8UI:
|
||||
case TextureFormat::R16UI:
|
||||
case TextureFormat::R32UI:
|
||||
case TextureFormat::RG8UI:
|
||||
case TextureFormat::RG16UI:
|
||||
case TextureFormat::RG32UI:
|
||||
case TextureFormat::RGB8UI:
|
||||
case TextureFormat::RGB16UI:
|
||||
case TextureFormat::RGB32UI:
|
||||
case TextureFormat::RGBA8UI:
|
||||
case TextureFormat::RGBA16UI:
|
||||
case TextureFormat::RGBA32UI:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr bool isSignedIntFormat(TextureFormat format) {
|
||||
switch (format) {
|
||||
case TextureFormat::R8I:
|
||||
case TextureFormat::R16I:
|
||||
case TextureFormat::R32I:
|
||||
case TextureFormat::RG8I:
|
||||
case TextureFormat::RG16I:
|
||||
case TextureFormat::RG32I:
|
||||
case TextureFormat::RGB8I:
|
||||
case TextureFormat::RGB16I:
|
||||
case TextureFormat::RGB32I:
|
||||
case TextureFormat::RGBA8I:
|
||||
case TextureFormat::RGBA16I:
|
||||
case TextureFormat::RGBA32I:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//! returns whether this format a compressed format
|
||||
static constexpr bool isCompressedFormat(TextureFormat format) noexcept {
|
||||
return format >= TextureFormat::EAC_R11;
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <utils/Log.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
|
||||
@@ -28,8 +28,7 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace filament::backend {
|
||||
|
||||
/**
|
||||
* A descriptor to an image in main memory, typically used to transfer image data from the CPU
|
||||
@@ -58,9 +57,19 @@ public:
|
||||
* @param left Left coordinate in pixels
|
||||
* @param top Top coordinate in pixels
|
||||
* @param stride Stride of a row in pixels
|
||||
* @param handler Handler to dispatch the callback or nullptr for the default handler
|
||||
* @param callback A callback used to release the CPU buffer
|
||||
* @param user An opaque user pointer passed to the callback function when it's called
|
||||
*/
|
||||
PixelBufferDescriptor(void const* buffer, size_t size,
|
||||
PixelDataFormat format, PixelDataType type, uint8_t alignment,
|
||||
uint32_t left, uint32_t top, uint32_t stride,
|
||||
CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept
|
||||
: BufferDescriptor(buffer, size, handler, callback, user),
|
||||
left(left), top(top), stride(stride),
|
||||
format(format), type(type), alignment(alignment) {
|
||||
}
|
||||
|
||||
PixelBufferDescriptor(void const* buffer, size_t size,
|
||||
PixelDataFormat format, PixelDataType type, uint8_t alignment = 1,
|
||||
uint32_t left = 0, uint32_t top = 0, uint32_t stride = 0,
|
||||
@@ -77,9 +86,17 @@ public:
|
||||
* @param size Size in bytes of the buffer containing the image
|
||||
* @param format Format of the image pixels
|
||||
* @param type Type of the image pixels
|
||||
* @param handler Handler to dispatch the callback or nullptr for the default handler
|
||||
* @param callback A callback used to release the CPU buffer
|
||||
* @param user An opaque user pointer passed to the callback function when it's called
|
||||
*/
|
||||
PixelBufferDescriptor(void const* buffer, size_t size,
|
||||
PixelDataFormat format, PixelDataType type,
|
||||
CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept
|
||||
: BufferDescriptor(buffer, size, handler, callback, user),
|
||||
stride(0), format(format), type(type), alignment(1) {
|
||||
}
|
||||
|
||||
PixelBufferDescriptor(void const* buffer, size_t size,
|
||||
PixelDataFormat format, PixelDataType type,
|
||||
Callback callback, void* user = nullptr) noexcept
|
||||
@@ -87,6 +104,7 @@ public:
|
||||
stride(0), format(format), type(type), alignment(1) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new PixelBufferDescriptor referencing a compressed image in main memory
|
||||
*
|
||||
@@ -94,9 +112,18 @@ public:
|
||||
* @param size Size in bytes of the buffer containing the image
|
||||
* @param format Compressed format of the image
|
||||
* @param imageSize Compressed size of the image
|
||||
* @param handler Handler to dispatch the callback or nullptr for the default handler
|
||||
* @param callback A callback used to release the CPU buffer
|
||||
* @param user An opaque user pointer passed to the callback function when it's called
|
||||
*/
|
||||
PixelBufferDescriptor(void const* buffer, size_t size,
|
||||
backend::CompressedPixelDataType format, uint32_t imageSize,
|
||||
CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept
|
||||
: BufferDescriptor(buffer, size, handler, callback, user),
|
||||
imageSize(imageSize), compressedFormat(format), type(PixelDataType::COMPRESSED),
|
||||
alignment(1) {
|
||||
}
|
||||
|
||||
PixelBufferDescriptor(void const* buffer, size_t size,
|
||||
backend::CompressedPixelDataType format, uint32_t imageSize,
|
||||
Callback callback, void* user = nullptr) noexcept
|
||||
@@ -105,6 +132,77 @@ public:
|
||||
alignment(1) {
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
template<typename T, void(T::*method)(void const*, size_t)>
|
||||
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
||||
PixelDataFormat format, PixelDataType type, uint8_t alignment,
|
||||
uint32_t left, uint32_t top, uint32_t stride, T* data,
|
||||
CallbackHandler* handler = nullptr) noexcept {
|
||||
return { buffer, size, format, type, alignment, left, top, stride,
|
||||
handler, [](void* b, size_t s, void* u) {
|
||||
(*static_cast<T**>(u)->*method)(b, s); }, data };
|
||||
}
|
||||
|
||||
template<typename T, void(T::*method)(void const*, size_t)>
|
||||
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
||||
PixelDataFormat format, PixelDataType type, T* data,
|
||||
CallbackHandler* handler = nullptr) noexcept {
|
||||
return { buffer, size, format, type, handler, [](void* b, size_t s, void* u) {
|
||||
(*static_cast<T**>(u)->*method)(b, s); }, data };
|
||||
}
|
||||
|
||||
template<typename T, void(T::*method)(void const*, size_t)>
|
||||
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
||||
backend::CompressedPixelDataType format, uint32_t imageSize, T* data,
|
||||
CallbackHandler* handler = nullptr) noexcept {
|
||||
return { buffer, size, format, imageSize, handler, [](void* b, size_t s, void* u) {
|
||||
(*static_cast<T**>(u)->*method)(b, s); }, data
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
||||
PixelDataFormat format, PixelDataType type, uint8_t alignment,
|
||||
uint32_t left, uint32_t top, uint32_t stride, T&& functor,
|
||||
CallbackHandler* handler = nullptr) noexcept {
|
||||
return { buffer, size, format, type, alignment, left, top, stride,
|
||||
handler, [](void* b, size_t s, void* u) {
|
||||
T& that = *static_cast<T*>(u);
|
||||
that(b, s);
|
||||
delete &that;
|
||||
}, new T(std::forward<T>(functor))
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
||||
PixelDataFormat format, PixelDataType type, T&& functor,
|
||||
CallbackHandler* handler = nullptr) noexcept {
|
||||
return { buffer, size, format, type,
|
||||
handler, [](void* b, size_t s, void* u) {
|
||||
T& that = *static_cast<T*>(u);
|
||||
that(b, s);
|
||||
delete &that;
|
||||
}, new T(std::forward<T>(functor))
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static PixelBufferDescriptor make(void const* buffer, size_t size,
|
||||
backend::CompressedPixelDataType format, uint32_t imageSize, T&& functor,
|
||||
CallbackHandler* handler = nullptr) noexcept {
|
||||
return { buffer, size, format, imageSize,
|
||||
handler, [](void* b, size_t s, void* u) {
|
||||
T& that = *static_cast<T*>(u);
|
||||
that(b, s);
|
||||
delete &that;
|
||||
}, new T(std::forward<T>(functor))
|
||||
};
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Computes the size in bytes needed to fit an image of given dimensions and format
|
||||
*
|
||||
@@ -210,8 +308,7 @@ public:
|
||||
uint8_t alignment : 4;
|
||||
};
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
} // namespace backend::filament
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::PixelBufferDescriptor& b);
|
||||
|
||||
@@ -19,8 +19,9 @@
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace filament::backend {
|
||||
|
||||
class CallbackHandler;
|
||||
|
||||
// This lightweight POD allows us to bundle the state required to process an ACQUIRED stream.
|
||||
// Since these types of external images need to be moved around and queued up, an encapsulation is
|
||||
@@ -30,9 +31,9 @@ struct AcquiredImage {
|
||||
void* image = nullptr;
|
||||
backend::StreamCallback callback = nullptr;
|
||||
void* userData = nullptr;
|
||||
CallbackHandler* handler = nullptr;
|
||||
};
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
} // namespace filament::backend
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_PRIVATE_ACQUIREDIMAGE_H
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#define TNT_FILAMENT_BACKEND_PRIVATE_DRIVER_H
|
||||
|
||||
#include <backend/BufferDescriptor.h>
|
||||
#include <backend/CallbackHandler.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
#include <backend/PipelineState.h>
|
||||
@@ -63,7 +64,7 @@ public:
|
||||
virtual ~Driver() noexcept;
|
||||
|
||||
// called from the main thread (NOT the render-thread) at various intervals, this
|
||||
// is where the driver can free resources consumed by previous commands.
|
||||
// is where the driver can execute user callbacks.
|
||||
virtual void purge() noexcept = 0;
|
||||
|
||||
virtual ShaderModel getShaderModel() const noexcept = 0;
|
||||
|
||||
@@ -280,7 +280,7 @@ DECL_DRIVER_API_N(destroySync, backend::SyncHandle, sh)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(void, terminate)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(backend::StreamHandle, createStreamNative, void*, stream)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(backend::StreamHandle, createStreamAcquired)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(void, setAcquiredImage, backend::StreamHandle, stream, void*, image, backend::StreamCallback, cb, void*, userData)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(void, setAcquiredImage, backend::StreamHandle, stream, void*, image, backend::CallbackHandler*, handler, backend::StreamCallback, cb, void*, userData)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(void, setStreamDimensions, backend::StreamHandle, stream, uint32_t, width, uint32_t, height)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(int64_t, getStreamTimestamp, backend::StreamHandle, stream)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(void, updateStreams, backend::DriverApi*, driver)
|
||||
@@ -291,6 +291,7 @@ DECL_DRIVER_API_SYNCHRONOUS_0(bool, isTextureSwizzleSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isTextureFormatMipmappable, backend::TextureFormat, format)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isRenderTargetFormatSupported, backend::TextureFormat, format)
|
||||
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(uint8_t, getMaxDrawBuffers)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(math::float2, getClipSpaceParams)
|
||||
|
||||
@@ -43,18 +43,6 @@ public:
|
||||
return env;
|
||||
}
|
||||
|
||||
VirtualMachineEnv() noexcept : mVirtualMachine(sVirtualMachine) {
|
||||
// We're not initializing the JVM here -- but we could -- because most of the time
|
||||
// we don't need the jvm. Instead we do the initialization on first use. This means we could get
|
||||
// a nasty slow down the very first time, but we'll live with it for now.
|
||||
}
|
||||
|
||||
~VirtualMachineEnv() {
|
||||
if (mVirtualMachine) {
|
||||
mVirtualMachine->DetachCurrentThread();
|
||||
}
|
||||
}
|
||||
|
||||
inline JNIEnv* getEnvironment() noexcept {
|
||||
assert_invariant(mVirtualMachine);
|
||||
JNIEnv* env = mJniEnv;
|
||||
@@ -67,6 +55,18 @@ public:
|
||||
static void handleException(JNIEnv* env) noexcept;
|
||||
|
||||
private:
|
||||
VirtualMachineEnv() noexcept : mVirtualMachine(sVirtualMachine) {
|
||||
// We're not initializing the JVM here -- but we could -- because most of the time
|
||||
// we don't need the jvm. Instead we do the initialization on first use. This means we could get
|
||||
// a nasty slow down the very first time, but we'll live with it for now.
|
||||
}
|
||||
|
||||
~VirtualMachineEnv() {
|
||||
if (mVirtualMachine) {
|
||||
mVirtualMachine->DetachCurrentThread();
|
||||
}
|
||||
}
|
||||
|
||||
JNIEnv* getEnvironmentSlow() noexcept;
|
||||
static JavaVM* sVirtualMachine;
|
||||
JNIEnv* mJniEnv = nullptr;
|
||||
23
filament/backend/src/CallbackHandler.cpp
Normal file
23
filament/backend/src/CallbackHandler.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2021 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 <backend/CallbackHandler.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
CallbackHandler::~CallbackHandler() = default;
|
||||
|
||||
} // namespace filament::backend
|
||||
@@ -83,7 +83,13 @@ public:
|
||||
dstComponentType* out = (dstComponentType*) dest;
|
||||
for (size_t column = 0; column < width; ++column) {
|
||||
for (size_t channel = 0; channel < minChannelCount; ++channel) {
|
||||
out[channel] = in[inds[channel]] * dstMaxValue / srcMaxValue;
|
||||
if constexpr (std::is_same_v<dstComponentType, srcComponentType>) {
|
||||
out[channel] = in[inds[channel]];
|
||||
} else {
|
||||
// TODO: beware of overflows in the multiply
|
||||
// TODO: probably not correct for _INTEGER src/dst
|
||||
out[channel] = in[inds[channel]] * dstMaxValue / srcMaxValue;
|
||||
}
|
||||
}
|
||||
for (size_t channel = srcChannelCount; channel < dstChannelCount; ++channel) {
|
||||
out[channel] = dstMaxValue;
|
||||
@@ -102,6 +108,12 @@ public:
|
||||
bool flip) {
|
||||
size_t dstChannelCount;
|
||||
switch (dst->format) {
|
||||
case PixelDataFormat::R_INTEGER: dstChannelCount = 1; break;
|
||||
case PixelDataFormat::RG_INTEGER: dstChannelCount = 2; break;
|
||||
case PixelDataFormat::RGB_INTEGER: dstChannelCount = 3; break;
|
||||
case PixelDataFormat::RGBA_INTEGER: dstChannelCount = 4; break;
|
||||
case PixelDataFormat::R: dstChannelCount = 1; break;
|
||||
case PixelDataFormat::RG: dstChannelCount = 2; break;
|
||||
case PixelDataFormat::RGB: dstChannelCount = 3; break;
|
||||
case PixelDataFormat::RGBA: dstChannelCount = 4; break;
|
||||
default: return false;
|
||||
|
||||
@@ -39,35 +39,100 @@ namespace backend {
|
||||
|
||||
DriverBase::DriverBase(Dispatcher* dispatcher) noexcept
|
||||
: mDispatcher(dispatcher) {
|
||||
if constexpr (UTILS_HAS_THREADING) {
|
||||
// This thread services user callbacks
|
||||
mServiceThread = std::thread([this]() {
|
||||
do {
|
||||
auto& serviceThreadCondition = mServiceThreadCondition;
|
||||
auto& serviceThreadCallbackQueue = mServiceThreadCallbackQueue;
|
||||
|
||||
// wait for some callbacks to dispatch
|
||||
std::unique_lock<std::mutex> lock(mServiceThreadLock);
|
||||
while (serviceThreadCallbackQueue.empty() && !mExitRequested) {
|
||||
serviceThreadCondition.wait(lock);
|
||||
}
|
||||
if (mExitRequested) {
|
||||
break;
|
||||
}
|
||||
// move the callbacks to a temporary vector
|
||||
auto callbacks(std::move(serviceThreadCallbackQueue));
|
||||
lock.unlock();
|
||||
// and make sure to call them without our lock held
|
||||
for (auto[handler, callback, user]: callbacks) {
|
||||
handler->post(user, callback);
|
||||
}
|
||||
} while (true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
DriverBase::~DriverBase() noexcept {
|
||||
if constexpr (UTILS_HAS_THREADING) {
|
||||
// quit our service thread
|
||||
std::unique_lock<std::mutex> lock(mServiceThreadLock);
|
||||
mExitRequested = true;
|
||||
mServiceThreadCondition.notify_one();
|
||||
lock.unlock();
|
||||
mServiceThread.join();
|
||||
}
|
||||
delete mDispatcher;
|
||||
}
|
||||
|
||||
void DriverBase::purge() noexcept {
|
||||
std::vector<BufferDescriptor> buffersToPurge;
|
||||
std::vector<AcquiredImage> imagesToPurge;
|
||||
std::unique_lock<std::mutex> lock(mPurgeLock);
|
||||
std::swap(buffersToPurge, mBufferToPurge);
|
||||
std::swap(imagesToPurge, mImagesToPurge);
|
||||
lock.unlock(); // don't remove this, it ensures mBufferToPurge is destroyed without lock held
|
||||
for (auto& image : imagesToPurge) {
|
||||
image.callback(image.image, image.userData);
|
||||
}
|
||||
// When the BufferDescriptors go out of scope, their destructors invoke their callbacks.
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
class DriverBase::CallbackDataDetails : public DriverBase::CallbackData {
|
||||
UTILS_UNUSED DriverBase* mAllocator;
|
||||
public:
|
||||
explicit CallbackDataDetails(DriverBase* allocator) : mAllocator(allocator) {}
|
||||
};
|
||||
|
||||
DriverBase::CallbackData* DriverBase::CallbackData::obtain(DriverBase* allocator) {
|
||||
// todo: use a pool
|
||||
return new CallbackDataDetails(allocator);
|
||||
}
|
||||
|
||||
void DriverBase::CallbackData::release(CallbackData* data) {
|
||||
// todo: use a pool
|
||||
delete static_cast<CallbackDataDetails*>(data);
|
||||
}
|
||||
|
||||
|
||||
void DriverBase::scheduleCallback(CallbackHandler* handler, void* user, CallbackHandler::Callback callback) {
|
||||
if (handler && UTILS_HAS_THREADING) {
|
||||
std::lock_guard<std::mutex> lock(mServiceThreadLock);
|
||||
mServiceThreadCallbackQueue.emplace_back(handler, callback, user);
|
||||
mServiceThreadCondition.notify_one();
|
||||
} else {
|
||||
std::lock_guard<std::mutex> lock(mPurgeLock);
|
||||
mCallbacks.emplace_back(user, callback);
|
||||
}
|
||||
}
|
||||
|
||||
void DriverBase::purge() noexcept {
|
||||
decltype(mCallbacks) callbacks;
|
||||
std::unique_lock<std::mutex> lock(mPurgeLock);
|
||||
std::swap(callbacks, mCallbacks);
|
||||
lock.unlock(); // don't remove this, it ensures callbacks are called without lock held
|
||||
for (auto& item : callbacks) {
|
||||
item.second(item.first);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void DriverBase::scheduleDestroySlow(BufferDescriptor&& buffer) noexcept {
|
||||
std::lock_guard<std::mutex> lock(mPurgeLock);
|
||||
mBufferToPurge.push_back(std::move(buffer));
|
||||
scheduleCallback(buffer.getHandler(), [buffer = std::move(buffer)]() {
|
||||
// user callback is called when BufferDescriptor gets destroyed
|
||||
});
|
||||
}
|
||||
|
||||
// This is called from an async driver method so it's in the GL thread, but purge is called
|
||||
// on the user thread. This is typically called 0 or 1 times per frame.
|
||||
void DriverBase::scheduleRelease(AcquiredImage&& image) noexcept {
|
||||
std::lock_guard<std::mutex> lock(mPurgeLock);
|
||||
mImagesToPurge.push_back(std::move(image));
|
||||
void DriverBase::scheduleRelease(AcquiredImage const& image) noexcept {
|
||||
scheduleCallback(image.handler, [image]() {
|
||||
image.callback(image.image, image.userData);
|
||||
});
|
||||
}
|
||||
|
||||
void DriverBase::debugCommandBegin(CommandStream* cmds, bool synchronous, const char* methodName) noexcept {
|
||||
|
||||
@@ -23,20 +23,23 @@
|
||||
#include <backend/Platform.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/CallbackHandler.h>
|
||||
|
||||
#include "private/backend/AcquiredImage.h"
|
||||
#include "private/backend/Driver.h"
|
||||
#include "private/backend/SamplerGroup.h"
|
||||
|
||||
#include <array>
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
namespace filament::backend {
|
||||
|
||||
class Dispatcher;
|
||||
|
||||
@@ -183,6 +186,38 @@ public:
|
||||
protected:
|
||||
Dispatcher* mDispatcher;
|
||||
|
||||
class CallbackDataDetails;
|
||||
|
||||
// Helpers...
|
||||
struct CallbackData {
|
||||
CallbackData(CallbackData const &) = delete;
|
||||
CallbackData(CallbackData&&) = delete;
|
||||
CallbackData& operator=(CallbackData const &) = delete;
|
||||
CallbackData& operator=(CallbackData&&) = delete;
|
||||
void* storage[8] = {};
|
||||
static CallbackData* obtain(DriverBase* allocator);
|
||||
static void release(CallbackData* data);
|
||||
protected:
|
||||
CallbackData() = default;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void scheduleCallback(CallbackHandler* handler, T&& functor) {
|
||||
CallbackData* data = CallbackData::obtain(this);
|
||||
static_assert(sizeof(T) <= sizeof(data->storage), "functor too large");
|
||||
new(data->storage) T(std::forward<T>(functor));
|
||||
scheduleCallback(handler, data, (CallbackHandler::Callback)[](void* data) {
|
||||
CallbackData* details = static_cast<CallbackData*>(data);
|
||||
void* user = details->storage;
|
||||
T& functor = *static_cast<T*>(user);
|
||||
functor();
|
||||
functor.~T();
|
||||
CallbackData::release(details);
|
||||
});
|
||||
}
|
||||
|
||||
void scheduleCallback(CallbackHandler* handler, void* user, CallbackHandler::Callback callback);
|
||||
|
||||
inline void scheduleDestroy(BufferDescriptor&& buffer) noexcept {
|
||||
if (buffer.hasCallback()) {
|
||||
scheduleDestroySlow(std::move(buffer));
|
||||
@@ -191,19 +226,23 @@ protected:
|
||||
|
||||
void scheduleDestroySlow(BufferDescriptor&& buffer) noexcept;
|
||||
|
||||
void scheduleRelease(AcquiredImage&& image) noexcept;
|
||||
void scheduleRelease(AcquiredImage const& image) noexcept;
|
||||
|
||||
void debugCommandBegin(CommandStream* cmds, bool synchronous, const char* methodName) noexcept override;
|
||||
void debugCommandEnd(CommandStream* cmds, bool synchronous, const char* methodName) noexcept override;
|
||||
|
||||
private:
|
||||
std::mutex mPurgeLock;
|
||||
std::vector<BufferDescriptor> mBufferToPurge;
|
||||
std::vector<AcquiredImage> mImagesToPurge;
|
||||
std::vector<std::pair<void*, CallbackHandler::Callback>> mCallbacks;
|
||||
|
||||
std::thread mServiceThread;
|
||||
std::mutex mServiceThreadLock;
|
||||
std::condition_variable mServiceThreadCondition;
|
||||
std::vector<std::tuple<CallbackHandler*, CallbackHandler::Callback, void*>> mServiceThreadCallbackQueue;
|
||||
bool mExitRequested = false;
|
||||
};
|
||||
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
} // namespace backend::filament
|
||||
|
||||
#endif // TNT_FILAMENT_DRIVER_DRIVERBASE_H
|
||||
|
||||
@@ -22,44 +22,44 @@
|
||||
#if defined(ANDROID)
|
||||
#include <sys/system_properties.h>
|
||||
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
|
||||
#include "opengl/PlatformEGLAndroid.h"
|
||||
#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/PlatformCocoaTouchGL.h"
|
||||
#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/PlatformCocoaGL.h"
|
||||
#include "opengl/platforms/PlatformCocoaGL.h"
|
||||
#endif
|
||||
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
|
||||
#include "vulkan/PlatformVkCocoa.h"
|
||||
#endif
|
||||
#elif defined(__linux__)
|
||||
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
|
||||
#include "opengl/PlatformGLX.h"
|
||||
#include "opengl/platforms/PlatformGLX.h"
|
||||
#endif
|
||||
#if defined (FILAMENT_DRIVER_SUPPORTS_VULKAN)
|
||||
#include "vulkan/PlatformVkLinux.h"
|
||||
#endif
|
||||
#elif defined(WIN32)
|
||||
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
|
||||
#include "opengl/PlatformWGL.h"
|
||||
#include "opengl/platforms/PlatformWGL.h"
|
||||
#endif
|
||||
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
|
||||
#include "vulkan/PlatformVkWindows.h"
|
||||
#endif
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#include "opengl/PlatformWebGL.h"
|
||||
#include "opengl/platforms/PlatformWebGL.h"
|
||||
#else
|
||||
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
|
||||
#include "opengl/PlatformDummyGL.h"
|
||||
#include "opengl/platforms/PlatformDummyGL.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "VirtualMachineEnv.h"
|
||||
#include "private/backend/VirtualMachineEnv.h"
|
||||
|
||||
#include <utils/debug.h>
|
||||
|
||||
@@ -44,7 +44,11 @@ void VirtualMachineEnv::handleException(JNIEnv* const env) noexcept {
|
||||
|
||||
UTILS_NOINLINE
|
||||
JNIEnv* VirtualMachineEnv::getEnvironmentSlow() noexcept {
|
||||
#if defined(__ANDROID__)
|
||||
mVirtualMachine->AttachCurrentThread(&mJniEnv, nullptr);
|
||||
#else
|
||||
mVirtualMachine->AttachCurrentThread(reinterpret_cast<void**>(&mJniEnv), nullptr);
|
||||
#endif
|
||||
assert_invariant(mJniEnv);
|
||||
return mJniEnv;
|
||||
}
|
||||
@@ -84,9 +84,12 @@ struct EGLExternalTexture : public ExternalTextureManagerAndroid::ExternalTextur
|
||||
GraphicBufferWrapper* graphicBufferWrapper = nullptr;
|
||||
};
|
||||
|
||||
ExternalTextureManagerAndroid& ExternalTextureManagerAndroid::get() noexcept {
|
||||
static ExternalTextureManagerAndroid instance;
|
||||
return instance;
|
||||
ExternalTextureManagerAndroid& ExternalTextureManagerAndroid::create() noexcept {
|
||||
return *(new ExternalTextureManagerAndroid{});
|
||||
}
|
||||
|
||||
void ExternalTextureManagerAndroid::destroy(ExternalTextureManagerAndroid* pExternalTextureManager) noexcept {
|
||||
delete pExternalTextureManager;
|
||||
}
|
||||
|
||||
// called on gl thread
|
||||
@@ -116,7 +119,7 @@ ExternalTextureManagerAndroid::~ExternalTextureManagerAndroid() noexcept {
|
||||
}
|
||||
|
||||
// called on gl thread
|
||||
backend::Platform::ExternalTexture* ExternalTextureManagerAndroid::create() noexcept {
|
||||
backend::Platform::ExternalTexture* ExternalTextureManagerAndroid::createExternalTexture() noexcept {
|
||||
#ifndef PLATFORM_HAS_HARDWAREBUFFER
|
||||
if (!AHardwareBuffer_allocate) {
|
||||
// initialize java stuff on-demand
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#ifndef TNT_FILAMENT_DRIVER_ANDROID_EXTERNAL_TEXTURE_MANAGER_ANDROID_H
|
||||
#define TNT_FILAMENT_DRIVER_ANDROID_EXTERNAL_TEXTURE_MANAGER_ANDROID_H
|
||||
|
||||
#include "android/VirtualMachineEnv.h"
|
||||
#include "private/backend/VirtualMachineEnv.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Platform.h>
|
||||
@@ -31,6 +31,15 @@
|
||||
|
||||
namespace filament {
|
||||
|
||||
/*
|
||||
* ExternalTextureManagerAndroid::ExternalTexture is basically a wrapper for AHardwareBuffer.
|
||||
*
|
||||
* This class doesn't rely on GL or EGL, and could be used for other Android platform if needed
|
||||
* (e.g. Vulkan).
|
||||
*
|
||||
* ExternalTextureManagerAndroid handle allocation/destruction using either Java or the NDK,
|
||||
* whichever is available.
|
||||
*/
|
||||
class ExternalTextureManagerAndroid {
|
||||
public:
|
||||
|
||||
@@ -39,26 +48,27 @@ public:
|
||||
AHardwareBuffer* hardwareBuffer = nullptr;
|
||||
};
|
||||
|
||||
static ExternalTextureManagerAndroid& get() noexcept;
|
||||
// must be called on backend thread
|
||||
static ExternalTextureManagerAndroid& create() noexcept;
|
||||
|
||||
// called on gl thread
|
||||
ExternalTextureManagerAndroid() noexcept;
|
||||
// must be called on backend thread
|
||||
static void destroy(ExternalTextureManagerAndroid* pExternalTextureManager) noexcept;
|
||||
|
||||
// not quite sure on which thread this is going to be called
|
||||
~ExternalTextureManagerAndroid() noexcept;
|
||||
|
||||
// called on gl thread
|
||||
backend::Platform::ExternalTexture* create() noexcept;
|
||||
// must be called on backend thread (only because we don't synchronize
|
||||
backend::Platform::ExternalTexture* createExternalTexture() noexcept;
|
||||
|
||||
// called on app thread
|
||||
void reallocate(
|
||||
backend::Platform::ExternalTexture* ets, uint32_t w, uint32_t h,
|
||||
backend::TextureFormat format, uint64_t usage) noexcept;
|
||||
|
||||
// called on gl thread
|
||||
// must be called on backend thread
|
||||
void destroy(backend::Platform::ExternalTexture* ets) noexcept;
|
||||
|
||||
private:
|
||||
ExternalTextureManagerAndroid() noexcept;
|
||||
~ExternalTextureManagerAndroid() noexcept;
|
||||
|
||||
// called on app thread
|
||||
void alloc(backend::Platform::ExternalTexture* ets,
|
||||
uint32_t w, uint32_t h, backend::TextureFormat format, uint64_t usage) noexcept;
|
||||
|
||||
@@ -64,16 +64,19 @@ MetalDriver::MetalDriver(backend::MetalPlatform* platform) noexcept
|
||||
|
||||
initializeSupportedGpuFamilies(mContext);
|
||||
|
||||
utils::slog.d << "Supported GPU families: " << utils::io::endl;
|
||||
utils::slog.v << "Supported GPU families: " << utils::io::endl;
|
||||
if (mContext->highestSupportedGpuFamily.common > 0) {
|
||||
utils::slog.d << " MTLGPUFamilyCommon" << (int) mContext->highestSupportedGpuFamily.common << utils::io::endl;
|
||||
utils::slog.v << " MTLGPUFamilyCommon" << (int) mContext->highestSupportedGpuFamily.common << utils::io::endl;
|
||||
}
|
||||
if (mContext->highestSupportedGpuFamily.apple > 0) {
|
||||
utils::slog.d << " MTLGPUFamilyApple" << (int) mContext->highestSupportedGpuFamily.apple << utils::io::endl;
|
||||
utils::slog.v << " MTLGPUFamilyApple" << (int) mContext->highestSupportedGpuFamily.apple << utils::io::endl;
|
||||
}
|
||||
if (mContext->highestSupportedGpuFamily.mac > 0) {
|
||||
utils::slog.d << " MTLGPUFamilyMac" << (int) mContext->highestSupportedGpuFamily.mac << utils::io::endl;
|
||||
utils::slog.v << " MTLGPUFamilyMac" << (int) mContext->highestSupportedGpuFamily.mac << utils::io::endl;
|
||||
}
|
||||
utils::slog.v << "Features:" << utils::io::endl;
|
||||
utils::slog.v << " readWriteTextureSupport: " <<
|
||||
(bool) mContext->device.readWriteTextureSupport << utils::io::endl;
|
||||
|
||||
// In order to support texture swizzling, the GPU needs to support it and the system be running
|
||||
// iOS 13+.
|
||||
@@ -565,8 +568,8 @@ Handle<HwStream> MetalDriver::createStreamAcquired() {
|
||||
return {};
|
||||
}
|
||||
|
||||
void MetalDriver::setAcquiredImage(Handle<HwStream> sh, void* image, backend::StreamCallback cb,
|
||||
void* userData) {
|
||||
void MetalDriver::setAcquiredImage(Handle<HwStream> sh, void* image,
|
||||
backend::CallbackHandler* handler, backend::StreamCallback cb, void* userData) {
|
||||
}
|
||||
|
||||
void MetalDriver::setStreamDimensions(Handle<HwStream> stream, uint32_t width,
|
||||
@@ -650,11 +653,14 @@ bool MetalDriver::isRenderTargetFormatSupported(TextureFormat format) {
|
||||
}
|
||||
|
||||
bool MetalDriver::isFrameBufferFetchSupported() {
|
||||
#if defined(IOS) && !defined(FILAMENT_IOS_SIMULATOR)
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
// FrameBuffer fetch is achievable via "programmable blending" in Metal, and only supported on
|
||||
// Apple GPUs with readWriteTextureSupport.
|
||||
return mContext->highestSupportedGpuFamily.apple >= 1 &&
|
||||
mContext->device.readWriteTextureSupport;
|
||||
}
|
||||
|
||||
bool MetalDriver::isFrameBufferFetchMultiSampleSupported() {
|
||||
return isFrameBufferFetchSupported();
|
||||
}
|
||||
|
||||
bool MetalDriver::isFrameTimeSupported() {
|
||||
@@ -973,23 +979,19 @@ void MetalDriver::readPixels(Handle<HwRenderTarget> src, uint32_t x, uint32_t y,
|
||||
id<MTLTexture> srcTexture = color.getTexture();
|
||||
size_t miplevel = color.level;
|
||||
|
||||
auto chooseMetalPixelFormat = [] (PixelDataFormat format, PixelDataType type) {
|
||||
// TODO: Add support for UINT and INT
|
||||
if (format == PixelDataFormat::RGBA && type == PixelDataType::UBYTE) {
|
||||
return MTLPixelFormatRGBA8Unorm;
|
||||
}
|
||||
|
||||
if (format == PixelDataFormat::RGBA && type == PixelDataType::FLOAT) {
|
||||
return MTLPixelFormatRGBA32Float;
|
||||
}
|
||||
|
||||
return MTLPixelFormatInvalid;
|
||||
};
|
||||
|
||||
const MTLPixelFormat format = chooseMetalPixelFormat(data.format, data.type);
|
||||
const MTLPixelFormat format = getMetalFormat(data.format, data.type);
|
||||
ASSERT_PRECONDITION(format != MTLPixelFormatInvalid,
|
||||
"The chosen combination of PixelDataFormat and PixelDataType is not supported for "
|
||||
"readPixels.");
|
||||
"The chosen combination of PixelDataFormat (%d) and PixelDataType (%d) is not supported for "
|
||||
"readPixels.", (int) data.format, (int) data.type);
|
||||
|
||||
const bool formatConversionNecessary = srcTexture.pixelFormat != format;
|
||||
|
||||
// TODO: MetalBlitter does not currently support format conversions to integer types.
|
||||
// The format and type must match the source pixel format exactly.
|
||||
ASSERT_PRECONDITION(!formatConversionNecessary || !isMetalFormatInteger(format),
|
||||
"readPixels does not support integer format conversions from MTLPixelFormat (%d) to (%d).",
|
||||
(int) srcTexture.pixelFormat, (int) format);
|
||||
|
||||
MTLTextureDescriptor* textureDescriptor =
|
||||
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format
|
||||
width:(srcTexture.width >> miplevel)
|
||||
|
||||
@@ -222,6 +222,34 @@ inline MTLPixelFormat getMetalFormatLinear(MTLPixelFormat format) {
|
||||
return format;
|
||||
}
|
||||
|
||||
constexpr inline bool isMetalFormatInteger(MTLPixelFormat format) {
|
||||
switch (format) {
|
||||
case MTLPixelFormatR8Uint:
|
||||
case MTLPixelFormatR8Sint:
|
||||
case MTLPixelFormatR16Uint:
|
||||
case MTLPixelFormatR16Sint:
|
||||
case MTLPixelFormatRG8Uint:
|
||||
case MTLPixelFormatRG8Sint:
|
||||
case MTLPixelFormatR32Uint:
|
||||
case MTLPixelFormatR32Sint:
|
||||
case MTLPixelFormatRG16Uint:
|
||||
case MTLPixelFormatRG16Sint:
|
||||
case MTLPixelFormatRGBA8Uint:
|
||||
case MTLPixelFormatRGBA8Sint:
|
||||
case MTLPixelFormatRGB10A2Uint:
|
||||
case MTLPixelFormatRG32Uint:
|
||||
case MTLPixelFormatRG32Sint:
|
||||
case MTLPixelFormatRGBA16Uint:
|
||||
case MTLPixelFormatRGBA16Sint:
|
||||
case MTLPixelFormatRGBA32Uint:
|
||||
case MTLPixelFormatRGBA32Sint:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline MTLTextureType getMetalType(SamplerType target) {
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
|
||||
@@ -352,8 +352,7 @@ MetalProgram::MetalProgram(id<MTLDevice> device, const Program& program) noexcep
|
||||
length:source.size()
|
||||
encoding:NSUTF8StringEncoding];
|
||||
NSError* error = nil;
|
||||
MTLCompileOptions* options = [MTLCompileOptions new];
|
||||
options.languageVersion = MTLLanguageVersion1_1;
|
||||
// When options is nil, Metal uses the most recent language version available.
|
||||
id<MTLLibrary> library = [device newLibraryWithSource:objcSource
|
||||
options:nil
|
||||
error:&error];
|
||||
|
||||
@@ -117,8 +117,8 @@ Handle<HwStream> NoopDriver::createStreamAcquired() {
|
||||
return {};
|
||||
}
|
||||
|
||||
void NoopDriver::setAcquiredImage(Handle<HwStream> sh, void* image, backend::StreamCallback cb,
|
||||
void* userData) {
|
||||
void NoopDriver::setAcquiredImage(Handle<HwStream> sh, void* image,
|
||||
backend::CallbackHandler* handler, backend::StreamCallback cb, void* userData) {
|
||||
}
|
||||
|
||||
void NoopDriver::setStreamDimensions(Handle<HwStream> sh, uint32_t width, uint32_t height) {
|
||||
@@ -160,6 +160,10 @@ bool NoopDriver::isFrameBufferFetchSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NoopDriver::isFrameBufferFetchMultiSampleSupported() {
|
||||
return false; // TODO: add support for MS framebuffer_fetch
|
||||
}
|
||||
|
||||
bool NoopDriver::isFrameTimeSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -35,9 +35,7 @@ OpenGLContext::OpenGLContext() noexcept {
|
||||
UTILS_UNUSED char const* const version = (char const*) glGetString(GL_VERSION);
|
||||
UTILS_UNUSED char const* const shader = (char const*) glGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||
|
||||
#ifndef NDEBUG
|
||||
slog.i << vendor << ", " << renderer << ", " << version << ", " << shader << io::endl;
|
||||
#endif
|
||||
slog.v << "[" << vendor << "], [" << renderer << "], [" << version << "], [" << shader << "]" << io::endl;
|
||||
|
||||
// OpenGL (ES) version
|
||||
GLint major = 0;
|
||||
@@ -77,12 +75,29 @@ OpenGLContext::OpenGLContext() noexcept {
|
||||
|
||||
// Figure out which driver bugs we need to workaround
|
||||
if (strstr(renderer, "Adreno")) {
|
||||
int maj, min, driverMajor, driverMinor;
|
||||
int c = sscanf(version, "OpenGL ES %d.%d V@%d.%d", // NOLINT(cert-err34-c)
|
||||
&maj, &min, &driverMajor, &driverMinor);
|
||||
if (c == 4) {
|
||||
// workarounds based on version here.
|
||||
// notes:
|
||||
// bugs.invalidate_end_only_if_invalidate_start
|
||||
// - appeared at least in "OpenGL ES 3.2 V@0490.0 (GIT@85da404, I46ff5fc46f, 1606794520) (Date:11/30/20)"
|
||||
// - wasn't present in "OpenGL ES 3.2 V@0490.0 (GIT@0905e9f, Ia11ce2d146, 1599072951) (Date:09/02/20)"
|
||||
}
|
||||
// On Adreno (As of 3/20) timer query seem to return the CPU time, not the GPU time.
|
||||
bugs.dont_use_timer_query = true;
|
||||
|
||||
// Blits to texture arrays are failing
|
||||
bugs.disable_sidecar_blit_into_texture_array = true;
|
||||
// This bug doesn't happen anymore, but we don't know why. The standalone sample
|
||||
// app that was written to show this problem still does. We have tested this on
|
||||
// several V@0490.0 on several devices and the problem appears to have gone away.
|
||||
// The working hypthesis is that some other state affects this behavior.
|
||||
bugs.disable_sidecar_blit_into_texture_array = false;
|
||||
|
||||
// early exit condition is flattened in EASU code
|
||||
bugs.split_easu = true;
|
||||
bugs.invalidate_end_only_if_invalidate_start = true;
|
||||
} else if (strstr(renderer, "Mali")) {
|
||||
bugs.vao_doesnt_store_element_array_buffer_binding = true;
|
||||
if (strstr(renderer, "Mali-T")) {
|
||||
@@ -105,6 +120,14 @@ OpenGLContext::OpenGLContext() noexcept {
|
||||
bugs.disable_invalidate_framebuffer = true;
|
||||
}
|
||||
|
||||
slog.v << "Active workarounds: " << '\n';
|
||||
for (auto [enabled, name, _] : mBugDatabase) {
|
||||
if (enabled) {
|
||||
slog.v << name << '\n';
|
||||
}
|
||||
}
|
||||
flush(slog.v);
|
||||
|
||||
// now we can query getter and features
|
||||
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &gets.max_renderbuffer_size);
|
||||
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &gets.max_uniform_block_size);
|
||||
@@ -119,16 +142,16 @@ OpenGLContext::OpenGLContext() noexcept {
|
||||
|
||||
assert_invariant(gets.max_draw_buffers >= 4); // minspec
|
||||
|
||||
#if 0
|
||||
// this is useful for development, but too verbose even for debug builds
|
||||
slog.i
|
||||
<< "GL_MAX_DRAW_BUFFERS = " << gets.max_draw_buffers << '\n'
|
||||
#ifndef NDEBUG
|
||||
// this is useful for development
|
||||
slog.v << "GL_MAX_DRAW_BUFFERS = " << gets.max_draw_buffers << '\n'
|
||||
<< "GL_MAX_RENDERBUFFER_SIZE = " << gets.max_renderbuffer_size << '\n'
|
||||
<< "GL_MAX_SAMPLES = " << gets.max_samples << '\n'
|
||||
<< "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = " << gets.max_anisotropy << '\n'
|
||||
<< "GL_MAX_UNIFORM_BLOCK_SIZE = " << gets.max_uniform_block_size << '\n'
|
||||
<< "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT = " << gets.uniform_buffer_offset_alignment << '\n'
|
||||
<< io::endl;
|
||||
;
|
||||
flush(slog.v);
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
||||
@@ -26,7 +26,9 @@
|
||||
|
||||
#include "GLUtils.h"
|
||||
|
||||
#include <array>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
|
||||
namespace filament {
|
||||
|
||||
@@ -192,8 +194,48 @@ public:
|
||||
// Some drivers incorrectly flatten the early exit condition in the EASU code, in which
|
||||
// case we need an alternative algorithm
|
||||
bool split_easu = false;
|
||||
|
||||
// As of Android R some qualcomm drivers invalidate buffers for the whole render pass
|
||||
// even if glInvalidateFramebuffer() is called at the end of it.
|
||||
bool invalidate_end_only_if_invalidate_start = false;
|
||||
} bugs;
|
||||
|
||||
const std::array<std::tuple<bool const&, char const*, char const*>, sizeof(bugs)> mBugDatabase{{
|
||||
{ bugs.disable_glFlush,
|
||||
"disable_glFlush",
|
||||
""},
|
||||
{ bugs.vao_doesnt_store_element_array_buffer_binding,
|
||||
"vao_doesnt_store_element_array_buffer_binding",
|
||||
""},
|
||||
{ bugs.disable_shared_context_draws,
|
||||
"disable_shared_context_draws",
|
||||
""},
|
||||
{ bugs.texture_external_needs_rebind,
|
||||
"texture_external_needs_rebind",
|
||||
""},
|
||||
{ bugs.disable_invalidate_framebuffer,
|
||||
"disable_invalidate_framebuffer",
|
||||
""},
|
||||
{ bugs.texture_filter_anisotropic_broken_on_sampler,
|
||||
"texture_filter_anisotropic_broken_on_sampler",
|
||||
""},
|
||||
{ bugs.disable_feedback_loops,
|
||||
"disable_feedback_loops",
|
||||
""},
|
||||
{ bugs.dont_use_timer_query,
|
||||
"dont_use_timer_query",
|
||||
""},
|
||||
{ bugs.disable_sidecar_blit_into_texture_array,
|
||||
"disable_sidecar_blit_into_texture_array",
|
||||
""},
|
||||
{ bugs.split_easu,
|
||||
"split_easu",
|
||||
""},
|
||||
{ bugs.invalidate_end_only_if_invalidate_start,
|
||||
"invalidate_end_only_if_invalidate_start",
|
||||
""},
|
||||
}};
|
||||
|
||||
// state getters -- as needed.
|
||||
GLuint getDrawFbo() const noexcept { return state.draw_fbo; }
|
||||
vec4gli const& getViewport() const { return state.window.viewport; }
|
||||
|
||||
@@ -1360,13 +1360,14 @@ Handle<HwStream> OpenGLDriver::createStreamAcquired() {
|
||||
// called only once per frame. If the user pushes images to the same stream multiple times in a
|
||||
// single frame, we emit a warning and honor only the final image, but still invoke all callbacks.
|
||||
void OpenGLDriver::setAcquiredImage(Handle<HwStream> sh, void* hwbuffer,
|
||||
backend::StreamCallback cb, void* userData) {
|
||||
backend::CallbackHandler* handler, backend::StreamCallback cb, void* userData) {
|
||||
GLStream* glstream = handle_cast<GLStream*>(sh);
|
||||
if (glstream->user_thread.pending.image) {
|
||||
scheduleRelease(std::move(glstream->user_thread.pending));
|
||||
scheduleRelease(glstream->user_thread.pending);
|
||||
slog.w << "Acquired image is set more than once per frame." << io::endl;
|
||||
}
|
||||
glstream->user_thread.pending = mPlatform.transformAcquiredImage({hwbuffer, cb, userData});
|
||||
glstream->user_thread.pending = mPlatform.transformAcquiredImage({
|
||||
hwbuffer, cb, userData, handler });
|
||||
}
|
||||
|
||||
void OpenGLDriver::updateStreams(DriverApi* driver) {
|
||||
@@ -1552,6 +1553,10 @@ bool OpenGLDriver::isFrameBufferFetchSupported() {
|
||||
return gl.ext.EXT_shader_framebuffer_fetch;
|
||||
}
|
||||
|
||||
bool OpenGLDriver::isFrameBufferFetchMultiSampleSupported() {
|
||||
return isFrameBufferFetchSupported();
|
||||
}
|
||||
|
||||
bool OpenGLDriver::isFrameTimeSupported() {
|
||||
return mFrameTimeSupported;
|
||||
}
|
||||
@@ -2299,11 +2304,15 @@ void OpenGLDriver::endRenderPass(int) {
|
||||
// glInvalidateFramebuffer appeared on GLES 3.0 and GL4.3, for simplicity we just
|
||||
// ignore it on GL (rather than having to do a runtime check).
|
||||
if (GLES30_HEADERS) {
|
||||
auto effectiveDiscardFlags = discardFlags;
|
||||
if (gl.bugs.invalidate_end_only_if_invalidate_start) {
|
||||
effectiveDiscardFlags &= mRenderPassParams.flags.discardStart;
|
||||
}
|
||||
if (!gl.bugs.disable_invalidate_framebuffer) {
|
||||
// we wouldn't have to bind the framebuffer if we had glInvalidateNamedFramebuffer()
|
||||
gl.bindFramebuffer(GL_FRAMEBUFFER, rt->gl.fbo);
|
||||
AttachmentArray attachments; // NOLINT
|
||||
GLsizei attachmentCount = getAttachments(attachments, rt, discardFlags);
|
||||
GLsizei attachmentCount = getAttachments(attachments, rt, effectiveDiscardFlags);
|
||||
if (attachmentCount) {
|
||||
glInvalidateFramebuffer(GL_FRAMEBUFFER, attachmentCount, attachments.data());
|
||||
}
|
||||
@@ -2750,7 +2759,7 @@ void OpenGLDriver::insertEventMarker(char const* string, uint32_t len) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLDriver::pushGroupMarker(char const* string, uint32_t len) {
|
||||
void OpenGLDriver::pushGroupMarker(char const* string, uint32_t len) {
|
||||
#ifdef GL_EXT_debug_marker
|
||||
auto& gl = mContext;
|
||||
if (UTILS_LIKELY(gl.ext.EXT_debug_marker)) {
|
||||
@@ -2834,6 +2843,7 @@ void OpenGLDriver::readPixels(Handle<HwRenderTarget> src,
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, p.size, 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.
|
||||
@@ -2865,8 +2875,6 @@ void OpenGLDriver::readPixels(Handle<HwRenderTarget> src,
|
||||
delete pUserBuffer;
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
});
|
||||
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
}
|
||||
|
||||
void OpenGLDriver::whenGpuCommandsComplete(std::function<void()> fn) noexcept {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#ifndef FILAMENT_DRIVER_OPENGL_COCOA_TOUCH_EXTERNAL_IMAGE
|
||||
#define FILAMENT_DRIVER_OPENGL_COCOA_TOUCH_EXTERNAL_IMAGE
|
||||
|
||||
#include "gl_headers.h"
|
||||
#include "../gl_headers.h"
|
||||
|
||||
#include <CoreVideo/CoreVideo.h>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <OpenGLES/ES3/gl.h>
|
||||
#include <OpenGLES/ES3/glext.h>
|
||||
|
||||
#include "GLUtils.h"
|
||||
#include "../GLUtils.h"
|
||||
|
||||
#include <math/vec2.h>
|
||||
|
||||
@@ -37,10 +37,12 @@ static void loadSymbol(T*& pfn, const char *symbol) noexcept {
|
||||
pfn = (T*)dlsym(RTLD_DEFAULT, symbol);
|
||||
}
|
||||
|
||||
ExternalStreamManagerAndroid& ExternalStreamManagerAndroid::get() noexcept {
|
||||
// declaring this thread local, will ensure it's destroyed with the calling thread
|
||||
static thread_local ExternalStreamManagerAndroid instance;
|
||||
return instance;
|
||||
ExternalStreamManagerAndroid& ExternalStreamManagerAndroid::create() noexcept {
|
||||
return *(new ExternalStreamManagerAndroid{});
|
||||
}
|
||||
|
||||
void ExternalStreamManagerAndroid::destroy(ExternalStreamManagerAndroid* pExternalStreamManagerAndroid) noexcept {
|
||||
delete pExternalStreamManagerAndroid;
|
||||
}
|
||||
|
||||
ExternalStreamManagerAndroid::ExternalStreamManagerAndroid() noexcept
|
||||
@@ -61,6 +63,8 @@ ExternalStreamManagerAndroid::ExternalStreamManagerAndroid() noexcept
|
||||
}
|
||||
}
|
||||
|
||||
ExternalStreamManagerAndroid::~ExternalStreamManagerAndroid() noexcept = default;
|
||||
|
||||
UTILS_NOINLINE
|
||||
JNIEnv* ExternalStreamManagerAndroid::getEnvironmentSlow() noexcept {
|
||||
JNIEnv * env = mVm.getEnvironment();
|
||||
@@ -17,7 +17,7 @@
|
||||
#ifndef TNT_FILAMENT_DRIVER_ANDROID_EXTERNAL_STREAM_MANAGER_ANDROID_H
|
||||
#define TNT_FILAMENT_DRIVER_ANDROID_EXTERNAL_STREAM_MANAGER_ANDROID_H
|
||||
|
||||
#include "android/VirtualMachineEnv.h"
|
||||
#include "private/backend/VirtualMachineEnv.h"
|
||||
|
||||
#include <backend/Platform.h>
|
||||
|
||||
@@ -31,20 +31,37 @@ typedef struct ASurfaceTexture ASurfaceTexture;
|
||||
|
||||
namespace filament {
|
||||
|
||||
/*
|
||||
* ExternalStreamManagerAndroid::Stream is basically a wrapper for SurfaceTexture.
|
||||
*
|
||||
* This class DOES DEPEND on having a GLES context, because that's how SurfaceTexture works.
|
||||
*/
|
||||
class ExternalStreamManagerAndroid {
|
||||
public:
|
||||
using Stream = backend::Platform::Stream;
|
||||
|
||||
ExternalStreamManagerAndroid() noexcept;
|
||||
static ExternalStreamManagerAndroid& get() noexcept;
|
||||
// must be called on GLES thread
|
||||
static ExternalStreamManagerAndroid& create() noexcept;
|
||||
|
||||
// must be called on GLES thread
|
||||
static void destroy(ExternalStreamManagerAndroid* pExternalStreamManagerAndroid) noexcept;
|
||||
|
||||
Stream* acquire(jobject surfaceTexture) noexcept;
|
||||
void release(Stream* stream) noexcept;
|
||||
|
||||
// attach Stream to current GLES context
|
||||
void attach(Stream* stream, intptr_t tname) noexcept;
|
||||
|
||||
// detach Stream to current GLES context
|
||||
void detach(Stream* stream) noexcept;
|
||||
|
||||
// must be called on GLES context thread, updates the stream content
|
||||
void updateTexImage(Stream* stream, int64_t* timestamp) noexcept;
|
||||
|
||||
private:
|
||||
ExternalStreamManagerAndroid() noexcept;
|
||||
~ExternalStreamManagerAndroid() noexcept;
|
||||
|
||||
VirtualMachineEnv& mVm;
|
||||
JNIEnv* mJniEnv = nullptr;
|
||||
|
||||
@@ -63,17 +80,17 @@ private:
|
||||
|
||||
JNIEnv* getEnvironmentSlow() noexcept;
|
||||
|
||||
jmethodID mSurfaceTextureClass_updateTexImage;
|
||||
jmethodID mSurfaceTextureClass_getTimestamp;
|
||||
jmethodID mSurfaceTextureClass_attachToGLContext;
|
||||
jmethodID mSurfaceTextureClass_detachFromGLContext;
|
||||
jmethodID mSurfaceTextureClass_updateTexImage{};
|
||||
jmethodID mSurfaceTextureClass_getTimestamp{};
|
||||
jmethodID mSurfaceTextureClass_attachToGLContext{};
|
||||
jmethodID mSurfaceTextureClass_detachFromGLContext{};
|
||||
|
||||
ASurfaceTexture* (*ASurfaceTexture_fromSurfaceTexture)(JNIEnv*, jobject);
|
||||
void (*ASurfaceTexture_release)(ASurfaceTexture*);
|
||||
int (*ASurfaceTexture_attachToGLContext)(ASurfaceTexture*, uint32_t);
|
||||
int (*ASurfaceTexture_detachFromGLContext)(ASurfaceTexture*);
|
||||
int (*ASurfaceTexture_updateTexImage)(ASurfaceTexture*);
|
||||
int64_t (*ASurfaceTexture_getTimestamp)(ASurfaceTexture*); // available since api 28
|
||||
ASurfaceTexture* (*ASurfaceTexture_fromSurfaceTexture)(JNIEnv*, jobject){};
|
||||
void (*ASurfaceTexture_release)(ASurfaceTexture*){};
|
||||
int (*ASurfaceTexture_attachToGLContext)(ASurfaceTexture*, uint32_t){};
|
||||
int (*ASurfaceTexture_detachFromGLContext)(ASurfaceTexture*){};
|
||||
int (*ASurfaceTexture_updateTexImage)(ASurfaceTexture*){};
|
||||
int64_t (*ASurfaceTexture_getTimestamp)(ASurfaceTexture*){}; // available since api 28
|
||||
};
|
||||
|
||||
} // namespace filament
|
||||
@@ -19,8 +19,8 @@
|
||||
|
||||
#include "PlatformCocoaGL.h"
|
||||
|
||||
#include "OpenGLDriverFactory.h"
|
||||
#include "gl_headers.h"
|
||||
#include "opengl/OpenGLDriverFactory.h"
|
||||
#include "opengl/gl_headers.h"
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Panic.h>
|
||||
@@ -30,9 +30,9 @@
|
||||
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include "OpenGLDriverFactory.h"
|
||||
#include "../OpenGLDriverFactory.h"
|
||||
|
||||
#include "OpenGLDriver.h"
|
||||
#include "../OpenGLDriver.h"
|
||||
#include "CocoaTouchExternalImage.h"
|
||||
|
||||
namespace filament {
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
#include "PlatformEGL.h"
|
||||
|
||||
#include "OpenGLDriver.h"
|
||||
#include "OpenGLContext.h"
|
||||
#include "OpenGLDriverFactory.h"
|
||||
#include "opengl/OpenGLDriver.h"
|
||||
#include "opengl/OpenGLContext.h"
|
||||
#include "opengl/OpenGLDriverFactory.h"
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
#include "PlatformEGLAndroid.h"
|
||||
|
||||
#include "OpenGLDriver.h"
|
||||
#include "OpenGLContext.h"
|
||||
#include "opengl/OpenGLDriver.h"
|
||||
#include "opengl/OpenGLContext.h"
|
||||
|
||||
#include "android/ExternalTextureManagerAndroid.h"
|
||||
#include "android/ExternalStreamManagerAndroid.h"
|
||||
#include "android/VirtualMachineEnv.h"
|
||||
#include "ExternalStreamManagerAndroid.h"
|
||||
#include "private/backend/VirtualMachineEnv.h"
|
||||
|
||||
#include <android/api-level.h>
|
||||
|
||||
@@ -73,8 +73,8 @@ using EGLStream = Platform::Stream;
|
||||
|
||||
PlatformEGLAndroid::PlatformEGLAndroid() noexcept
|
||||
: PlatformEGL(),
|
||||
mExternalStreamManager(ExternalStreamManagerAndroid::get()),
|
||||
mExternalTextureManager(ExternalTextureManagerAndroid::get()) {
|
||||
mExternalStreamManager(ExternalStreamManagerAndroid::create()),
|
||||
mExternalTextureManager(ExternalTextureManagerAndroid::create()) {
|
||||
|
||||
char scratch[PROP_VALUE_MAX + 1];
|
||||
int length = __system_property_get("ro.build.version.release", scratch);
|
||||
@@ -87,8 +87,17 @@ PlatformEGLAndroid::PlatformEGLAndroid() noexcept
|
||||
}
|
||||
}
|
||||
|
||||
backend::Driver* PlatformEGLAndroid::createDriver(void* sharedContext) noexcept {
|
||||
backend::Driver* driver = PlatformEGL::createDriver(sharedContext);
|
||||
PlatformEGLAndroid::~PlatformEGLAndroid() noexcept = default;
|
||||
|
||||
|
||||
void PlatformEGLAndroid::terminate() noexcept {
|
||||
ExternalStreamManagerAndroid::destroy(&mExternalStreamManager);
|
||||
ExternalTextureManagerAndroid::destroy(&mExternalTextureManager);
|
||||
PlatformEGL::terminate();
|
||||
}
|
||||
|
||||
Driver* PlatformEGLAndroid::createDriver(void* sharedContext) noexcept {
|
||||
Driver* driver = PlatformEGL::createDriver(sharedContext);
|
||||
auto extensions = GLUtils::split(eglQueryString(mEGLDisplay, EGL_EXTENSIONS));
|
||||
|
||||
eglGetNativeClientBufferANDROID = (PFNEGLGETNATIVECLIENTBUFFERANDROIDPROC) eglGetProcAddress("eglGetNativeClientBufferANDROID");
|
||||
@@ -146,12 +155,12 @@ void PlatformEGLAndroid::updateTexImage(Stream* stream, int64_t* timestamp) noex
|
||||
}
|
||||
|
||||
Platform::ExternalTexture* PlatformEGLAndroid::createExternalTextureStorage() noexcept {
|
||||
return mExternalTextureManager.create();
|
||||
return mExternalTextureManager.createExternalTexture();
|
||||
}
|
||||
|
||||
void PlatformEGLAndroid::reallocateExternalStorage(
|
||||
Platform::ExternalTexture* externalTexture,
|
||||
uint32_t w, uint32_t h, backend::TextureFormat format) noexcept {
|
||||
uint32_t w, uint32_t h, TextureFormat format) noexcept {
|
||||
if (externalTexture) {
|
||||
if ((EGLImageKHR)externalTexture->image != EGL_NO_IMAGE_KHR) {
|
||||
eglDestroyImageKHR(mEGLDisplay, (EGLImageKHR)externalTexture->image);
|
||||
@@ -201,13 +210,9 @@ int PlatformEGLAndroid::getOSVersion() const noexcept {
|
||||
return mOSVersion;
|
||||
}
|
||||
|
||||
backend::AcquiredImage PlatformEGLAndroid::transformAcquiredImage(backend::AcquiredImage source) noexcept {
|
||||
void* const hwbuffer = source.image;
|
||||
const backend::StreamCallback userCallback = source.callback;
|
||||
void* const userData = source.userData;
|
||||
|
||||
AcquiredImage PlatformEGLAndroid::transformAcquiredImage(AcquiredImage source) noexcept {
|
||||
// Convert the AHardwareBuffer to EGLImage.
|
||||
EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID((const AHardwareBuffer*) hwbuffer);
|
||||
EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID((const AHardwareBuffer*)source.image);
|
||||
if (!clientBuffer) {
|
||||
slog.e << "Unable to get EGLClientBuffer from AHardwareBuffer." << io::endl;
|
||||
return {};
|
||||
@@ -222,31 +227,22 @@ backend::AcquiredImage PlatformEGLAndroid::transformAcquiredImage(backend::Acqui
|
||||
|
||||
// Destroy the EGLImage before invoking the user's callback.
|
||||
struct Closure {
|
||||
void* image;
|
||||
backend::StreamCallback callback;
|
||||
void* userData;
|
||||
Closure(AcquiredImage const& acquiredImage, EGLDisplay display)
|
||||
: acquiredImage(acquiredImage), display(display) {}
|
||||
AcquiredImage acquiredImage;
|
||||
EGLDisplay display;
|
||||
};
|
||||
Closure* closure = new Closure();
|
||||
closure->callback = userCallback;
|
||||
closure->image = hwbuffer;
|
||||
closure->userData = userData;
|
||||
closure->display = mEGLDisplay;
|
||||
Closure* closure = new Closure(source, mEGLDisplay);
|
||||
auto patchedCallback = [](void* image, void* userdata) {
|
||||
Closure* closure = (Closure*) userdata;
|
||||
Closure* closure = (Closure*)userdata;
|
||||
if (eglDestroyImageKHR(closure->display, (EGLImageKHR) image) == EGL_FALSE) {
|
||||
slog.e << "eglDestroyImageKHR failed." << io::endl;
|
||||
}
|
||||
closure->callback(closure->image, closure->userData);
|
||||
closure->acquiredImage.callback(closure->acquiredImage.image, closure->acquiredImage.userData);
|
||||
delete closure;
|
||||
};
|
||||
|
||||
return {eglImage, patchedCallback, closure};
|
||||
}
|
||||
|
||||
// This must called when the library is loaded. We need this to get a reference to the global VM
|
||||
void JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
::filament::VirtualMachineEnv::JNI_OnLoad(vm);
|
||||
return { eglImage, patchedCallback, closure, source.handler };
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
@@ -28,6 +28,9 @@ class PlatformEGLAndroid final : public PlatformEGL {
|
||||
public:
|
||||
|
||||
PlatformEGLAndroid() noexcept;
|
||||
~PlatformEGLAndroid() noexcept override;
|
||||
|
||||
void terminate() noexcept override;
|
||||
|
||||
backend::Driver* createDriver(void* sharedContext) noexcept final;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <GL/glx.h>
|
||||
#include <GL/glxext.h>
|
||||
|
||||
#include "OpenGLDriverFactory.h"
|
||||
#include "../OpenGLDriverFactory.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#include <Wingdi.h>
|
||||
|
||||
#include "OpenGLDriverFactory.h"
|
||||
#include "../OpenGLDriverFactory.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// this variable is checked in BlueGL.h (included from "gl_headers.h" right after this),
|
||||
@@ -27,7 +27,7 @@
|
||||
#define FILAMENT_PLATFORM_WGL
|
||||
#endif
|
||||
|
||||
#include "gl_headers.h"
|
||||
#include "../gl_headers.h"
|
||||
|
||||
#include "Windows.h"
|
||||
#include <GL/gl.h>
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
#include "PlatformWebGL.h"
|
||||
#include "OpenGLDriverFactory.h"
|
||||
#include "../OpenGLDriverFactory.h"
|
||||
|
||||
namespace filament {
|
||||
|
||||
@@ -38,30 +38,6 @@ struct BlitterUniforms {
|
||||
float inverseSampleCount;
|
||||
};
|
||||
|
||||
// Helper function for populating barrier fields based on the desired image layout.
|
||||
// This logic is specific to blitting, please keep this private to VulkanBlitter.
|
||||
static VulkanLayoutTransition transitionHelper(VulkanLayoutTransition transition) {
|
||||
switch (transition.newLayout) {
|
||||
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
|
||||
case VK_IMAGE_LAYOUT_GENERAL:
|
||||
transition.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
transition.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
|
||||
transition.srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
transition.dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
break;
|
||||
|
||||
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
|
||||
case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
|
||||
default:
|
||||
transition.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
transition.dstAccessMask = 0;
|
||||
transition.srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
transition.dstStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
|
||||
break;
|
||||
}
|
||||
return transition;
|
||||
}
|
||||
|
||||
void VulkanBlitter::blitColor(BlitArgs args) {
|
||||
const VulkanAttachment src = args.srcTarget->getColor(mContext.currentSurface, args.targetIndex);
|
||||
const VulkanAttachment dst = args.dstTarget->getColor(mContext.currentSurface, 0);
|
||||
@@ -153,9 +129,15 @@ void VulkanBlitter::blitFast(VkImageAspectFlags aspect, VkFilter filter,
|
||||
|
||||
const VkCommandBuffer cmdbuffer = mContext.commands->get().cmdbuffer;
|
||||
|
||||
|
||||
VkImageLayout srcLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
if (src.texture) {
|
||||
srcLayout = mContext.getTextureLayout(src.texture->usage);
|
||||
}
|
||||
|
||||
transitionImageLayout(cmdbuffer, {
|
||||
src.image,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
srcLayout,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
srcRange,
|
||||
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0,
|
||||
@@ -180,21 +162,12 @@ void VulkanBlitter::blitFast(VkImageAspectFlags aspect, VkFilter filter,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, blitRegions, filter);
|
||||
}
|
||||
|
||||
if (src.texture) {
|
||||
transitionImageLayout(cmdbuffer, transitionHelper({
|
||||
.image = src.image,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = mContext.getTextureLayout(src.texture->usage),
|
||||
.subresources = srcRange
|
||||
}));
|
||||
} else if (!mContext.currentSurface->headlessQueue) {
|
||||
transitionImageLayout(cmdbuffer, transitionHelper({
|
||||
.image = src.image,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
||||
.subresources = srcRange
|
||||
}));
|
||||
}
|
||||
transitionImageLayout(cmdbuffer, blitterTransitionHelper({
|
||||
.image = src.image,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
.newLayout = srcLayout,
|
||||
.subresources = srcRange
|
||||
}));
|
||||
|
||||
// Determine the desired texture layout for the destination while ensuring that the default
|
||||
// render target is supported, which has no associated texture.
|
||||
@@ -202,9 +175,9 @@ void VulkanBlitter::blitFast(VkImageAspectFlags aspect, VkFilter filter,
|
||||
mContext.getTextureLayout(dst.texture->usage) :
|
||||
mContext.currentSurface->getColor().layout;
|
||||
|
||||
transitionImageLayout(cmdbuffer, transitionHelper({
|
||||
transitionImageLayout(cmdbuffer, blitterTransitionHelper({
|
||||
.image = dst.image,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
.newLayout = desiredLayout,
|
||||
.subresources = dstRange,
|
||||
}));
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user