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