blob: cb937a36ed9b2c39090b24a6214bbc13fe07cae8 [file] [log] [blame]
#include "NIOBuffer.h"
#include "GraphicsJNI.h"
// enable this to dump each time we ref/unref a global java object (buffer)
//
//#define TRACE_GLOBAL_REFS
//#define TRACE_ARRAY_LOCKS
static jclass gNIOAccess_classID;
static jmethodID gNIOAccess_getBasePointer;
static jmethodID gNIOAccess_getBaseArray;
static jmethodID gNIOAccess_getBaseArrayOffset;
static jmethodID gNIOAccess_getRemainingBytes;
void NIOBuffer::RegisterJNI(JNIEnv* env) {
if (0 != gNIOAccess_classID) {
return; // already called
}
jclass c = env->FindClass("java/nio/NIOAccess");
gNIOAccess_classID = (jclass)env->NewGlobalRef(c);
gNIOAccess_getBasePointer = env->GetStaticMethodID(gNIOAccess_classID,
"getBasePointer", "(Ljava/nio/Buffer;)J");
gNIOAccess_getBaseArray = env->GetStaticMethodID(gNIOAccess_classID,
"getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
gNIOAccess_getBaseArrayOffset = env->GetStaticMethodID(gNIOAccess_classID,
"getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
gNIOAccess_getRemainingBytes = env->GetStaticMethodID(gNIOAccess_classID,
"getRemainingBytes", "(Ljava/nio/Buffer;)I");
}
///////////////////////////////////////////////////////////////////////////////
#ifdef TRACE_GLOBAL_REFS
static int gGlobalRefs;
#endif
#ifdef TRACE_ARRAY_LOCKS
static int gLockCount;
#endif
NIOBuffer::NIOBuffer(JNIEnv* env, jobject buffer) {
fBuffer = env->NewGlobalRef(buffer);
#ifdef TRACE_GLOBAL_REFS
SkDebugf("------------ newglobalref bbuffer %X %d\n", buffer, gGlobalRefs++);
#endif
fLockedPtr = NULL;
fLockedArray = NULL;
}
NIOBuffer::~NIOBuffer() {
// free() needs to have already been called
if (NULL != fBuffer) {
SkDebugf("----- leaked fBuffer in NIOBuffer");
sk_throw();
}
}
void NIOBuffer::free(JNIEnv* env) {
if (NULL != fLockedPtr) {
SkDebugf("======= free: array still locked %x %p\n", fLockedArray, fLockedPtr);
}
if (NULL != fBuffer) {
#ifdef TRACE_GLOBAL_REFS
SkDebugf("----------- deleteglobalref buffer %X %d\n", fBuffer, --gGlobalRefs);
#endif
env->DeleteGlobalRef(fBuffer);
fBuffer = NULL;
}
}
void* NIOBuffer::lock(JNIEnv* env, int* remaining) {
if (NULL != fLockedPtr) {
SkDebugf("======= lock: array still locked %x %p\n", fLockedArray, fLockedPtr);
}
fLockedPtr = NULL;
fLockedArray = NULL;
if (NULL != remaining) {
*remaining = env->CallStaticIntMethod(gNIOAccess_classID,
gNIOAccess_getRemainingBytes,
fBuffer);
if (GraphicsJNI::hasException(env)) {
return NULL;
}
}
jlong pointer = env->CallStaticLongMethod(gNIOAccess_classID,
gNIOAccess_getBasePointer,
fBuffer);
if (GraphicsJNI::hasException(env)) {
return NULL;
}
if (0 != pointer) {
return reinterpret_cast<void*>(pointer);
}
fLockedArray = (jbyteArray)env->CallStaticObjectMethod(gNIOAccess_classID,
gNIOAccess_getBaseArray,
fBuffer);
if (GraphicsJNI::hasException(env) || NULL == fLockedArray) {
return NULL;
}
jint offset = env->CallStaticIntMethod(gNIOAccess_classID,
gNIOAccess_getBaseArrayOffset,
fBuffer);
fLockedPtr = env->GetByteArrayElements(fLockedArray, NULL);
if (GraphicsJNI::hasException(env)) {
SkDebugf("------------ failed to lockarray %x\n", fLockedArray);
return NULL;
}
#ifdef TRACE_ARRAY_LOCKS
SkDebugf("------------ lockarray %x %p %d\n",
fLockedArray, fLockedPtr, gLockCount++);
#endif
if (NULL == fLockedPtr) {
offset = 0;
}
return (char*)fLockedPtr + offset;
}
void NIOBuffer::unlock(JNIEnv* env, bool dataChanged) {
if (NULL != fLockedPtr) {
#ifdef TRACE_ARRAY_LOCKS
SkDebugf("------------ unlockarray %x %p %d\n",
fLockedArray, fLockedPtr, --gLockCount);
#endif
env->ReleaseByteArrayElements(fLockedArray, (jbyte*)fLockedPtr,
dataChanged ? 0 : JNI_ABORT);
fLockedPtr = NULL;
fLockedArray = NULL;
} else {
SkDebugf("============= unlock called with null ptr %x\n", fLockedArray);
}
}