Files
cup_edit/ios/include/common/NioUtils.cpp
2022-02-06 13:28:28 +08:00

152 lines
5.6 KiB
C++

/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common/NioUtils.h"
#include <algorithm>
#include <utils/Log.h>
AutoBuffer::AutoBuffer(JNIEnv *env, jobject buffer, jint size, bool commit) noexcept :
mEnv(env),
mDoCommit(commit) {
mNioUtils.jniClass = env->FindClass("com/google/android/filament/NioUtils");
mNioUtils.jniClass = (jclass) env->NewGlobalRef(mNioUtils.jniClass);
mNioUtils.getBasePointer = env->GetStaticMethodID(mNioUtils.jniClass,
"getBasePointer", "(Ljava/nio/Buffer;JI)J");
mNioUtils.getBaseArray = env->GetStaticMethodID(mNioUtils.jniClass,
"getBaseArray", "(Ljava/nio/Buffer;)Ljava/lang/Object;");
mNioUtils.getBaseArrayOffset = env->GetStaticMethodID(mNioUtils.jniClass,
"getBaseArrayOffset", "(Ljava/nio/Buffer;I)I");
mNioUtils.getBufferType = env->GetStaticMethodID(mNioUtils.jniClass,
"getBufferType", "(Ljava/nio/Buffer;)I");
mBuffer = env->NewGlobalRef(buffer);
mType = (BufferType) env->CallStaticIntMethod(
mNioUtils.jniClass, mNioUtils.getBufferType, mBuffer);
switch (mType) {
case BufferType::BYTE:
mShift = 0;
break;
case BufferType::CHAR:
case BufferType::SHORT:
mShift = 1;
break;
case BufferType::INT:
case BufferType::FLOAT:
mShift = 2;
break;
case BufferType::LONG:
case BufferType::DOUBLE:
mShift = 3;
break;
}
mSize = (size_t) size << mShift;
jlong address = (jlong) env->GetDirectBufferAddress(mBuffer);
if (address) {
// Direct buffer case
mData = reinterpret_cast<void *>(env->CallStaticLongMethod(mNioUtils.jniClass,
mNioUtils.getBasePointer, mBuffer, address, mShift));
mUserData = mData;
} else {
// wrapped array case
jarray array = (jarray) env->CallStaticObjectMethod(mNioUtils.jniClass,
mNioUtils.getBaseArray, mBuffer);
jint offset = env->CallStaticIntMethod(mNioUtils.jniClass,
mNioUtils.getBaseArrayOffset, mBuffer, mShift);
mBaseArray = (jarray) env->NewGlobalRef(array);
switch (mType) {
case BufferType::BYTE:
mData = env->GetByteArrayElements((jbyteArray)mBaseArray, nullptr);
break;
case BufferType::CHAR:
mData = env->GetCharArrayElements((jcharArray)mBaseArray, nullptr);
break;
case BufferType::SHORT:
mData = env->GetShortArrayElements((jshortArray)mBaseArray, nullptr);
break;
case BufferType::INT:
mData = env->GetIntArrayElements((jintArray)mBaseArray, nullptr);
break;
case BufferType::LONG:
mData = env->GetLongArrayElements((jlongArray)mBaseArray, nullptr);
break;
case BufferType::FLOAT:
mData = env->GetFloatArrayElements((jfloatArray)mBaseArray, nullptr);
break;
case BufferType::DOUBLE:
mData = env->GetDoubleArrayElements((jdoubleArray)mBaseArray, nullptr);
break;
}
mUserData = (void *) ((char *) mData + offset);
}
}
AutoBuffer::AutoBuffer(AutoBuffer &&rhs) noexcept {
mEnv = rhs.mEnv;
std::swap(mData, rhs.mData);
std::swap(mUserData, rhs.mUserData);
std::swap(mSize, rhs.mSize);
std::swap(mType, rhs.mType);
std::swap(mShift, rhs.mShift);
std::swap(mBuffer, rhs.mBuffer);
std::swap(mBaseArray, rhs.mBaseArray);
std::swap(mNioUtils, rhs.mNioUtils);
}
AutoBuffer::~AutoBuffer() noexcept {
JNIEnv *env = mEnv;
if (mBaseArray) {
jint mode = mDoCommit ? 0 : JNI_ABORT;
switch (mType) {
case BufferType::BYTE:
env->ReleaseByteArrayElements((jbyteArray)mBaseArray, (jbyte *) mData, mode);
break;
case BufferType::CHAR:
env->ReleaseCharArrayElements((jcharArray)mBaseArray, (jchar *) mData, mode);
break;
case BufferType::SHORT:
env->ReleaseShortArrayElements((jshortArray)mBaseArray, (jshort *) mData, mode);
break;
case BufferType::INT:
env->ReleaseIntArrayElements((jintArray)mBaseArray, (jint *) mData, mode);
break;
case BufferType::LONG:
env->ReleaseLongArrayElements((jlongArray)mBaseArray, (jlong *) mData, mode);
break;
case BufferType::FLOAT:
env->ReleaseFloatArrayElements((jfloatArray)mBaseArray, (jfloat *) mData, mode);
break;
case BufferType::DOUBLE:
env->ReleaseDoubleArrayElements((jdoubleArray)mBaseArray, (jdouble *) mData, mode);
break;
}
env->DeleteGlobalRef(mBaseArray);
}
if (mBuffer) {
env->DeleteGlobalRef(mBuffer);
}
mEnv->DeleteGlobalRef(mNioUtils.jniClass);
}