diff --git a/app/src/main/cpp/winlator/gpu_image.c b/app/src/main/cpp/winlator/gpu_image.c index f0f3647..c24c54e 100644 --- a/app/src/main/cpp/winlator/gpu_image.c +++ b/app/src/main/cpp/winlator/gpu_image.c @@ -11,9 +11,15 @@ #include #include #include +#include +#include + +#include "native_handle.h" -#define printf(...) __android_log_print(ANDROID_LOG_DEBUG, "System.out", __VA_ARGS__); #define HAL_PIXEL_FORMAT_BGRA_8888 5 +#define println(...) __android_log_print(ANDROID_LOG_DEBUG, "System.out", __VA_ARGS__); + +extern const native_handle_t* _Nullable AHardwareBuffer_getNativeHandle(const AHardwareBuffer* _Nonnull buffer); EGLImageKHR createImageKHR(AHardwareBuffer* hardwareBuffer, int textureId) { const EGLint attribList[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; @@ -34,12 +40,12 @@ EGLImageKHR createImageKHR(AHardwareBuffer* hardwareBuffer, int textureId) { return imageKHR; } -AHardwareBuffer* createHardwareBuffer(int width, int height) { - AHardwareBuffer_Desc buffDesc = {}; +AHardwareBuffer* createHardwareBuffer(int width, int height, bool cpuAccess) { + AHardwareBuffer_Desc buffDesc = {0}; buffDesc.width = width; buffDesc.height = height; buffDesc.layers = 1; - buffDesc.usage = AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN; + buffDesc.usage = cpuAccess ? AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN : AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT; buffDesc.format = HAL_PIXEL_FORMAT_BGRA_8888; AHardwareBuffer *hardwareBuffer = NULL; @@ -50,8 +56,24 @@ AHardwareBuffer* createHardwareBuffer(int width, int height) { JNIEXPORT jlong JNICALL Java_com_winlator_renderer_GPUImage_createHardwareBuffer(JNIEnv *env, jclass obj, jshort width, - jshort height) { - return (jlong)createHardwareBuffer(width, height); + jshort height, jboolean cpuAccess) { + AHardwareBuffer* hardwareBuffer = createHardwareBuffer(width, height, cpuAccess); + if (hardwareBuffer) { + jclass cls = (*env)->GetObjectClass(env, obj); + + AHardwareBuffer_Desc buffDesc; + AHardwareBuffer_describe(hardwareBuffer, &buffDesc); + + jmethodID setStride = (*env)->GetMethodID(env, cls, "setStride", "(S)V"); + (*env)->CallVoidMethod(env, obj, setStride, (jshort)buffDesc.stride); + + const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(hardwareBuffer); + if (nativeHandle->numFds > 0) { + jmethodID setNativeHandle = (*env)->GetMethodID(env, cls, "setNativeHandle", "(I)V"); + (*env)->CallVoidMethod(env, obj, setNativeHandle, nativeHandle->data[0]); + } + } + return (jlong)hardwareBuffer; } JNIEXPORT jlong JNICALL @@ -62,10 +84,13 @@ Java_com_winlator_renderer_GPUImage_createImageKHR(JNIEnv *env, jclass obj, JNIEXPORT void JNICALL Java_com_winlator_renderer_GPUImage_destroyHardwareBuffer(JNIEnv *env, jclass obj, - jlong hardwareBufferPtr) { + jlong hardwareBufferPtr, jboolean locked) { AHardwareBuffer* hardwareBuffer = (AHardwareBuffer*)hardwareBufferPtr; if (hardwareBuffer) { - AHardwareBuffer_unlock(hardwareBuffer, NULL); + if (locked) { + AHardwareBuffer_unlock(hardwareBuffer, NULL); + locked = false; + } AHardwareBuffer_release(hardwareBuffer); } } @@ -80,10 +105,6 @@ Java_com_winlator_renderer_GPUImage_lockHardwareBuffer(JNIEnv *env, jclass obj, AHardwareBuffer_Desc buffDesc; AHardwareBuffer_describe(hardwareBuffer, &buffDesc); - jclass cls = (*env)->GetObjectClass(env, obj); - jmethodID setStride = (*env)->GetMethodID(env, cls, "setStride", "(S)V"); - (*env)->CallVoidMethod(env, obj, setStride, (jshort)buffDesc.stride); - jlong size = buffDesc.stride * buffDesc.height * 4; return (*env)->NewDirectByteBuffer(env, virtualAddr, size); } diff --git a/app/src/main/java/com/winlator/renderer/GPUImage.java b/app/src/main/java/com/winlator/renderer/GPUImage.java index 2573297..f799067 100644 --- a/app/src/main/java/com/winlator/renderer/GPUImage.java +++ b/app/src/main/java/com/winlator/renderer/GPUImage.java @@ -11,6 +11,8 @@ public class GPUImage extends Texture { private long imageKHRPtr; private ByteBuffer virtualData; private short stride; + private boolean locked = false; + private int nativeHandle; private static boolean supported = false; static { @@ -18,8 +20,15 @@ public class GPUImage extends Texture { } public GPUImage(short width, short height) { - hardwareBufferPtr = createHardwareBuffer(width, height); - if (hardwareBufferPtr != 0) virtualData = lockHardwareBuffer(hardwareBufferPtr); + this(width, height, true); + } + + public GPUImage(short width, short height, boolean cpuAccess) { + hardwareBufferPtr = createHardwareBuffer(width, height, cpuAccess); + if (cpuAccess && hardwareBufferPtr != 0) { + virtualData = lockHardwareBuffer(hardwareBufferPtr); + locked = true; + } } @Override @@ -44,6 +53,15 @@ public class GPUImage extends Texture { this.stride = stride; } + public int getNativeHandle() { + return nativeHandle; + } + + @Keep + private void setNativeHandle(int nativeHandle) { + this.nativeHandle = nativeHandle; + } + public ByteBuffer getVirtualData() { return virtualData; } @@ -51,7 +69,7 @@ public class GPUImage extends Texture { @Override public void destroy() { destroyImageKHR(imageKHRPtr); - destroyHardwareBuffer(hardwareBufferPtr); + destroyHardwareBuffer(hardwareBufferPtr, locked); virtualData = null; imageKHRPtr = 0; hardwareBufferPtr = 0; @@ -62,6 +80,10 @@ public class GPUImage extends Texture { return supported; } + public long getHardwareBufferPtr() { + return hardwareBufferPtr; + } + public static void checkIsSupported() { final short size = 8; GPUImage gpuImage = new GPUImage(size, size); @@ -70,9 +92,9 @@ public class GPUImage extends Texture { gpuImage.destroy(); } - private native long createHardwareBuffer(short width, short height); + private native long createHardwareBuffer(short width, short height, boolean cpuAccess); - private native void destroyHardwareBuffer(long hardwareBufferPtr); + private native void destroyHardwareBuffer(long hardwareBufferPtr, boolean locked); private native ByteBuffer lockHardwareBuffer(long hardwareBufferPtr);