diff --git a/android/filament-android/CMakeLists.txt b/android/filament-android/CMakeLists.txt index fafef186b6..dee525447b 100644 --- a/android/filament-android/CMakeLists.txt +++ b/android/filament-android/CMakeLists.txt @@ -63,6 +63,7 @@ add_library(filament-jni SHARED src/main/cpp/MathUtils.cpp src/main/cpp/RenderableManager.cpp src/main/cpp/Renderer.cpp + src/main/cpp/RenderTarget.cpp src/main/cpp/Scene.cpp src/main/cpp/SkyBox.cpp src/main/cpp/Stream.cpp diff --git a/android/filament-android/src/main/cpp/Engine.cpp b/android/filament-android/src/main/cpp/Engine.cpp index a895e989f0..59041ee97e 100644 --- a/android/filament-android/src/main/cpp/Engine.cpp +++ b/android/filament-android/src/main/cpp/Engine.cpp @@ -236,6 +236,14 @@ Java_com_google_android_filament_Engine_nDestroyTexture(JNIEnv*, jclass, engine->destroy(texture); } +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_Engine_nDestroyRenderTarget(JNIEnv*, jclass, + jlong nativeEngine, jlong nativeTarget) { + Engine* engine = (Engine*) nativeEngine; + RenderTarget* target = (RenderTarget*) nativeTarget; + engine->destroy(target); +} + extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nDestroyEntity(JNIEnv*, jclass, jlong nativeEngine, jint entity_) { diff --git a/android/filament-android/src/main/cpp/RenderTarget.cpp b/android/filament-android/src/main/cpp/RenderTarget.cpp new file mode 100644 index 0000000000..63d0f700ee --- /dev/null +++ b/android/filament-android/src/main/cpp/RenderTarget.cpp @@ -0,0 +1,86 @@ +/* + * 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. + */ + +#include + +#include +#include +#include + +#include + +#include "CallbackUtils.h" +#include "NioUtils.h" + +using namespace filament; +using namespace backend; + +extern "C" JNIEXPORT jlong JNICALL +Java_com_google_android_filament_RenderTarget_nCreateBuilder(JNIEnv *env, jclass type) { + return (jlong) new RenderTarget::Builder(); +} + +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_RenderTarget_nDestroyBuilder(JNIEnv *env, jclass type, + jlong nativeBuilder) { + RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder; + delete builder; +} + +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_RenderTarget_nBuilderTexture(JNIEnv *env, jclass type, + jlong nativeBuilder, jlong attachment, jlong nativeTexture) { + RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder; + Texture* texture = (Texture*) nativeTexture; + builder->texture(RenderTarget::AttachmentPoint(attachment), texture); +} + +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_RenderTarget_nBuilderMipLevel(JNIEnv *env, jclass type, + jlong nativeBuilder, jlong attachment, jint level) { + RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder; + builder->mipLevel(RenderTarget::AttachmentPoint(attachment), level); +} + +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_RenderTarget_nBuilderFace(JNIEnv *env, jclass type, + jlong nativeBuilder, jlong attachment, jint face) { + RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder; + RenderTarget::CubemapFace cubeface = (RenderTarget::CubemapFace) face; + builder->face(RenderTarget::AttachmentPoint(attachment), cubeface); +} + +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_RenderTarget_nBuilderLayer(JNIEnv *env, jclass type, + jlong nativeBuilder, jlong attachment, jint layer) { + RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder; + builder->layer(RenderTarget::AttachmentPoint(attachment), layer); +} + +extern "C" JNIEXPORT jlong JNICALL +Java_com_google_android_filament_RenderTarget_nBuilderBuild(JNIEnv *env, jclass type, + jlong nativeBuilder, jlong nativeEngine) { + RenderTarget::Builder* builder = (RenderTarget::Builder*) nativeBuilder; + Engine *engine = (Engine *) nativeEngine; + return (jlong) builder->build(*engine); +} + +extern "C" JNIEXPORT jint JNICALL +Java_com_google_android_filament_RenderTarget_nGetMipLevel(JNIEnv *env, jclass type, + jlong nativeTarget, jlong attachment) { + RenderTarget* target = (RenderTarget*) nativeTarget; + return (jint) target->getMipLevel(RenderTarget::AttachmentPoint(attachment)); +} diff --git a/android/filament-android/src/main/cpp/View.cpp b/android/filament-android/src/main/cpp/View.cpp index 51a750ded6..58b2a643c6 100644 --- a/android/filament-android/src/main/cpp/View.cpp +++ b/android/filament-android/src/main/cpp/View.cpp @@ -94,6 +94,13 @@ Java_com_google_android_filament_View_nSetShadowsEnabled(JNIEnv*, jclass, view->setShadowsEnabled(enabled); } +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_View_nSetRenderTarget(JNIEnv*, jclass, + jlong nativeView, jlong nativeTarget) { + View* view = (View*) nativeView; + view->setRenderTarget((RenderTarget*) nativeTarget); +} + extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_View_nSetSampleCount(JNIEnv*, jclass, jlong nativeView, jint count) { diff --git a/android/filament-android/src/main/java/com/google/android/filament/Engine.java b/android/filament-android/src/main/java/com/google/android/filament/Engine.java index aa4329a52e..3cddcb5487 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/Engine.java +++ b/android/filament-android/src/main/java/com/google/android/filament/Engine.java @@ -247,6 +247,11 @@ public class Engine { texture.clearNativeObject(); } + public void destroyRenderTarget(@NonNull RenderTarget target) { + nDestroyRenderTarget(getNativeObject(), target.getNativeObject()); + target.clearNativeObject(); + } + public void destroyEntity(@Entity int entity) { nDestroyEntity(getNativeObject(), entity); } @@ -309,6 +314,7 @@ public class Engine { private static native void nDestroyMaterialInstance(long nativeEngine, long nativeMaterialInstance); private static native void nDestroySkybox(long nativeEngine, long nativeSkybox); private static native void nDestroyTexture(long nativeEngine, long nativeTexture); + private static native void nDestroyRenderTarget(long nativeEngine, long nativeTarget); private static native void nDestroyEntity(long nativeEngine, int entity); private static native long nGetTransformManager(long nativeEngine); private static native long nGetLightManager(long nativeEngine); diff --git a/android/filament-android/src/main/java/com/google/android/filament/RenderTarget.java b/android/filament-android/src/main/java/com/google/android/filament/RenderTarget.java new file mode 100644 index 0000000000..1785bbf4cf --- /dev/null +++ b/android/filament-android/src/main/java/com/google/android/filament/RenderTarget.java @@ -0,0 +1,145 @@ +/* + * 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.support.annotation.IntRange; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import java.nio.Buffer; +import java.nio.BufferOverflowException; + +public class RenderTarget { + private long mNativeObject; + private final Texture[] mTextures = new Texture[2]; + + private RenderTarget(long nativeRenderTarget, Builder builder) { + mNativeObject = nativeRenderTarget; + mTextures[0] = builder.mTextures[0]; + mTextures[1] = builder.mTextures[1]; + } + + long getNativeObject() { + if (mNativeObject == 0) { + throw new IllegalStateException("Calling method on destroyed RenderTarget"); + } + return mNativeObject; + } + + public enum AttachmentPoint { + COLOR, + DEPTH, + } + + public static class Builder { + @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) + private final BuilderFinalizer mFinalizer; + private final long mNativeBuilder; + private final Texture[] mTextures = new Texture[2]; + + public Builder() { + mNativeBuilder = nCreateBuilder(); + mFinalizer = new BuilderFinalizer(mNativeBuilder); + } + + @NonNull + public Builder texture(@NonNull AttachmentPoint attachment, @Nullable Texture texture) { + mTextures[attachment.ordinal()] = texture; + nBuilderTexture(mNativeBuilder, attachment.ordinal(), texture != null ? texture.getNativeObject() : 0); + return this; + } + + @NonNull + public Builder mipLevel(@NonNull AttachmentPoint attachment, @IntRange(from = 0) int level) { + nBuilderMipLevel(mNativeBuilder, attachment.ordinal(), level); + return this; + } + + @NonNull + public Builder face(@NonNull AttachmentPoint attachment, Texture.CubemapFace face) { + nBuilderFace(mNativeBuilder, attachment.ordinal(), face.ordinal()); + return this; + } + + @NonNull + public Builder layer(@NonNull AttachmentPoint attachment, @IntRange(from = 0) int layer) { + nBuilderLayer(mNativeBuilder, attachment.ordinal(), layer); + return this; + } + + @NonNull + public RenderTarget build(@NonNull Engine engine) { + long nativeRenderTarget = nBuilderBuild(mNativeBuilder, engine.getNativeObject()); + if (nativeRenderTarget == 0) + throw new IllegalStateException("Couldn't create RenderTarget"); + return new RenderTarget(nativeRenderTarget, this); + } + + private static class BuilderFinalizer { + private final long mNativeObject; + + BuilderFinalizer(long nativeObject) { + mNativeObject = nativeObject; + } + + @Override + public void finalize() { + try { + super.finalize(); + } catch (Throwable t) { // Ignore + } finally { + nDestroyBuilder(mNativeObject); + } + } + } + } + + @Nullable + public Texture getTexture(@NonNull AttachmentPoint attachment) { + return mTextures[attachment.ordinal()]; + } + + @IntRange(from = 0) + public int getMipLevel(@NonNull AttachmentPoint attachment) { + return nGetMipLevel(getNativeObject(), attachment.ordinal()); + } + + public Texture.CubemapFace getFace(AttachmentPoint attachment) { + return Texture.CubemapFace.values()[nGetFace(getNativeObject(), attachment.ordinal())]; + } + + @IntRange(from = 0) + public int getLayer(@NonNull AttachmentPoint attachment) { + return nGetLayer(getNativeObject(), attachment.ordinal()); + } + + void clearNativeObject() { + mNativeObject = 0; + } + + private static native long nCreateBuilder(); + private static native long nDestroyBuilder(long nativeBuilder); + private static native long nBuilderTexture(long nativeBuilder, int attachment, long nativeTexture); + private static native long nBuilderMipLevel(long nativeBuilder, int attachment, int level); + private static native long nBuilderFace(long nativeBuilder, int attachment, int face); + private static native long nBuilderLayer(long nativeBuilder, int attachment, int layer); + private static native long nBuilderBuild(long nativeBuilder, long nativeEngine); + + private static native int nGetMipLevel(long nativeRenderTarget, int attachment); + private static native int nGetFace(long nativeRenderTarget, int attachment); + private static native int nGetLayer(long nativeRenderTarget, int attachment); +} diff --git a/android/filament-android/src/main/java/com/google/android/filament/View.java b/android/filament-android/src/main/java/com/google/android/filament/View.java index b949c5ba0b..4318a895a1 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/View.java +++ b/android/filament-android/src/main/java/com/google/android/filament/View.java @@ -166,6 +166,10 @@ public class View { nSetShadowsEnabled(getNativeObject(), enabled); } + public void setRenderTarget(@Nullable RenderTarget target) { + nSetRenderTarget(getNativeObject(), target != null ? target.getNativeObject() : 0); + } + public void setSampleCount(int count) { nSetSampleCount(getNativeObject(), count); } @@ -316,6 +320,7 @@ public class View { private static native void nSetClearTargets(long nativeView, boolean color, boolean depth, boolean stencil); private static native void nSetVisibleLayers(long nativeView, int select, int value); private static native void nSetShadowsEnabled(long nativeView, boolean enabled); + private static native void nSetRenderTarget(long nativeView, long nativeRenderTarget); private static native void nSetSampleCount(long nativeView, int count); private static native int nGetSampleCount(long nativeView); private static native void nSetAntiAliasing(long nativeView, int type); diff --git a/java/filament/CMakeLists.txt b/java/filament/CMakeLists.txt index 00c61f05d0..51d9ea64aa 100644 --- a/java/filament/CMakeLists.txt +++ b/java/filament/CMakeLists.txt @@ -52,6 +52,7 @@ set(JNI_SOURCE_FILES ${FILAMENT_DIR}/src/main/cpp/NativeSurface.cpp ${FILAMENT_DIR}/src/main/cpp/RenderableManager.cpp ${FILAMENT_DIR}/src/main/cpp/Renderer.cpp + ${FILAMENT_DIR}/src/main/cpp/RenderTarget.cpp ${FILAMENT_DIR}/src/main/cpp/Scene.cpp ${FILAMENT_DIR}/src/main/cpp/SkyBox.cpp ${FILAMENT_DIR}/src/main/cpp/Stream.cpp @@ -127,6 +128,7 @@ set(JAVA_SOURCE_FILES ${FILAMENT_JAVA_DIR}/com/google/android/filament/Platform.java ${FILAMENT_JAVA_DIR}/com/google/android/filament/RenderableManager.java ${FILAMENT_JAVA_DIR}/com/google/android/filament/Renderer.java + ${FILAMENT_JAVA_DIR}/com/google/android/filament/RenderTarget.java ${FILAMENT_JAVA_DIR}/com/google/android/filament/Scene.java ${FILAMENT_JAVA_DIR}/com/google/android/filament/Skybox.java ${FILAMENT_JAVA_DIR}/com/google/android/filament/Stream.java