diff --git a/android/common/CallbackUtils.cpp b/android/common/CallbackUtils.cpp index 2ef64e144e..d9a5151990 100644 --- a/android/common/CallbackUtils.cpp +++ b/android/common/CallbackUtils.cpp @@ -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(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(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(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; } diff --git a/android/common/CallbackUtils.h b/android/common/CallbackUtils.h index 6a631efe5c..93e3c7ec0f 100644 --- a/android/common/CallbackUtils.h +++ b/android/common/CallbackUtils.h @@ -18,9 +18,10 @@ #include -#include "common/CallbackUtils.h" #include "common/NioUtils.h" +#include + #include struct CallbackJni { @@ -35,60 +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); - - jobject getCallbackObject() { return mCallback; } - JNIEnv* getJniEnv() { return mEnv; } - -private: - JniCallback(JNIEnv* env, jobject handler, jobject runnable); - JniCallback(JniCallback const &) = delete; - JniCallback(JniCallback&&) = delete; - ~JniCallback(); - - JNIEnv* mEnv; - jobject mHandler; - jobject mCallback; - CallbackJni mCallbackUtils; }; diff --git a/android/common/NioUtils.h b/android/common/NioUtils.h index 94e43d92e3..72f4656ea9 100644 --- a/android/common/NioUtils.h +++ b/android/common/NioUtils.h @@ -38,6 +38,10 @@ public: AutoBuffer(AutoBuffer&& rhs) noexcept; ~AutoBuffer() noexcept; + void attachToJniThread(JNIEnv* env) noexcept { + mEnv = env; + } + void* getData() const noexcept { return mUserData; } diff --git a/android/filament-android/CMakeLists.txt b/android/filament-android/CMakeLists.txt index cdf4c7511d..df4ea3cbdc 100644 --- a/android/filament-android/CMakeLists.txt +++ b/android/filament-android/CMakeLists.txt @@ -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) diff --git a/android/filament-android/src/main/cpp/BufferObject.cpp b/android/filament-android/src/main/cpp/BufferObject.cpp index e86d81bd5c..cdb4c39694 100644 --- a/android/filament-android/src/main/cpp/BufferObject.cpp +++ b/android/filament-android/src/main/cpp/BufferObject.cpp @@ -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); diff --git a/android/filament-android/src/main/cpp/IndexBuffer.cpp b/android/filament-android/src/main/cpp/IndexBuffer.cpp index 86515e7485..f88f95fd6a 100644 --- a/android/filament-android/src/main/cpp/IndexBuffer.cpp +++ b/android/filament-android/src/main/cpp/IndexBuffer.cpp @@ -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); diff --git a/android/filament-android/src/main/cpp/Renderer.cpp b/android/filament-android/src/main/cpp/Renderer.cpp index f20b7a0bcf..fb9f5034f4 100644 --- a/android/filament-android/src/main/cpp/Renderer.cpp +++ b/android/filament-android/src/main/cpp/Renderer.cpp @@ -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), diff --git a/android/filament-android/src/main/cpp/Stream.cpp b/android/filament-android/src/main/cpp/Stream.cpp index b7955f54d5..e84767d676 100644 --- a/android/filament-android/src/main/cpp/Stream.cpp +++ b/android/filament-android/src/main/cpp/Stream.cpp @@ -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); } diff --git a/android/filament-android/src/main/cpp/SwapChain.cpp b/android/filament-android/src/main/cpp/SwapChain.cpp index 5528c00411..0ddc85f12f 100644 --- a/android/filament-android/src/main/cpp/SwapChain.cpp +++ b/android/filament-android/src/main/cpp/SwapChain.cpp @@ -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); } diff --git a/android/filament-android/src/main/cpp/Texture.cpp b/android/filament-android/src/main/cpp/Texture.cpp index 5a63833da1..b4384eef56 100644 --- a/android/filament-android/src/main/cpp/Texture.cpp +++ b/android/filament-android/src/main/cpp/Texture.cpp @@ -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; }; diff --git a/android/filament-android/src/main/cpp/VertexBuffer.cpp b/android/filament-android/src/main/cpp/VertexBuffer.cpp index 8bc1e99e55..d5b3fc326d 100644 --- a/android/filament-android/src/main/cpp/VertexBuffer.cpp +++ b/android/filament-android/src/main/cpp/VertexBuffer.cpp @@ -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; diff --git a/android/filament-android/src/main/cpp/View.cpp b/android/filament-android/src/main/cpp/View.cpp index 5361c56fe7..686867f5eb 100644 --- a/android/filament-android/src/main/cpp/View.cpp +++ b/android/filament-android/src/main/cpp/View.cpp @@ -22,6 +22,8 @@ #include "common/CallbackUtils.h" +#include "private/backend/VirtualMachineEnv.h" + using namespace filament; extern "C" JNIEXPORT void JNICALL @@ -387,7 +389,7 @@ Java_com_google_android_filament_View_nIsScreenSpaceRefractionEnabled(JNIEnv *, extern "C" JNIEXPORT void JNICALL -Java_com_google_android_filament_View_nPick(JNIEnv* env, jclass clazz, +Java_com_google_android_filament_View_nPick(JNIEnv* env, jclass, jlong nativeView, jint x, jint y, jobject handler, jobject internalCallback) { @@ -412,13 +414,14 @@ Java_com_google_android_filament_View_nPick(JNIEnv* env, jclass clazz, 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* const env = callback->getJniEnv(); + 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::invoke(callback); // this destroys JniCallback - }); + JniCallback::postToJavaAndDestroy(callback); + }, callback->getHandler()); } diff --git a/android/filament-utils-android/CMakeLists.txt b/android/filament-utils-android/CMakeLists.txt index 267e1aa29c..c5c214e216 100644 --- a/android/filament-utils-android/CMakeLists.txt +++ b/android/filament-utils-android/CMakeLists.txt @@ -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) diff --git a/android/gltfio-android/CMakeLists.txt b/android/gltfio-android/CMakeLists.txt index d52989cac3..916ff0226a 100644 --- a/android/gltfio-android/CMakeLists.txt +++ b/android/gltfio-android/CMakeLists.txt @@ -76,6 +76,7 @@ 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 diff --git a/filament/backend/CMakeLists.txt b/filament/backend/CMakeLists.txt index a8defa495d..ba9070805c 100644 --- a/filament/backend/CMakeLists.txt +++ b/filament/backend/CMakeLists.txt @@ -81,10 +81,14 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMEN if (EGL) list(APPEND SRCS src/opengl/PlatformEGL.cpp) endif() + if (ANDROID) + # 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/android/ExternalStreamManagerAndroid.cpp) list(APPEND SRCS src/android/ExternalTextureManagerAndroid.cpp) - list(APPEND SRCS src/android/VirtualMachineEnv.cpp) list(APPEND SRCS src/opengl/PlatformEGLAndroid.cpp) elseif (IOS) list(APPEND SRCS src/opengl/PlatformCocoaTouchGL.mm) diff --git a/filament/backend/include/backend/CallbackHandler.h b/filament/backend/include/backend/CallbackHandler.h index e2ce6a6ea1..dee3aaa251 100644 --- a/filament/backend/include/backend/CallbackHandler.h +++ b/filament/backend/include/backend/CallbackHandler.h @@ -36,6 +36,22 @@ namespace filament::backend { * * 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: @@ -44,6 +60,8 @@ public: /** * 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; diff --git a/filament/backend/src/android/VirtualMachineEnv.h b/filament/backend/include/private/backend/VirtualMachineEnv.h similarity index 100% rename from filament/backend/src/android/VirtualMachineEnv.h rename to filament/backend/include/private/backend/VirtualMachineEnv.h diff --git a/filament/backend/src/android/VirtualMachineEnv.cpp b/filament/backend/src/VirtualMachineEnv.cpp similarity index 97% rename from filament/backend/src/android/VirtualMachineEnv.cpp rename to filament/backend/src/VirtualMachineEnv.cpp index 1122e69d61..9ea660dea7 100644 --- a/filament/backend/src/android/VirtualMachineEnv.cpp +++ b/filament/backend/src/VirtualMachineEnv.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "VirtualMachineEnv.h" +#include "private/backend/VirtualMachineEnv.h" #include diff --git a/filament/backend/src/android/ExternalStreamManagerAndroid.h b/filament/backend/src/android/ExternalStreamManagerAndroid.h index 323fc8f9be..addf4b7a0f 100644 --- a/filament/backend/src/android/ExternalStreamManagerAndroid.h +++ b/filament/backend/src/android/ExternalStreamManagerAndroid.h @@ -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 diff --git a/filament/backend/src/android/ExternalTextureManagerAndroid.h b/filament/backend/src/android/ExternalTextureManagerAndroid.h index 9b7efc4dbb..faa04b9efb 100644 --- a/filament/backend/src/android/ExternalTextureManagerAndroid.h +++ b/filament/backend/src/android/ExternalTextureManagerAndroid.h @@ -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 #include diff --git a/filament/backend/src/opengl/PlatformEGLAndroid.cpp b/filament/backend/src/opengl/PlatformEGLAndroid.cpp index 2d0a5ca80b..28ba47a477 100644 --- a/filament/backend/src/opengl/PlatformEGLAndroid.cpp +++ b/filament/backend/src/opengl/PlatformEGLAndroid.cpp @@ -21,7 +21,7 @@ #include "android/ExternalTextureManagerAndroid.h" #include "android/ExternalStreamManagerAndroid.h" -#include "android/VirtualMachineEnv.h" +#include "private/backend/VirtualMachineEnv.h" #include @@ -236,7 +236,7 @@ AcquiredImage PlatformEGLAndroid::transformAcquiredImage(AcquiredImage source) n return { eglImage, patchedCallback, closure, source.handler }; } -// This must called when the library is loaded. We need this to get a reference to the global VM +// This must be 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); }