Lower limit from API 21 to API 19 (#1701)

* Lower limit from API 21 to API 19

This was requested by an internal application. API 19 is when OpenGL
ES 3.0 support was added so there is no good reason for us to not
support this API level. The only trick is to avoid referring to the
glTexStorage2DMultisample symbol directly as it only exists in 3.1.

* Compile out code we never use

* Use reflection to handle shared EGL contexts pre-API 21.

* Remove comment

* More fixes required to run on API level 19

- dlym() fails for ashmem on API 19, so we only try on API 26+ instead.
- Older emulation for OpenGL ES 3.0 returns error states for valid API calls so we need to clear the GL error bit before we create the GL driver.
- Activity lifecycle changes since API 19 would cause animations to keep running and to reference destroyed objects.
- EGLContext.getNativeHandle() is new in API 21, we need to use reflection on API 19. The new code path uses the class loading trick to avoid a bytecode verification error on API 19.

* Filament now runs properly on API level 19

This commit adds a new api_level() API to libutils which can be used to
query the platform's API level. On Android it works as expected, other
platforms currently return 0.
This commit is contained in:
Romain Guy
2019-09-28 14:13:06 +03:00
committed by GitHub
parent 21b208398b
commit a67d92c2ca
35 changed files with 373 additions and 87 deletions

View File

@@ -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.

View File

@@ -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")

View File

@@ -1,29 +1,113 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair source="cpp" header="h" fileNamingConvention="NONE" />
<pair source="c" header="h" fileNamingConvention="NONE" />
</extensions>
</Objective-C-extensions>
<codeStyleSettings language="XML">
<arrangement>
<rules>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:android</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>xmlns:.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:id</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*:name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>name</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>style</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>^$</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
</AND>
</match>
<order>ANDROID_ATTRIBUTE_ORDER</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<NAME>.*</NAME>
<XML_ATTRIBUTE />
<XML_NAMESPACE>.*</XML_NAMESPACE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings>
</code_scheme>
</component>

View File

@@ -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")

View File

@@ -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;
}
}
}

View File

@@ -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();
}
}

View File

@@ -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")

View File

@@ -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"

View File

@@ -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()

View File

@@ -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"

View File

@@ -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()

View File

@@ -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"

View File

@@ -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()

View File

@@ -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"

View File

@@ -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()

View File

@@ -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"

View File

@@ -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()

View File

@@ -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"

View File

@@ -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()

View File

@@ -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"

View File

@@ -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()

View File

@@ -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")
}

View File

@@ -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"

View File

@@ -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()

View File

@@ -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 {

View File

@@ -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)

View File

@@ -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)

View File

@@ -16,6 +16,7 @@
#include "ExternalStreamManagerAndroid.h"
#include <utils/api_level.h>
#include <utils/compiler.h>
#include <utils/Log.h>
@@ -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();

View File

@@ -17,6 +17,7 @@
#include "ExternalTextureManagerAndroid.h"
#include <utils/api_level.h>
#include <utils/compiler.h>
#include <utils/Log.h>
@@ -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
}

View File

@@ -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;

View File

@@ -41,9 +41,11 @@
#include <android/api-level.h>
#include <sys/system_properties.h>
// 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<std::string> {
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");

View File

@@ -23,6 +23,7 @@ set(DIST_HDRS
)
set(SRCS
src/api_level.cpp
src/ashmem.cpp
src/Allocator.cpp
src/CallStack.cpp

View File

@@ -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 <utils/compiler.h>
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

View File

@@ -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 <utils/api_level.h>
#ifdef ANDROID
#include <mutex>
#include <sys/system_properties.h>
#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

View File

@@ -15,6 +15,7 @@
*/
#include <utils/ashmem.h>
#include <utils/api_level.h>
#include <errno.h>
#include <assert.h>
@@ -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;