Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android: Implemented AndroidNativeBufferAllocator - Deprecated AndroidBufferAllocator #1821

Merged
59 changes: 59 additions & 0 deletions jme3-android-native/bufferallocator.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// build file for native buffer allocator, created by pavl_g on 5/17/22.

// directories for native source
String bufferAllocatorAndroidPath = 'src/native/jme_bufferallocator'
String bufferAllocatorHeaders = 'src/native/headers'

//Pre-compiled libs directory
def rootPath = rootProject.projectDir.absolutePath
String bufferAllocatorPreCompiledLibsDir =
rootPath + File.separator + "build" + File.separator + 'native' + File.separator + 'android' + File.separator + 'allocator'

// directories for build
String bufferAllocatorBuildDir = "$buildDir" + File.separator + "bufferallocator"
String bufferAllocatorJniDir = bufferAllocatorBuildDir + File.separator + "jni"
String bufferAllocatorHeadersBuildDir = bufferAllocatorJniDir + File.separator + "headers"
String bufferAllocatorBuildLibsDir = bufferAllocatorBuildDir + File.separator + "libs"

// copy native src to build dir
task copyJmeBufferAllocator(type: Copy) {
from file(bufferAllocatorAndroidPath)
into file(bufferAllocatorJniDir)
}

// copy native headers to build dir
task copyJmeHeadersBufferAllocator(type: Copy, dependsOn: copyJmeBufferAllocator) {
from file(bufferAllocatorHeaders)
into file(bufferAllocatorHeadersBuildDir)
}

// compile and build copied natives in build dir
task buildBufferAllocatorNativeLib(type: Exec, dependsOn: [copyJmeBufferAllocator, copyJmeHeadersBufferAllocator]) {
workingDir bufferAllocatorBuildDir
executable rootProject.ndkCommandPath
args "-j" + Runtime.runtime.availableProcessors()
}

task updatePreCompiledLibsBufferAllocator(type: Copy, dependsOn: buildBufferAllocatorNativeLib) {
from file(bufferAllocatorBuildLibsDir)
into file(bufferAllocatorPreCompiledLibsDir)
}

// Copy pre-compiled libs to build directory (when not building new libs)
task copyPreCompiledLibsBufferAllocator(type: Copy) {
from file(bufferAllocatorPreCompiledLibsDir)
into file(bufferAllocatorBuildLibsDir)
}

// ndkExists is a boolean from the build.gradle in the root project
// buildNativeProjects is a string set to "true"
if (ndkExists && buildNativeProjects == "true") {
// build native libs and update stored pre-compiled libs to commit
compileJava.dependsOn { updatePreCompiledLibsBufferAllocator }
} else {
// use pre-compiled native libs (not building new ones)
compileJava.dependsOn { copyPreCompiledLibsBufferAllocator }
}

// package the native object files inside the lib folder in a production jar
jar.into("lib") { from bufferAllocatorBuildLibsDir }
1 change: 1 addition & 0 deletions jme3-android-native/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ apply from: file('openalsoft.gradle')
// apply from: file('stb_image.gradle')
// apply from: file('tremor.gradle')
apply from: file('decode.gradle')
apply from: file('bufferallocator.gradle')
50 changes: 50 additions & 0 deletions jme3-android-native/src/native/jme_bufferallocator/Android.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#
# Copyright (c) 2009-2022 jMonkeyEngine
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the name of 'jMonkeyEngine' nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

##
# Created by pavl_g on 5/17/22.
# For more : https://developer.android.com/ndk/guides/android_mk.
##
TARGET_PLATFORM := android-19

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_LDLIBS := -llog -Wl,-s

LOCAL_MODULE := bufferallocatorjme

LOCAL_C_INCLUDES := $(LOCAL_PATH)

LOCAL_SRC_FILES := com_jme3_util_AndroidNativeBufferAllocator.c

include $(BUILD_SHARED_LIBRARY)
39 changes: 39 additions & 0 deletions jme3-android-native/src/native/jme_bufferallocator/Application.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#
# Copyright (c) 2009-2022 jMonkeyEngine
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# * Neither the name of 'jMonkeyEngine' nor the names of its contributors
# may be used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

##
# Created by pavl_g on 5/17/22.
# For more : https://developer.android.com/ndk/guides/application_mk.
##
APP_PLATFORM := android-19
# change this to 'debug' to see android logs
APP_OPTIM := release
APP_ABI := all
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright (c) 2009-2022 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**
* @file com_jme3_util_AndroidNativeBufferAllocator.c
* @author pavl_g.
* @brief Creates and releases direct byte buffers for {com.jme3.util.AndroidNativeBufferAllocator}.
* @date 2022-05-17.
* @note
* Find more at :
* - JNI Direct byte buffers : https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#NewDirectByteBuffer.
* - JNI Get Direct byte buffer : https://docs.oracle.com/javase/8/docs/technotes/guides/jni/spec/functions.html#GetDirectBufferAddress.
* - GNU Basic allocation : https://www.gnu.org/software/libc/manual/html_node/Basic-Allocation.html.
* - GNU Allocating Cleared Space : https://www.gnu.org/software/libc/manual/html_node/Allocating-Cleared-Space.html.
* - GNU No Memory error : https://www.gnu.org/software/libc/manual/html_node/Error-Codes.html#index-ENOMEM.
* - GNU Freeing memory : https://www.gnu.org/software/libc/manual/html_node/Freeing-after-Malloc.html.
* - Android logging : https://developer.android.com/ndk/reference/group/logging.
* - Android logging example : https://github.com/android/ndk-samples/blob/7a8ff4c5529fce6ec4c5796efbe773f5d0e569cc/hello-libs/app/src/main/cpp/hello-libs.cpp#L25-L26.
*/

