Home | History | Annotate | Download | only in graphics
      1 #include "NIOBuffer.h"
      2 #include "GraphicsJNI.h"
      3 
      4 // enable this to dump each time we ref/unref a global java object (buffer)
      5 //
      6 //#define TRACE_GLOBAL_REFS
      7 
      8 //#define TRACE_ARRAY_LOCKS
      9 
     10 static jclass gNIOAccess_classID;
     11 static jmethodID gNIOAccess_getBasePointer;
     12 static jmethodID gNIOAccess_getBaseArray;
     13 static jmethodID gNIOAccess_getBaseArrayOffset;
     14 static jmethodID gNIOAccess_getRemainingBytes;
     15 
     16 void NIOBuffer::RegisterJNI(JNIEnv* env) {
     17     if (0 != gNIOAccess_classID) {
     18         return; // already called
     19     }
     20 
     21     jclass c = env->FindClass("java/nio/NIOAccess");
     22     gNIOAccess_classID = (jclass)env->NewGlobalRef(c);
     23 
     24     gNIOAccess_getBasePointer = env->GetStaticMethodID(gNIOAccess_classID,
     25                                     "getBasePointer", "(Ljava/nio/Buffer;)J");
     26     gNIOAccess_getBaseArray = env->GetStaticMethodID(gNIOAccess_classID,
     27                     "getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
     28     gNIOAccess_getBaseArrayOffset = env->GetStaticMethodID(gNIOAccess_classID,
     29                                 "getBaseArrayOffset", "(Ljava/nio/Buffer;)I");
     30     gNIOAccess_getRemainingBytes = env->GetStaticMethodID(gNIOAccess_classID,
     31                                 "getRemainingBytes", "(Ljava/nio/Buffer;)I");
     32 }
     33 
     34 ///////////////////////////////////////////////////////////////////////////////
     35 
     36 #ifdef TRACE_GLOBAL_REFS
     37     static int gGlobalRefs;
     38 #endif
     39 
     40 #ifdef TRACE_ARRAY_LOCKS
     41     static int gLockCount;
     42 #endif
     43 
     44 NIOBuffer::NIOBuffer(JNIEnv* env, jobject buffer) {
     45     fBuffer = env->NewGlobalRef(buffer);
     46 #ifdef TRACE_GLOBAL_REFS
     47     SkDebugf("------------ newglobalref bbuffer %X %d\n", buffer, gGlobalRefs++);
     48 #endif
     49     fLockedPtr = NULL;
     50     fLockedArray = NULL;
     51 }
     52 
     53 NIOBuffer::~NIOBuffer() {
     54     // free() needs to have already been called
     55     if (NULL != fBuffer) {
     56         SkDebugf("----- leaked fBuffer in NIOBuffer");
     57         sk_throw();
     58     }
     59 }
     60 
     61 void NIOBuffer::free(JNIEnv* env) {
     62 
     63     if (NULL != fLockedPtr) {
     64         SkDebugf("======= free: array still locked %x %p\n", fLockedArray, fLockedPtr);
     65     }
     66 
     67 
     68     if (NULL != fBuffer) {
     69 #ifdef TRACE_GLOBAL_REFS
     70         SkDebugf("----------- deleteglobalref buffer %X %d\n", fBuffer, --gGlobalRefs);
     71 #endif
     72         env->DeleteGlobalRef(fBuffer);
     73         fBuffer = NULL;
     74     }
     75 }
     76 
     77 void* NIOBuffer::lock(JNIEnv* env, int* remaining) {
     78     if (NULL != fLockedPtr) {
     79         SkDebugf("======= lock: array still locked %x %p\n", fLockedArray, fLockedPtr);
     80     }
     81 
     82     fLockedPtr = NULL;
     83     fLockedArray = NULL;
     84 
     85     if (NULL != remaining) {
     86         *remaining = env->CallStaticIntMethod(gNIOAccess_classID,
     87                                               gNIOAccess_getRemainingBytes,
     88                                               fBuffer);
     89         if (GraphicsJNI::hasException(env)) {
     90             return NULL;
     91         }
     92     }
     93 
     94     jlong pointer = env->CallStaticLongMethod(gNIOAccess_classID,
     95                                               gNIOAccess_getBasePointer,
     96                                               fBuffer);
     97     if (GraphicsJNI::hasException(env)) {
     98         return NULL;
     99     }
    100     if (0 != pointer) {
    101         return reinterpret_cast<void*>(pointer);
    102     }
    103 
    104     fLockedArray = (jbyteArray)env->CallStaticObjectMethod(gNIOAccess_classID,
    105                                                         gNIOAccess_getBaseArray,
    106                                                         fBuffer);
    107     if (GraphicsJNI::hasException(env) || NULL == fLockedArray) {
    108         return NULL;
    109     }
    110     jint offset = env->CallStaticIntMethod(gNIOAccess_classID,
    111                                            gNIOAccess_getBaseArrayOffset,
    112                                            fBuffer);
    113     fLockedPtr = env->GetByteArrayElements(fLockedArray, NULL);
    114     if (GraphicsJNI::hasException(env)) {
    115         SkDebugf("------------ failed to lockarray %x\n", fLockedArray);
    116         return NULL;
    117     }
    118 #ifdef TRACE_ARRAY_LOCKS
    119     SkDebugf("------------ lockarray %x %p %d\n",
    120              fLockedArray, fLockedPtr, gLockCount++);
    121 #endif
    122     if (NULL == fLockedPtr) {
    123         offset = 0;
    124     }
    125     return (char*)fLockedPtr + offset;
    126 }
    127 
    128 void NIOBuffer::unlock(JNIEnv* env, bool dataChanged) {
    129     if (NULL != fLockedPtr) {
    130 #ifdef TRACE_ARRAY_LOCKS
    131         SkDebugf("------------ unlockarray %x %p %d\n",
    132                  fLockedArray, fLockedPtr, --gLockCount);
    133 #endif
    134         env->ReleaseByteArrayElements(fLockedArray, (jbyte*)fLockedPtr,
    135                                       dataChanged ? 0 : JNI_ABORT);
    136 
    137         fLockedPtr = NULL;
    138         fLockedArray = NULL;
    139     } else {
    140         SkDebugf("============= unlock called with null ptr %x\n", fLockedArray);
    141     }
    142 }
    143 
    144