• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
RegisterJNI(JNIEnv * env)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 
NIOBuffer(JNIEnv * env,jobject buffer)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 
~NIOBuffer()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 
free(JNIEnv * env)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 
lock(JNIEnv * env,int * remaining)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 
unlock(JNIEnv * env,bool dataChanged)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