#include "headers/com_jme3_util_AndroidNativeBufferAllocator.h"
#include <stdlib.h>
#include <stdbool.h>
#include <errno.h>

#ifndef NDEBUG
#include <android/log.h>
#define LOG(LOG_ID, ...) __android_log_print(LOG_ID, \
"AndroidNativeBufferAllocator", ##__VA_ARGS__);
#else
#define LOG(...)
#endif

bool isDeviceOutOfMemory(void*);

/**
* @brief Tests if the device is out of memory.
*
* @return true if the buffer to allocate is a NULL pointer and the errno is ENOMEM (Error-no-memory).
* @return false otherwise.
*/
bool isDeviceOutOfMemory(void* buffer) {
return buffer == NULL && errno == ENOMEM;
}

JNIEXPORT void JNICALL Java_com_jme3_util_AndroidNativeBufferAllocator_releaseDirectByteBuffer
(JNIEnv * env, jobject object, jobject bufferObject)
{
void* buffer = (*env)->GetDirectBufferAddress(env, bufferObject);
// deallocates the buffer pointer
free(buffer);
// log the destruction by mem address
LOG(ANDROID_LOG_INFO, "Buffer released (mem_address, size) -> (%p, %lu)", buffer, sizeof(buffer));
// avoid accessing this memory space by resetting the memory address
buffer = NULL;
LOG(ANDROID_LOG_INFO, "Buffer mem_address formatted (mem_address, size) -> (%p, %u)", buffer, sizeof(buffer));
}

JNIEXPORT jobject JNICALL Java_com_jme3_util_AndroidNativeBufferAllocator_createDirectByteBuffer
(JNIEnv * env, jobject object, jlong size)
{
void* buffer = calloc(1, size);
if (isDeviceOutOfMemory(buffer)) {
LOG(ANDROID_LOG_FATAL, "Device is out of memory exiting with %u", errno);
exit(errno);
} else {
LOG(ANDROID_LOG_INFO, "Buffer created successfully (mem_address, size) -> (%p %lli)", buffer, size);
}
return (*env)->NewDirectByteBuffer(env, buffer, size);
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@
import com.jme3.renderer.android.AndroidGL;
import com.jme3.renderer.opengl.*;
import com.jme3.system.*;
import com.jme3.util.AndroidBufferAllocator;
import com.jme3.util.BufferAllocatorFactory;
import com.jme3.util.AndroidNativeBufferAllocator;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Logger;
Expand All @@ -82,7 +82,7 @@ public class OGLESContext implements JmeContext, GLSurfaceView.Renderer, SoftTex
final String implementation = BufferAllocatorFactory.PROPERTY_BUFFER_ALLOCATOR_IMPLEMENTATION;

if (System.getProperty(implementation) == null) {
System.setProperty(implementation, AndroidBufferAllocator.class.getName());
System.setProperty(implementation, AndroidNativeBufferAllocator.class.getName());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2009-2019 jMonkeyEngine
* Copyright (c) 2009-2022 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand Down Expand Up @@ -40,7 +40,9 @@

/**
* @author Jesus Oliver
* @deprecated implemented {@link AndroidNativeBufferAllocator} instead.
*/
@Deprecated
public class AndroidBufferAllocator implements BufferAllocator {
pavly-gerges marked this conversation as resolved.
Show resolved Hide resolved

// We make use of the ReflectionAllocator to remove the inner buffer
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright (c) 2009-2022 jMonkeyEngine
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'jMonkeyEngine' nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jme3.util;

import java.nio.Buffer;
import java.nio.ByteBuffer;

/**
* Allocates and destroys direct byte buffers using native code.
*
* @author pavl_g.
*/
public final class AndroidNativeBufferAllocator implements BufferAllocator {
pavly-gerges marked this conversation as resolved.
Show resolved Hide resolved

static {
System.loadLibrary("bufferallocatorjme");
}

@Override
public void destroyDirectBuffer(Buffer toBeDestroyed) {
releaseDirectByteBuffer(toBeDestroyed);
}

@Override
public ByteBuffer allocate(int size) {
return createDirectByteBuffer(size);
}

/**
* Releases the memory of a direct buffer using a buffer object reference.
*
* @param buffer the buffer reference to release its memory.
* @see AndroidNativeBufferAllocator#destroyDirectBuffer(Buffer)
*/
private native void releaseDirectByteBuffer(Buffer buffer);

/**
* Creates a new direct byte buffer explicitly with a specific size.
*
* @param size the byte buffer size used for allocating the buffer.
* @return a new direct byte buffer object.
* @see AndroidNativeBufferAllocator#allocate(int)
*/
private native ByteBuffer createDirectByteBuffer(long size);
}