1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
#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);
}
}
|