diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 7f6e8f8866..494fd45c23 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -5,6 +5,7 @@ A new header is inserted each time a *tag* is created.
## Next release
+- Minimum API level on Android is now API 19 instead of API 21.
- Added missing API documentation.
- Improved existing API documentation.
- Added `Camera::setExposure(float)` to directly control the camera's exposure.
diff --git a/android/filamat-android/build.gradle b/android/filamat-android/build.gradle
index ba1faf9895..9e04bc2d86 100644
--- a/android/filamat-android/build.gradle
+++ b/android/filamat-android/build.gradle
@@ -47,7 +47,7 @@ android {
externalNativeBuild {
cmake {
arguments.add("-DANDROID_PIE=ON")
- arguments.add("-DANDROID_PLATFORM=android-21")
+ arguments.add("-DANDROID_PLATFORM=android-19")
arguments.add("-DANDROID_STL=c++_static")
arguments.add("-DFILAMENT_DIST_DIR=${filament_path}".toString())
cppFlags.add("-std=c++14")
diff --git a/android/filament-android/.idea/codeStyles/Project.xml b/android/filament-android/.idea/codeStyles/Project.xml
index 30aa626c23..ae78c113ff 100644
--- a/android/filament-android/.idea/codeStyles/Project.xml
+++ b/android/filament-android/.idea/codeStyles/Project.xml
@@ -1,29 +1,113 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ xmlns:android
+
+ ^$
+
+
+
+
+
+
+
+
+ xmlns:.*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*:id
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ .*:name
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ name
+
+ ^$
+
+
+
+
+
+
+
+
+ style
+
+ ^$
+
+
+
+
+
+
+
+
+ .*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*
+
+ http://schemas.android.com/apk/res/android
+
+
+ ANDROID_ATTRIBUTE_ORDER
+
+
+
+
+
+
+ .*
+
+ .*
+
+
+ BY_NAME
+
+
+
+
+
\ No newline at end of file
diff --git a/android/filament-android/build.gradle b/android/filament-android/build.gradle
index 7aece47a7a..97bd4c621e 100644
--- a/android/filament-android/build.gradle
+++ b/android/filament-android/build.gradle
@@ -37,9 +37,9 @@ if (project.hasProperty("filament_dist_dir")) {
android {
compileSdkVersion 29
defaultConfig {
- // Our minSdkVersion is actually 21, we lie and say 14 here so apps don't have
+ // Our minSdkVersion is actually 19, we lie and say 14 here so apps don't have
// to increase their minSdkVersion unnecessarily. It is however up to them to
- // ensure they do not initialize Filament on API levels < 21.
+ // ensure they do not initialize Filament on API levels < 19.
minSdkVersion 14
targetSdkVersion 29
versionCode 1
@@ -50,7 +50,7 @@ android {
externalNativeBuild {
cmake {
arguments.add("-DANDROID_PIE=ON")
- arguments.add("-DANDROID_PLATFORM=android-21")
+ arguments.add("-DANDROID_PLATFORM=android-19")
arguments.add("-DANDROID_STL=c++_static")
arguments.add("-DFILAMENT_DIST_DIR=${filament_path}".toString())
cppFlags.add("-std=c++14")
diff --git a/android/filament-android/src/main/java/com/google/android/filament/AndroidPlatform.java b/android/filament-android/src/main/java/com/google/android/filament/AndroidPlatform.java
index 6570a623c4..cb6add9e04 100644
--- a/android/filament-android/src/main/java/com/google/android/filament/AndroidPlatform.java
+++ b/android/filament-android/src/main/java/com/google/android/filament/AndroidPlatform.java
@@ -19,8 +19,10 @@ package com.google.android.filament;
import android.graphics.SurfaceTexture;
import android.opengl.EGL14;
import android.opengl.EGLContext;
+import android.os.Build;
import android.util.Log;
import android.view.Surface;
+import java.lang.reflect.Method;
final class AndroidPlatform extends Platform {
private static final String LOG_TAG = "Filament";
@@ -59,6 +61,20 @@ final class AndroidPlatform extends Platform {
@Override
long getSharedContextNativeHandle(Object sharedContext) {
- return ((EGLContext) sharedContext).getNativeHandle();
+ if (Build.VERSION.SDK_INT >= 21) {
+ return AndroidPlatform21.getSharedContextNativeHandle(sharedContext);
+ } else {
+ try {
+ //noinspection JavaReflectionMemberAccess
+ Method method = EGLContext.class.getDeclaredMethod("getHandle");
+ Integer handle = (Integer) method.invoke(sharedContext);
+ //noinspection ConstantConditions
+ return handle.longValue();
+ } catch (Exception e) {
+ Log.d(LOG_TAG, "Could not access shared context's native handle", e);
+ }
+ // Should not happen
+ return 0;
+ }
}
}
diff --git a/android/filament-android/src/main/java/com/google/android/filament/AndroidPlatform21.java b/android/filament-android/src/main/java/com/google/android/filament/AndroidPlatform21.java
new file mode 100644
index 0000000000..c50c00a167
--- /dev/null
+++ b/android/filament-android/src/main/java/com/google/android/filament/AndroidPlatform21.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+package com.google.android.filament;
+
+import android.opengl.EGLContext;
+
+final class AndroidPlatform21 {
+ static long getSharedContextNativeHandle(Object sharedContext) {
+ return ((EGLContext) sharedContext).getNativeHandle();
+ }
+}
diff --git a/android/gltfio-android/build.gradle b/android/gltfio-android/build.gradle
index 5024fd04a8..2f904336a6 100644
--- a/android/gltfio-android/build.gradle
+++ b/android/gltfio-android/build.gradle
@@ -47,7 +47,7 @@ android {
externalNativeBuild {
cmake {
arguments.add("-DANDROID_PIE=ON")
- arguments.add("-DANDROID_PLATFORM=android-21")
+ arguments.add("-DANDROID_PLATFORM=android-19")
arguments.add("-DANDROID_STL=c++_static")
arguments.add("-DFILAMENT_DIST_DIR=${filament_path}".toString())
cppFlags.add("-std=c++14")
diff --git a/android/samples/gltf-bloom/app/build.gradle b/android/samples/gltf-bloom/app/build.gradle
index a373781fd3..707374599a 100644
--- a/android/samples/gltf-bloom/app/build.gradle
+++ b/android/samples/gltf-bloom/app/build.gradle
@@ -38,7 +38,7 @@ android {
compileSdkVersion 29
defaultConfig {
applicationId "com.google.android.filament.gltf"
- minSdkVersion 26
+ minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
diff --git a/android/samples/gltf-bloom/app/src/main/java/com/google/android/filament/gltf/MainActivity.kt b/android/samples/gltf-bloom/app/src/main/java/com/google/android/filament/gltf/MainActivity.kt
index 0e59412946..013c007a04 100644
--- a/android/samples/gltf-bloom/app/src/main/java/com/google/android/filament/gltf/MainActivity.kt
+++ b/android/samples/gltf-bloom/app/src/main/java/com/google/android/filament/gltf/MainActivity.kt
@@ -426,6 +426,11 @@ class MainActivity : Activity() {
override fun onDestroy() {
super.onDestroy()
+
+ // Stop the animation and any pending frame
+ choreographer.removeFrameCallback(frameScheduler)
+ animator.cancel();
+
// Always detach the surface before destroying the engine
uiHelper.detach()
diff --git a/android/samples/hello-triangle/app/build.gradle b/android/samples/hello-triangle/app/build.gradle
index 9523759200..bb12e8c252 100644
--- a/android/samples/hello-triangle/app/build.gradle
+++ b/android/samples/hello-triangle/app/build.gradle
@@ -22,7 +22,7 @@ android {
compileSdkVersion 29
defaultConfig {
applicationId "com.google.android.filament.hellotriangle"
- minSdkVersion 21
+ minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
diff --git a/android/samples/hello-triangle/app/src/main/java/com/google/android/filament/hellotriangle/MainActivity.kt b/android/samples/hello-triangle/app/src/main/java/com/google/android/filament/hellotriangle/MainActivity.kt
index fdc9e497a8..f19c1abbac 100644
--- a/android/samples/hello-triangle/app/src/main/java/com/google/android/filament/hellotriangle/MainActivity.kt
+++ b/android/samples/hello-triangle/app/src/main/java/com/google/android/filament/hellotriangle/MainActivity.kt
@@ -253,6 +253,11 @@ class MainActivity : Activity() {
override fun onDestroy() {
super.onDestroy()
+
+ // Stop the animation and any pending frame
+ choreographer.removeFrameCallback(frameScheduler)
+ animator.cancel();
+
// Always detach the surface before destroying the engine
uiHelper.detach()
diff --git a/android/samples/image-based-lighting/app/build.gradle b/android/samples/image-based-lighting/app/build.gradle
index 75622921a7..ddeff1f5e0 100644
--- a/android/samples/image-based-lighting/app/build.gradle
+++ b/android/samples/image-based-lighting/app/build.gradle
@@ -40,7 +40,7 @@ android {
compileSdkVersion 29
defaultConfig {
applicationId "com.google.android.filament.ibl"
- minSdkVersion 21
+ minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
diff --git a/android/samples/image-based-lighting/app/src/main/java/com/google/android/filament/ibl/MainActivity.kt b/android/samples/image-based-lighting/app/src/main/java/com/google/android/filament/ibl/MainActivity.kt
index 14b02175bd..0d9f94416a 100644
--- a/android/samples/image-based-lighting/app/src/main/java/com/google/android/filament/ibl/MainActivity.kt
+++ b/android/samples/image-based-lighting/app/src/main/java/com/google/android/filament/ibl/MainActivity.kt
@@ -230,6 +230,11 @@ class MainActivity : Activity() {
override fun onDestroy() {
super.onDestroy()
+
+ // Stop the animation and any pending frame
+ choreographer.removeFrameCallback(frameScheduler)
+ animator.cancel();
+
// Always detach the surface before destroying the engine
uiHelper.detach()
diff --git a/android/samples/lit-cube/app/build.gradle b/android/samples/lit-cube/app/build.gradle
index 8d78fa8713..daa0ce1a11 100644
--- a/android/samples/lit-cube/app/build.gradle
+++ b/android/samples/lit-cube/app/build.gradle
@@ -22,7 +22,7 @@ android {
compileSdkVersion 29
defaultConfig {
applicationId "com.google.android.filament.litcube"
- minSdkVersion 21
+ minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
diff --git a/android/samples/lit-cube/app/src/main/java/com/google/android/filament/litcube/MainActivity.kt b/android/samples/lit-cube/app/src/main/java/com/google/android/filament/litcube/MainActivity.kt
index 95839956a8..defa60a5f1 100644
--- a/android/samples/lit-cube/app/src/main/java/com/google/android/filament/litcube/MainActivity.kt
+++ b/android/samples/lit-cube/app/src/main/java/com/google/android/filament/litcube/MainActivity.kt
@@ -338,6 +338,11 @@ class MainActivity : Activity() {
override fun onDestroy() {
super.onDestroy()
+
+ // Stop the animation and any pending frame
+ choreographer.removeFrameCallback(frameScheduler)
+ animator.cancel();
+
// Always detach the surface before destroying the engine
uiHelper.detach()
diff --git a/android/samples/material-builder/app/build.gradle b/android/samples/material-builder/app/build.gradle
index 874dbaf013..1d634c0ec0 100644
--- a/android/samples/material-builder/app/build.gradle
+++ b/android/samples/material-builder/app/build.gradle
@@ -27,7 +27,7 @@ android {
compileSdkVersion 29
defaultConfig {
applicationId "com.google.android.filament.material_builder"
- minSdkVersion 21
+ minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
diff --git a/android/samples/material-builder/app/src/main/java/com/google/android/filament/material_builder/MainActivity.kt b/android/samples/material-builder/app/src/main/java/com/google/android/filament/material_builder/MainActivity.kt
index a0f308b001..5c8b96be41 100644
--- a/android/samples/material-builder/app/src/main/java/com/google/android/filament/material_builder/MainActivity.kt
+++ b/android/samples/material-builder/app/src/main/java/com/google/android/filament/material_builder/MainActivity.kt
@@ -266,6 +266,11 @@ class MainActivity : Activity() {
override fun onDestroy() {
super.onDestroy()
+
+ // Stop the animation and any pending frame
+ choreographer.removeFrameCallback(frameScheduler)
+ animator.cancel();
+
// Always detach the surface before destroying the engine
uiHelper.detach()
diff --git a/android/samples/texture-view/app/build.gradle b/android/samples/texture-view/app/build.gradle
index 70afbb965e..0559e057a9 100644
--- a/android/samples/texture-view/app/build.gradle
+++ b/android/samples/texture-view/app/build.gradle
@@ -22,7 +22,7 @@ android {
compileSdkVersion 29
defaultConfig {
applicationId "com.google.android.filament.textureview"
- minSdkVersion 21
+ minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
diff --git a/android/samples/texture-view/app/src/main/java/com/google/android/filament/textureview/MainActivity.kt b/android/samples/texture-view/app/src/main/java/com/google/android/filament/textureview/MainActivity.kt
index 436ad9dc97..550d399d03 100644
--- a/android/samples/texture-view/app/src/main/java/com/google/android/filament/textureview/MainActivity.kt
+++ b/android/samples/texture-view/app/src/main/java/com/google/android/filament/textureview/MainActivity.kt
@@ -253,6 +253,11 @@ class MainActivity : Activity() {
override fun onDestroy() {
super.onDestroy()
+
+ // Stop the animation and any pending frame
+ choreographer.removeFrameCallback(frameScheduler)
+ animator.cancel();
+
// Always detach the surface before destroying the engine
uiHelper.detach()
diff --git a/android/samples/textured-object/app/build.gradle b/android/samples/textured-object/app/build.gradle
index 87b6a9dd81..4db15b8247 100644
--- a/android/samples/textured-object/app/build.gradle
+++ b/android/samples/textured-object/app/build.gradle
@@ -40,7 +40,7 @@ android {
compileSdkVersion 29
defaultConfig {
applicationId "com.google.android.filament.textured"
- minSdkVersion 26
+ minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
diff --git a/android/samples/textured-object/app/src/main/java/com/google/android/filament/textured/MainActivity.kt b/android/samples/textured-object/app/src/main/java/com/google/android/filament/textured/MainActivity.kt
index 181a2898f9..161a495eb9 100644
--- a/android/samples/textured-object/app/src/main/java/com/google/android/filament/textured/MainActivity.kt
+++ b/android/samples/textured-object/app/src/main/java/com/google/android/filament/textured/MainActivity.kt
@@ -249,6 +249,11 @@ class MainActivity : Activity() {
override fun onDestroy() {
super.onDestroy()
+
+ // Stop the animation and any pending frame
+ choreographer.removeFrameCallback(frameScheduler)
+ animator.cancel();
+
// Always detach the surface before destroying the engine
uiHelper.detach()
diff --git a/android/samples/textured-object/app/src/main/java/com/google/android/filament/textured/TextureLoader.kt b/android/samples/textured-object/app/src/main/java/com/google/android/filament/textured/TextureLoader.kt
index 784a914e2a..1306e6fb1b 100644
--- a/android/samples/textured-object/app/src/main/java/com/google/android/filament/textured/TextureLoader.kt
+++ b/android/samples/textured-object/app/src/main/java/com/google/android/filament/textured/TextureLoader.kt
@@ -79,19 +79,20 @@ private fun internalFormat(type: TextureType) = when (type) {
}
// Not required when SKIP_BITMAP_COPY is true
-private fun format(bitmap: Bitmap) = when (bitmap.config) {
- Bitmap.Config.ALPHA_8 -> Texture.Format.ALPHA
- Bitmap.Config.RGB_565 -> Texture.Format.RGB
- Bitmap.Config.ARGB_8888 -> Texture.Format.RGBA
- Bitmap.Config.RGBA_F16 -> Texture.Format.RGBA
+// Use String representation for compatibility across API levels
+private fun format(bitmap: Bitmap) = when (bitmap.config.name) {
+ "ALPHA_8" -> Texture.Format.ALPHA
+ "RGB_565" -> Texture.Format.RGB
+ "ARGB_8888" -> Texture.Format.RGBA
+ "RGBA_F16" -> Texture.Format.RGBA
else -> throw IllegalArgumentException("Unknown bitmap configuration")
}
// Not required when SKIP_BITMAP_COPY is true
-private fun type(bitmap: Bitmap) = when (bitmap.config) {
- Bitmap.Config.ALPHA_8 -> Texture.Type.UBYTE
- Bitmap.Config.RGB_565 -> Texture.Type.UBYTE
- Bitmap.Config.ARGB_8888 -> Texture.Type.UBYTE
- Bitmap.Config.RGBA_F16 -> Texture.Type.HALF
+private fun type(bitmap: Bitmap) = when (bitmap.config.name) {
+ "ALPHA_8" -> Texture.Type.UBYTE
+ "RGB_565" -> Texture.Type.UBYTE
+ "ARGB_8888" -> Texture.Type.UBYTE
+ "RGBA_F16" -> Texture.Type.HALF
else -> throw IllegalArgumentException("Unsupported bitmap configuration")
}
diff --git a/android/samples/transparent-view/app/build.gradle b/android/samples/transparent-view/app/build.gradle
index 9523759200..bb12e8c252 100644
--- a/android/samples/transparent-view/app/build.gradle
+++ b/android/samples/transparent-view/app/build.gradle
@@ -22,7 +22,7 @@ android {
compileSdkVersion 29
defaultConfig {
applicationId "com.google.android.filament.hellotriangle"
- minSdkVersion 21
+ minSdkVersion 19
targetSdkVersion 29
versionCode 1
versionName "1.0"
diff --git a/android/samples/transparent-view/app/src/main/java/com/google/android/filament/transparentrendering/MainActivity.kt b/android/samples/transparent-view/app/src/main/java/com/google/android/filament/transparentrendering/MainActivity.kt
index e3d7097c7e..7d81786a00 100644
--- a/android/samples/transparent-view/app/src/main/java/com/google/android/filament/transparentrendering/MainActivity.kt
+++ b/android/samples/transparent-view/app/src/main/java/com/google/android/filament/transparentrendering/MainActivity.kt
@@ -271,6 +271,11 @@ class MainActivity : Activity() {
override fun onDestroy() {
super.onDestroy()
+
+ // Stop the animation and any pending frame
+ choreographer.removeFrameCallback(frameScheduler)
+ animator.cancel();
+
// Always detach the surface before destroying the engine
uiHelper.detach()
diff --git a/build.sh b/build.sh
index a4efc3142d..6bcf929f8c 100755
--- a/build.sh
+++ b/build.sh
@@ -121,8 +121,11 @@ function build_clean {
echo "Cleaning build directories..."
rm -Rf out
rm -Rf android/filament-android/build android/filament-android/.externalNativeBuild
+ rm -Rf android/filament-android/build android/filament-android/.cxx
rm -Rf android/filamat-android/build android/filamat-android/.externalNativeBuild
+ rm -Rf android/filamat-android/build android/filamat-android/.cxx
rm -Rf android/gltfio-android/build android/gltfio-android/.externalNativeBuild
+ rm -Rf android/gltfio-android/build android/gltfio-android/.cxx
}
function build_desktop_target {
diff --git a/build/toolchain-arm7-linux-android.cmake b/build/toolchain-arm7-linux-android.cmake
index 3e37fd35db..aa3cbb1ce8 100644
--- a/build/toolchain-arm7-linux-android.cmake
+++ b/build/toolchain-arm7-linux-android.cmake
@@ -21,7 +21,7 @@ set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
# android
-set(API_LEVEL 21)
+set(API_LEVEL 19)
# architecture
set(ARCH armv7a-linux-androideabi)
diff --git a/build/toolchain-x86-linux-android.cmake b/build/toolchain-x86-linux-android.cmake
index e5d68d2a0c..d1d9f1ab75 100644
--- a/build/toolchain-x86-linux-android.cmake
+++ b/build/toolchain-x86-linux-android.cmake
@@ -21,7 +21,7 @@ set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
# android
-set(API_LEVEL 21)
+set(API_LEVEL 19)
# architecture
set(ARCH i686-linux-android)
diff --git a/filament/backend/src/android/ExternalStreamManagerAndroid.cpp b/filament/backend/src/android/ExternalStreamManagerAndroid.cpp
index 26b9e0eff0..da2941f545 100644
--- a/filament/backend/src/android/ExternalStreamManagerAndroid.cpp
+++ b/filament/backend/src/android/ExternalStreamManagerAndroid.cpp
@@ -16,6 +16,7 @@
#include "ExternalStreamManagerAndroid.h"
+#include
#include
#include
@@ -42,22 +43,22 @@ ExternalStreamManagerAndroid& ExternalStreamManagerAndroid::get() noexcept {
ExternalStreamManagerAndroid::ExternalStreamManagerAndroid() noexcept
: mVm(VirtualMachineEnv::get()) {
- // 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.
- loadSymbol(ASurfaceTexture_fromSurfaceTexture, "ASurfaceTexture_fromSurfaceTexture");
- loadSymbol(ASurfaceTexture_release, "ASurfaceTexture_release");
- loadSymbol(ASurfaceTexture_attachToGLContext, "ASurfaceTexture_attachToGLContext");
- loadSymbol(ASurfaceTexture_detachFromGLContext, "ASurfaceTexture_detachFromGLContext");
- loadSymbol(ASurfaceTexture_updateTexImage, "ASurfaceTexture_updateTexImage");
- loadSymbol(ASurfaceTexture_getTimestamp, "ASurfaceTexture_getTimestamp");
+ // the following dlsym() calls don't work on API 19
+ if (api_level() >= 21) {
+ loadSymbol(ASurfaceTexture_fromSurfaceTexture, "ASurfaceTexture_fromSurfaceTexture");
+ loadSymbol(ASurfaceTexture_release, "ASurfaceTexture_release");
+ loadSymbol(ASurfaceTexture_attachToGLContext, "ASurfaceTexture_attachToGLContext");
+ loadSymbol(ASurfaceTexture_detachFromGLContext, "ASurfaceTexture_detachFromGLContext");
+ loadSymbol(ASurfaceTexture_updateTexImage, "ASurfaceTexture_updateTexImage");
+ loadSymbol(ASurfaceTexture_getTimestamp, "ASurfaceTexture_getTimestamp");
+ }
+
if (ASurfaceTexture_fromSurfaceTexture) {
slog.d << "Using ASurfaceTexture" << io::endl;
}
}
-
UTILS_NOINLINE
JNIEnv* ExternalStreamManagerAndroid::getEnvironmentSlow() noexcept {
JNIEnv * env = mVm.getEnvironment();
diff --git a/filament/backend/src/android/ExternalTextureManagerAndroid.cpp b/filament/backend/src/android/ExternalTextureManagerAndroid.cpp
index a52fb71ebd..d667db2bcc 100644
--- a/filament/backend/src/android/ExternalTextureManagerAndroid.cpp
+++ b/filament/backend/src/android/ExternalTextureManagerAndroid.cpp
@@ -17,6 +17,7 @@
#include "ExternalTextureManagerAndroid.h"
+#include
#include
#include
@@ -94,8 +95,11 @@ ExternalTextureManagerAndroid::ExternalTextureManagerAndroid() noexcept
// if we compile for API 26 (Oreo) and above, we're guaranteed to have AHardwareBuffer
// in all other cases, we need to get them at runtime.
#ifndef PLATFORM_HAS_HARDWAREBUFFER
- loadSymbol(AHardwareBuffer_allocate, "AHardwareBuffer_allocate");
- loadSymbol(AHardwareBuffer_release, "AHardwareBuffer_release");
+ // the following dlsym() calls don't work on API 19
+ if (api_level() >= 21) {
+ loadSymbol(AHardwareBuffer_allocate, "AHardwareBuffer_allocate");
+ loadSymbol(AHardwareBuffer_release, "AHardwareBuffer_release");
+ }
#endif
}
diff --git a/filament/backend/src/opengl/OpenGLDriver.cpp b/filament/backend/src/opengl/OpenGLDriver.cpp
index ebe1c962f8..db391ce4c2 100644
--- a/filament/backend/src/opengl/OpenGLDriver.cpp
+++ b/filament/backend/src/opengl/OpenGLDriver.cpp
@@ -35,6 +35,10 @@
// we don't want to rely on it.
#define ALLOW_REVERSE_MULTISAMPLE_RESOLVE false
+// We can only support this feature on OpenGL ES 3.1+
+// Support is currently disabled as we don't need it
+#define TEXTURE_2D_MULTISAMPLE_SUPPORTED false
+
#if defined(__EMSCRIPTEN__)
#define HAS_MAPBUFFERS 0
#else
@@ -65,7 +69,7 @@ Driver* OpenGLDriverFactory::create(
return OpenGLDriver::create(platform, sharedGLContext);
}
-} // namesapce backend
+} // namespace backend
using namespace backend;
using namespace GLUtils;
@@ -76,7 +80,8 @@ Driver* OpenGLDriver::create(
assert(platform);
OpenGLPlatform* const ec = platform;
- { // here we check we're on a supported version of GL before initializing the driver
+ {
+ // here we check we're on a supported version of GL before initializing the driver
GLint major = 0, minor = 0;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
@@ -93,7 +98,6 @@ Driver* OpenGLDriver::create(
if (UTILS_UNLIKELY(!(major >= 3 && minor >= 0))) {
PANIC_LOG("OpenGL ES 3.0 minimum needed (current %d.%d)", major, minor);
goto cleanup;
-
}
} else if (GL41_HEADERS) {
// we require GL 4.1 headers and minimum version
@@ -573,20 +577,24 @@ void OpenGLDriver::textureStorage(OpenGLDriver::GLTexture* t,
break;
}
case GL_TEXTURE_2D_MULTISAMPLE:
- // NOTE: if there is a mix of texture and renderbuffers, "fixed_sample_locations" must be true
- // NOTE: what's the benefit of setting "fixed_sample_locations" to false?
+ if (TEXTURE_2D_MULTISAMPLE_SUPPORTED) {
+ // NOTE: if there is a mix of texture and renderbuffers, "fixed_sample_locations" must be true
+ // NOTE: what's the benefit of setting "fixed_sample_locations" to false?
#if GLES31_HEADERS
- // only supported from GL 4.3 and GLES 3.1
- glTexStorage2DMultisample(t->gl.target, t->samples, t->gl.internalFormat,
- GLsizei(width), GLsizei(height), GL_TRUE);
+ // only supported from GL 4.3 and GLES 3.1
+ glTexStorage2DMultisample(t->gl.target, t->samples, t->gl.internalFormat,
+ GLsizei(width), GLsizei(height), GL_TRUE);
#elif GL41_HEADERS
- // only supported in GL (never in GLES)
- // TODO: use glTexStorage2DMultisample() on GL 4.3 and above
- glTexImage2DMultisample(t->gl.target, t->samples, t->gl.internalFormat,
- GLsizei(width), GLsizei(height), GL_TRUE);
+ // only supported in GL (never in GLES)
+ // TODO: use glTexStorage2DMultisample() on GL 4.3 and above
+ glTexImage2DMultisample(t->gl.target, t->samples, t->gl.internalFormat,
+ GLsizei(width), GLsizei(height), GL_TRUE);
#else
# error "GL/GLES header version not supported"
#endif
+ } else {
+ PANIC_LOG("GL_TEXTURE_2D_MULTISAMPLE is not supported");
+ }
break;
default: // cannot happen
break;
diff --git a/filament/backend/src/opengl/PlatformEGL.cpp b/filament/backend/src/opengl/PlatformEGL.cpp
index 099adba4fd..4a2bf9336d 100644
--- a/filament/backend/src/opengl/PlatformEGL.cpp
+++ b/filament/backend/src/opengl/PlatformEGL.cpp
@@ -41,9 +41,11 @@
#include
#include
-// We require filament to be built with a API 21 toolchain, before that, OpenGLES 3.0 didn't exist
-#if __ANDROID_API__ < 21
-# error "__ANDROID_API__ must be at least 21"
+// We require filament to be built with a API 19 toolchain, before that, OpenGLES 3.0 didn't exist
+// Actually, OpenGL ES 3.0 was added to API 18, but API 19 is the better target and
+// the minimum for Jetpack at the time of this comment.
+#if __ANDROID_API__ < 19
+# error "__ANDROID_API__ must be at least 19"
#endif
using namespace utils;
@@ -96,6 +98,14 @@ static void logEglError(const char* name) noexcept {
slog.e << name << " failed with " << err << io::endl;
}
+static void clearGlError() noexcept {
+ // clear GL error that may have been set by previous calls
+ GLenum error = glGetError();
+ if (error != GL_NO_ERROR) {
+ slog.w << "Ignoring pending GL error " << io::hex << error << io::endl;
+ }
+}
+
class unordered_string_set : public std::unordered_set {
public:
bool has(const char* str) {
@@ -251,7 +261,6 @@ Driver* PlatformEGL::createDriver(void* sharedContext) noexcept {
}
}
-
if (!extensions.has("EGL_KHR_no_config_context")) {
// if we have the EGL_KHR_no_config_context, we don't need to worry about the config
// when creating the context, otherwise, we must always pick a transparent config.
@@ -290,6 +299,9 @@ Driver* PlatformEGL::createDriver(void* sharedContext) noexcept {
initializeGlExtensions();
+ // this is needed with older emulators/API levels on Android
+ clearGlError();
+
// success!!
return OpenGLDriverFactory::create(this, sharedContext);
@@ -513,7 +525,7 @@ void PlatformEGL::initializeGlExtensions() noexcept {
GLint n;
glGetIntegerv(GL_NUM_EXTENSIONS, &n);
for (GLint i = 0; i < n; ++i) {
- const char * const extension = (const char*)glGetStringi(GL_EXTENSIONS, (GLuint)i);
+ const char * const extension = (const char*) glGetStringi(GL_EXTENSIONS, (GLuint)i);
glExtensions.insert(extension);
}
ext.OES_EGL_image_external_essl3 = glExtensions.has("GL_OES_EGL_image_external_essl3");
diff --git a/libs/utils/CMakeLists.txt b/libs/utils/CMakeLists.txt
index 8cf133bfd5..0b4e7b7253 100644
--- a/libs/utils/CMakeLists.txt
+++ b/libs/utils/CMakeLists.txt
@@ -23,6 +23,7 @@ set(DIST_HDRS
)
set(SRCS
+ src/api_level.cpp
src/ashmem.cpp
src/Allocator.cpp
src/CallStack.cpp
diff --git a/libs/utils/include/utils/api_level.h b/libs/utils/include/utils/api_level.h
new file mode 100644
index 0000000000..bf347fd2ff
--- /dev/null
+++ b/libs/utils/include/utils/api_level.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 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_UTILS_API_H
+#define TNT_UTILS_API_H
+
+#include
+
+namespace utils {
+
+/**
+ * Returns this platform's API level. On Android this function will return
+ * the API level as defined by the SDK API level version. If a platform does
+ * not have an API level, this function returns 0.
+ */
+UTILS_PUBLIC
+int api_level();
+
+} // namespace utils
+
+#endif // TNT_UTILS_ARCHITECTURE_H
diff --git a/libs/utils/src/api_level.cpp b/libs/utils/src/api_level.cpp
new file mode 100644
index 0000000000..0e74770bd4
--- /dev/null
+++ b/libs/utils/src/api_level.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 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_UTILS_API_H
+#define TNT_UTILS_API_H
+
+#include
+
+#ifdef ANDROID
+#include
+#include
+#endif
+
+namespace utils {
+
+#ifdef ANDROID
+
+uint32_t sApiLevel = 0;
+std::once_flag sApiLevelOnceFlag;
+
+int api_level() {
+ std::call_once(sApiLevelOnceFlag, []() {
+ char sdkVersion[PROP_VALUE_MAX];
+ __system_property_get("ro.build.version.sdk", sdkVersion);
+ sApiLevel = atoi(sdkVersion);
+ });
+ return sApiLevel;
+}
+
+#else
+
+int api_level() {
+ return 0; // API level is only supported on Android currently
+}
+
+#endif
+
+} // namespace utils
+
+#endif // TNT_UTILS_ARCHITECTURE_H
diff --git a/libs/utils/src/ashmem.cpp b/libs/utils/src/ashmem.cpp
index 08e01e5867..ef3595ead6 100644
--- a/libs/utils/src/ashmem.cpp
+++ b/libs/utils/src/ashmem.cpp
@@ -15,6 +15,7 @@
*/
#include
+#include
#include
#include
@@ -85,13 +86,15 @@ static int __ashmem_open() {
}
int ashmem_create_region(const char *name, size_t size) {
-
- // dynamically check if we have "ASharedMemory_create" (should be the case since 26 (Oreo))
- using TASharedMemory_create = int(*)(const char *name, size_t size);
- TASharedMemory_create pfnASharedMemory_create =
- (TASharedMemory_create)dlsym(RTLD_DEFAULT, "ASharedMemory_create");
- if (pfnASharedMemory_create) {
- return pfnASharedMemory_create(name, size);
+ // Fetch the API level to avoid dlsym() on API 19
+ if (api_level() >= 26) {
+ // dynamically check if we have "ASharedMemory_create" (should be the case since 26 (Oreo))
+ using TASharedMemory_create = int(*)(const char *name, size_t size);
+ TASharedMemory_create pfnASharedMemory_create =
+ (TASharedMemory_create)dlsym(RTLD_DEFAULT, "ASharedMemory_create");
+ if (pfnASharedMemory_create) {
+ return pfnASharedMemory_create(name, size);
+ }
}
int ret, save_errno;