android_renderscript_RenderScript.cpp revision 9eb9dd326ae93cd84eb9bbc740f753fe8d8c7a13
1/* 2 * Copyright (C) 2011-2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define LOG_TAG "RenderScript_jni" 18 19#include <stdlib.h> 20#include <stdio.h> 21#include <fcntl.h> 22#include <unistd.h> 23#include <math.h> 24#include <utils/misc.h> 25#include <inttypes.h> 26 27#include <androidfw/Asset.h> 28#include <androidfw/AssetManager.h> 29#include <androidfw/ResourceTypes.h> 30 31#include "jni.h" 32#include "JNIHelp.h" 33#include "android_runtime/AndroidRuntime.h" 34#include "android_runtime/android_view_Surface.h" 35#include "android_runtime/android_util_AssetManager.h" 36#include "android/graphics/GraphicsJNI.h" 37 38#include <rs.h> 39#include <rsEnv.h> 40#include <gui/Surface.h> 41#include <gui/GLConsumer.h> 42#include <android_runtime/android_graphics_SurfaceTexture.h> 43 44//#define LOG_API ALOGE 45static constexpr bool kLogApi = false; 46static constexpr size_t kMaxNumberArgsAndBindings = 1000; 47static constexpr size_t kMaxNumberClosuresInScriptGroup = 1000000; 48static constexpr size_t kMaxNumberKernelArguments = 256; 49 50using namespace android; 51 52template <typename... T> 53void UNUSED(T... t) {} 54 55#define PER_ARRAY_TYPE(flag, fnc, readonly, ...) { \ 56 jint len = 0; \ 57 void *ptr = nullptr; \ 58 void *srcPtr = nullptr; \ 59 size_t typeBytes = 0; \ 60 jint relFlag = 0; \ 61 if (readonly) { \ 62 /* The on-release mode should only be JNI_ABORT for read-only accesses. */ \ 63 /* readonly = true, also indicates we are copying to the allocation . */ \ 64 relFlag = JNI_ABORT; \ 65 } \ 66 switch(dataType) { \ 67 case RS_TYPE_FLOAT_32: \ 68 len = _env->GetArrayLength((jfloatArray)data); \ 69 ptr = _env->GetFloatArrayElements((jfloatArray)data, flag); \ 70 typeBytes = 4; \ 71 if (usePadding) { \ 72 srcPtr = ptr; \ 73 len = len / 3 * 4; \ 74 if (count == 0) { \ 75 count = len / 4; \ 76 } \ 77 ptr = malloc (len * typeBytes); \ 78 if (readonly) { \ 79 copyWithPadding(ptr, srcPtr, mSize, count); \ 80 fnc(__VA_ARGS__); \ 81 } else { \ 82 fnc(__VA_ARGS__); \ 83 copyWithUnPadding(srcPtr, ptr, mSize, count); \ 84 } \ 85 free(ptr); \ 86 ptr = srcPtr; \ 87 } else { \ 88 fnc(__VA_ARGS__); \ 89 } \ 90 _env->ReleaseFloatArrayElements((jfloatArray)data, (jfloat *)ptr, relFlag); \ 91 return; \ 92 case RS_TYPE_FLOAT_64: \ 93 len = _env->GetArrayLength((jdoubleArray)data); \ 94 ptr = _env->GetDoubleArrayElements((jdoubleArray)data, flag); \ 95 typeBytes = 8; \ 96 if (usePadding) { \ 97 srcPtr = ptr; \ 98 len = len / 3 * 4; \ 99 if (count == 0) { \ 100 count = len / 4; \ 101 } \ 102 ptr = malloc (len * typeBytes); \ 103 if (readonly) { \ 104 copyWithPadding(ptr, srcPtr, mSize, count); \ 105 fnc(__VA_ARGS__); \ 106 } else { \ 107 fnc(__VA_ARGS__); \ 108 copyWithUnPadding(srcPtr, ptr, mSize, count); \ 109 } \ 110 free(ptr); \ 111 ptr = srcPtr; \ 112 } else { \ 113 fnc(__VA_ARGS__); \ 114 } \ 115 _env->ReleaseDoubleArrayElements((jdoubleArray)data, (jdouble *)ptr, relFlag); \ 116 return; \ 117 case RS_TYPE_SIGNED_8: \ 118 case RS_TYPE_UNSIGNED_8: \ 119 len = _env->GetArrayLength((jbyteArray)data); \ 120 ptr = _env->GetByteArrayElements((jbyteArray)data, flag); \ 121 typeBytes = 1; \ 122 if (usePadding) { \ 123 srcPtr = ptr; \ 124 len = len / 3 * 4; \ 125 if (count == 0) { \ 126 count = len / 4; \ 127 } \ 128 ptr = malloc (len * typeBytes); \ 129 if (readonly) { \ 130 copyWithPadding(ptr, srcPtr, mSize, count); \ 131 fnc(__VA_ARGS__); \ 132 } else { \ 133 fnc(__VA_ARGS__); \ 134 copyWithUnPadding(srcPtr, ptr, mSize, count); \ 135 } \ 136 free(ptr); \ 137 ptr = srcPtr; \ 138 } else { \ 139 fnc(__VA_ARGS__); \ 140 } \ 141 _env->ReleaseByteArrayElements((jbyteArray)data, (jbyte*)ptr, relFlag); \ 142 return; \ 143 case RS_TYPE_SIGNED_16: \ 144 case RS_TYPE_UNSIGNED_16: \ 145 len = _env->GetArrayLength((jshortArray)data); \ 146 ptr = _env->GetShortArrayElements((jshortArray)data, flag); \ 147 typeBytes = 2; \ 148 if (usePadding) { \ 149 srcPtr = ptr; \ 150 len = len / 3 * 4; \ 151 if (count == 0) { \ 152 count = len / 4; \ 153 } \ 154 ptr = malloc (len * typeBytes); \ 155 if (readonly) { \ 156 copyWithPadding(ptr, srcPtr, mSize, count); \ 157 fnc(__VA_ARGS__); \ 158 } else { \ 159 fnc(__VA_ARGS__); \ 160 copyWithUnPadding(srcPtr, ptr, mSize, count); \ 161 } \ 162 free(ptr); \ 163 ptr = srcPtr; \ 164 } else { \ 165 fnc(__VA_ARGS__); \ 166 } \ 167 _env->ReleaseShortArrayElements((jshortArray)data, (jshort *)ptr, relFlag); \ 168 return; \ 169 case RS_TYPE_SIGNED_32: \ 170 case RS_TYPE_UNSIGNED_32: \ 171 len = _env->GetArrayLength((jintArray)data); \ 172 ptr = _env->GetIntArrayElements((jintArray)data, flag); \ 173 typeBytes = 4; \ 174 if (usePadding) { \ 175 srcPtr = ptr; \ 176 len = len / 3 * 4; \ 177 if (count == 0) { \ 178 count = len / 4; \ 179 } \ 180 ptr = malloc (len * typeBytes); \ 181 if (readonly) { \ 182 copyWithPadding(ptr, srcPtr, mSize, count); \ 183 fnc(__VA_ARGS__); \ 184 } else { \ 185 fnc(__VA_ARGS__); \ 186 copyWithUnPadding(srcPtr, ptr, mSize, count); \ 187 } \ 188 free(ptr); \ 189 ptr = srcPtr; \ 190 } else { \ 191 fnc(__VA_ARGS__); \ 192 } \ 193 _env->ReleaseIntArrayElements((jintArray)data, (jint *)ptr, relFlag); \ 194 return; \ 195 case RS_TYPE_SIGNED_64: \ 196 case RS_TYPE_UNSIGNED_64: \ 197 len = _env->GetArrayLength((jlongArray)data); \ 198 ptr = _env->GetLongArrayElements((jlongArray)data, flag); \ 199 typeBytes = 8; \ 200 if (usePadding) { \ 201 srcPtr = ptr; \ 202 len = len / 3 * 4; \ 203 if (count == 0) { \ 204 count = len / 4; \ 205 } \ 206 ptr = malloc (len * typeBytes); \ 207 if (readonly) { \ 208 copyWithPadding(ptr, srcPtr, mSize, count); \ 209 fnc(__VA_ARGS__); \ 210 } else { \ 211 fnc(__VA_ARGS__); \ 212 copyWithUnPadding(srcPtr, ptr, mSize, count); \ 213 } \ 214 free(ptr); \ 215 ptr = srcPtr; \ 216 } else { \ 217 fnc(__VA_ARGS__); \ 218 } \ 219 _env->ReleaseLongArrayElements((jlongArray)data, (jlong *)ptr, relFlag); \ 220 return; \ 221 default: \ 222 break; \ 223 } \ 224 UNUSED(len, ptr, srcPtr, typeBytes, relFlag); \ 225} 226 227 228class AutoJavaStringToUTF8 { 229public: 230 AutoJavaStringToUTF8(JNIEnv* env, jstring str) : fEnv(env), fJStr(str) { 231 fCStr = env->GetStringUTFChars(str, nullptr); 232 fLength = env->GetStringUTFLength(str); 233 } 234 ~AutoJavaStringToUTF8() { 235 fEnv->ReleaseStringUTFChars(fJStr, fCStr); 236 } 237 const char* c_str() const { return fCStr; } 238 jsize length() const { return fLength; } 239 240private: 241 JNIEnv* fEnv; 242 jstring fJStr; 243 const char* fCStr; 244 jsize fLength; 245}; 246 247class AutoJavaStringArrayToUTF8 { 248public: 249 AutoJavaStringArrayToUTF8(JNIEnv* env, jobjectArray strings, jsize stringsLength) 250 : mEnv(env), mStrings(strings), mStringsLength(stringsLength) { 251 mCStrings = nullptr; 252 mSizeArray = nullptr; 253 if (stringsLength > 0) { 254 mCStrings = (const char **)calloc(stringsLength, sizeof(char *)); 255 mSizeArray = (size_t*)calloc(stringsLength, sizeof(size_t)); 256 for (jsize ct = 0; ct < stringsLength; ct ++) { 257 jstring s = (jstring)mEnv->GetObjectArrayElement(mStrings, ct); 258 mCStrings[ct] = mEnv->GetStringUTFChars(s, nullptr); 259 mSizeArray[ct] = mEnv->GetStringUTFLength(s); 260 } 261 } 262 } 263 ~AutoJavaStringArrayToUTF8() { 264 for (jsize ct=0; ct < mStringsLength; ct++) { 265 jstring s = (jstring)mEnv->GetObjectArrayElement(mStrings, ct); 266 mEnv->ReleaseStringUTFChars(s, mCStrings[ct]); 267 } 268 free(mCStrings); 269 free(mSizeArray); 270 } 271 const char **c_str() const { return mCStrings; } 272 size_t *c_str_len() const { return mSizeArray; } 273 jsize length() const { return mStringsLength; } 274 275private: 276 JNIEnv *mEnv; 277 jobjectArray mStrings; 278 const char **mCStrings; 279 size_t *mSizeArray; 280 jsize mStringsLength; 281}; 282 283// --------------------------------------------------------------------------- 284 285static jfieldID gContextId = 0; 286 287static void _nInit(JNIEnv *_env, jclass _this) 288{ 289 gContextId = _env->GetFieldID(_this, "mContext", "J"); 290} 291 292// --------------------------------------------------------------------------- 293 294static void copyWithPadding(void* ptr, void* srcPtr, int mSize, int count) { 295 int sizeBytesPad = mSize * 4; 296 int sizeBytes = mSize * 3; 297 uint8_t *dst = static_cast<uint8_t *>(ptr); 298 uint8_t *src = static_cast<uint8_t *>(srcPtr); 299 for (int i = 0; i < count; i++) { 300 memcpy(dst, src, sizeBytes); 301 dst += sizeBytesPad; 302 src += sizeBytes; 303 } 304} 305 306static void copyWithUnPadding(void* ptr, void* srcPtr, int mSize, int count) { 307 int sizeBytesPad = mSize * 4; 308 int sizeBytes = mSize * 3; 309 uint8_t *dst = static_cast<uint8_t *>(ptr); 310 uint8_t *src = static_cast<uint8_t *>(srcPtr); 311 for (int i = 0; i < count; i++) { 312 memcpy(dst, src, sizeBytes); 313 dst += sizeBytes; 314 src += sizeBytesPad; 315 } 316} 317 318 319// --------------------------------------------------------------------------- 320static void 321nContextFinish(JNIEnv *_env, jobject _this, jlong con) 322{ 323 if (kLogApi) { 324 ALOGD("nContextFinish, con(%p)", (RsContext)con); 325 } 326 rsContextFinish((RsContext)con); 327} 328 329static jlong 330nClosureCreate(JNIEnv *_env, jobject _this, jlong con, jlong kernelID, 331 jlong returnValue, jlongArray fieldIDArray, 332 jlongArray valueArray, jintArray sizeArray, 333 jlongArray depClosureArray, jlongArray depFieldIDArray) { 334 jlong ret = 0; 335 336 jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr); 337 jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray); 338 jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr); 339 jsize values_length = _env->GetArrayLength(valueArray); 340 jint* jSizes = _env->GetIntArrayElements(sizeArray, nullptr); 341 jsize sizes_length = _env->GetArrayLength(sizeArray); 342 jlong* jDepClosures = 343 _env->GetLongArrayElements(depClosureArray, nullptr); 344 jsize depClosures_length = _env->GetArrayLength(depClosureArray); 345 jlong* jDepFieldIDs = 346 _env->GetLongArrayElements(depFieldIDArray, nullptr); 347 jsize depFieldIDs_length = _env->GetArrayLength(depFieldIDArray); 348 349 size_t numValues, numDependencies; 350 RsScriptFieldID* fieldIDs; 351 uintptr_t* values; 352 RsClosure* depClosures; 353 RsScriptFieldID* depFieldIDs; 354 355 if (fieldIDs_length != values_length || values_length != sizes_length) { 356 ALOGE("Unmatched field IDs, values, and sizes in closure creation."); 357 goto exit; 358 } 359 360 numValues = (size_t)fieldIDs_length; 361 362 if (depClosures_length != depFieldIDs_length) { 363 ALOGE("Unmatched closures and field IDs for dependencies in closure creation."); 364 goto exit; 365 } 366 367 numDependencies = (size_t)depClosures_length; 368 369 if (numDependencies > numValues) { 370 ALOGE("Unexpected number of dependencies in closure creation"); 371 goto exit; 372 } 373 374 if (numValues > kMaxNumberArgsAndBindings) { 375 ALOGE("Too many arguments or globals in closure creation"); 376 goto exit; 377 } 378 379 fieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numValues); 380 if (fieldIDs == nullptr) { 381 goto exit; 382 } 383 384 for (size_t i = 0; i < numValues; i++) { 385 fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i]; 386 } 387 388 values = (uintptr_t*)alloca(sizeof(uintptr_t) * numValues); 389 if (values == nullptr) { 390 goto exit; 391 } 392 393 for (size_t i = 0; i < numValues; i++) { 394 values[i] = (uintptr_t)jValues[i]; 395 } 396 397 depClosures = (RsClosure*)alloca(sizeof(RsClosure) * numDependencies); 398 if (depClosures == nullptr) { 399 goto exit; 400 } 401 402 for (size_t i = 0; i < numDependencies; i++) { 403 depClosures[i] = (RsClosure)jDepClosures[i]; 404 } 405 406 depFieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numDependencies); 407 if (depFieldIDs == nullptr) { 408 goto exit; 409 } 410 411 for (size_t i = 0; i < numDependencies; i++) { 412 depFieldIDs[i] = (RsClosure)jDepFieldIDs[i]; 413 } 414 415 ret = (jlong)(uintptr_t)rsClosureCreate( 416 (RsContext)con, (RsScriptKernelID)kernelID, (RsAllocation)returnValue, 417 fieldIDs, numValues, values, numValues, 418 (int*)jSizes, numValues, 419 depClosures, numDependencies, 420 depFieldIDs, numDependencies); 421 422exit: 423 424 _env->ReleaseLongArrayElements(depFieldIDArray, jDepFieldIDs, JNI_ABORT); 425 _env->ReleaseLongArrayElements(depClosureArray, jDepClosures, JNI_ABORT); 426 _env->ReleaseIntArrayElements (sizeArray, jSizes, JNI_ABORT); 427 _env->ReleaseLongArrayElements(valueArray, jValues, JNI_ABORT); 428 _env->ReleaseLongArrayElements(fieldIDArray, jFieldIDs, JNI_ABORT); 429 430 return ret; 431} 432 433static jlong 434nInvokeClosureCreate(JNIEnv *_env, jobject _this, jlong con, jlong invokeID, 435 jbyteArray paramArray, jlongArray fieldIDArray, jlongArray valueArray, 436 jintArray sizeArray) { 437 jlong ret = 0; 438 439 jbyte* jParams = _env->GetByteArrayElements(paramArray, nullptr); 440 jsize jParamLength = _env->GetArrayLength(paramArray); 441 jlong* jFieldIDs = _env->GetLongArrayElements(fieldIDArray, nullptr); 442 jsize fieldIDs_length = _env->GetArrayLength(fieldIDArray); 443 jlong* jValues = _env->GetLongArrayElements(valueArray, nullptr); 444 jsize values_length = _env->GetArrayLength(valueArray); 445 jint* jSizes = _env->GetIntArrayElements(sizeArray, nullptr); 446 jsize sizes_length = _env->GetArrayLength(sizeArray); 447 448 size_t numValues; 449 RsScriptFieldID* fieldIDs; 450 uintptr_t* values; 451 452 if (fieldIDs_length != values_length || values_length != sizes_length) { 453 ALOGE("Unmatched field IDs, values, and sizes in closure creation."); 454 goto exit; 455 } 456 457 numValues = (size_t) fieldIDs_length; 458 459 if (numValues > kMaxNumberArgsAndBindings) { 460 ALOGE("Too many arguments or globals in closure creation"); 461 goto exit; 462 } 463 464 fieldIDs = (RsScriptFieldID*)alloca(sizeof(RsScriptFieldID) * numValues); 465 if (fieldIDs == nullptr) { 466 goto exit; 467 } 468 469 for (size_t i = 0; i< numValues; i++) { 470 fieldIDs[i] = (RsScriptFieldID)jFieldIDs[i]; 471 } 472 473 values = (uintptr_t*)alloca(sizeof(uintptr_t) * numValues); 474 if (values == nullptr) { 475 goto exit; 476 } 477 478 for (size_t i = 0; i < numValues; i++) { 479 values[i] = (uintptr_t)jValues[i]; 480 } 481 482 ret = (jlong)(uintptr_t)rsInvokeClosureCreate( 483 (RsContext)con, (RsScriptInvokeID)invokeID, jParams, jParamLength, 484 fieldIDs, numValues, values, numValues, 485 (int*)jSizes, numValues); 486 487exit: 488 489 _env->ReleaseIntArrayElements (sizeArray, jSizes, JNI_ABORT); 490 _env->ReleaseLongArrayElements(valueArray, jValues, JNI_ABORT); 491 _env->ReleaseLongArrayElements(fieldIDArray, jFieldIDs, JNI_ABORT); 492 _env->ReleaseByteArrayElements(paramArray, jParams, JNI_ABORT); 493 494 return ret; 495} 496 497static void 498nClosureSetArg(JNIEnv *_env, jobject _this, jlong con, jlong closureID, 499 jint index, jlong value, jint size) { 500 rsClosureSetArg((RsContext)con, (RsClosure)closureID, (uint32_t)index, 501 (uintptr_t)value, (size_t)size); 502} 503 504static void 505nClosureSetGlobal(JNIEnv *_env, jobject _this, jlong con, jlong closureID, 506 jlong fieldID, jlong value, jint size) { 507 rsClosureSetGlobal((RsContext)con, (RsClosure)closureID, 508 (RsScriptFieldID)fieldID, (uintptr_t)value, (size_t)size); 509} 510 511static long 512nScriptGroup2Create(JNIEnv *_env, jobject _this, jlong con, jstring name, 513 jstring cacheDir, jlongArray closureArray) { 514 jlong ret = 0; 515 516 AutoJavaStringToUTF8 nameUTF(_env, name); 517 AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir); 518 519 jlong* jClosures = _env->GetLongArrayElements(closureArray, nullptr); 520 jsize numClosures = _env->GetArrayLength(closureArray); 521 522 RsClosure* closures; 523 524 if (numClosures > (jsize) kMaxNumberClosuresInScriptGroup) { 525 ALOGE("Too many closures in script group"); 526 goto exit; 527 } 528 529 closures = (RsClosure*)alloca(sizeof(RsClosure) * numClosures); 530 if (closures == nullptr) { 531 goto exit; 532 } 533 534 for (int i = 0; i < numClosures; i++) { 535 closures[i] = (RsClosure)jClosures[i]; 536 } 537 538 ret = (jlong)(uintptr_t)rsScriptGroup2Create( 539 (RsContext)con, nameUTF.c_str(), nameUTF.length(), 540 cacheDirUTF.c_str(), cacheDirUTF.length(), 541 closures, numClosures); 542 543exit: 544 545 _env->ReleaseLongArrayElements(closureArray, jClosures, JNI_ABORT); 546 547 return ret; 548} 549 550static void 551nScriptGroup2Execute(JNIEnv *_env, jobject _this, jlong con, jlong groupID) { 552 rsScriptGroupExecute((RsContext)con, (RsScriptGroup2)groupID); 553} 554 555static void 556nScriptIntrinsicBLAS_Single(JNIEnv *_env, jobject _this, jlong con, jlong id, jint func, jint TransA, 557 jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K, 558 jfloat alpha, jlong A, jlong B, jfloat beta, jlong C, jint incX, jint incY, 559 jint KL, jint KU) { 560 RsBlasCall call; 561 memset(&call, 0, sizeof(call)); 562 call.func = (RsBlasFunction)func; 563 call.transA = (RsBlasTranspose)TransA; 564 call.transB = (RsBlasTranspose)TransB; 565 call.side = (RsBlasSide)Side; 566 call.uplo = (RsBlasUplo)Uplo; 567 call.diag = (RsBlasDiag)Diag; 568 call.M = M; 569 call.N = N; 570 call.K = K; 571 call.alpha.f = alpha; 572 call.beta.f = beta; 573 call.incX = incX; 574 call.incY = incY; 575 call.KL = KL; 576 call.KU = KU; 577 578 RsAllocation in_allocs[3]; 579 in_allocs[0] = (RsAllocation)A; 580 in_allocs[1] = (RsAllocation)B; 581 in_allocs[2] = (RsAllocation)C; 582 583 rsScriptForEachMulti((RsContext)con, (RsScript)id, 0, 584 in_allocs, sizeof(in_allocs), nullptr, 585 &call, sizeof(call), nullptr, 0); 586} 587 588static void 589nScriptIntrinsicBLAS_Double(JNIEnv *_env, jobject _this, jlong con, jlong id, jint func, jint TransA, 590 jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K, 591 jdouble alpha, jlong A, jlong B, jdouble beta, jlong C, jint incX, jint incY, 592 jint KL, jint KU) { 593 RsBlasCall call; 594 memset(&call, 0, sizeof(call)); 595 call.func = (RsBlasFunction)func; 596 call.transA = (RsBlasTranspose)TransA; 597 call.transB = (RsBlasTranspose)TransB; 598 call.side = (RsBlasSide)Side; 599 call.uplo = (RsBlasUplo)Uplo; 600 call.diag = (RsBlasDiag)Diag; 601 call.M = M; 602 call.N = N; 603 call.K = K; 604 call.alpha.d = alpha; 605 call.beta.d = beta; 606 call.incX = incX; 607 call.incY = incY; 608 call.KL = KL; 609 call.KU = KU; 610 611 RsAllocation in_allocs[3]; 612 in_allocs[0] = (RsAllocation)A; 613 in_allocs[1] = (RsAllocation)B; 614 in_allocs[2] = (RsAllocation)C; 615 616 rsScriptForEachMulti((RsContext)con, (RsScript)id, 0, 617 in_allocs, sizeof(in_allocs), nullptr, 618 &call, sizeof(call), nullptr, 0); 619} 620 621static void 622nScriptIntrinsicBLAS_Complex(JNIEnv *_env, jobject _this, jlong con, jlong id, jint func, jint TransA, 623 jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K, 624 jfloat alphaX, jfloat alphaY, jlong A, jlong B, jfloat betaX, 625 jfloat betaY, jlong C, jint incX, jint incY, jint KL, jint KU) { 626 RsBlasCall call; 627 memset(&call, 0, sizeof(call)); 628 call.func = (RsBlasFunction)func; 629 call.transA = (RsBlasTranspose)TransA; 630 call.transB = (RsBlasTranspose)TransB; 631 call.side = (RsBlasSide)Side; 632 call.uplo = (RsBlasUplo)Uplo; 633 call.diag = (RsBlasDiag)Diag; 634 call.M = M; 635 call.N = N; 636 call.K = K; 637 call.alpha.c.r = alphaX; 638 call.alpha.c.i = alphaY; 639 call.beta.c.r = betaX; 640 call.beta.c.i = betaY; 641 call.incX = incX; 642 call.incY = incY; 643 call.KL = KL; 644 call.KU = KU; 645 646 RsAllocation in_allocs[3]; 647 in_allocs[0] = (RsAllocation)A; 648 in_allocs[1] = (RsAllocation)B; 649 in_allocs[2] = (RsAllocation)C; 650 651 rsScriptForEachMulti((RsContext)con, (RsScript)id, 0, 652 in_allocs, sizeof(in_allocs), nullptr, 653 &call, sizeof(call), nullptr, 0); 654} 655 656static void 657nScriptIntrinsicBLAS_Z(JNIEnv *_env, jobject _this, jlong con, jlong id, jint func, jint TransA, 658 jint TransB, jint Side, jint Uplo, jint Diag, jint M, jint N, jint K, 659 jdouble alphaX, jdouble alphaY, jlong A, jlong B, jdouble betaX, 660 jdouble betaY, jlong C, jint incX, jint incY, jint KL, jint KU) { 661 RsBlasCall call; 662 memset(&call, 0, sizeof(call)); 663 call.func = (RsBlasFunction)func; 664 call.transA = (RsBlasTranspose)TransA; 665 call.transB = (RsBlasTranspose)TransB; 666 call.side = (RsBlasSide)Side; 667 call.uplo = (RsBlasUplo)Uplo; 668 call.diag = (RsBlasDiag)Diag; 669 call.M = M; 670 call.N = N; 671 call.K = K; 672 call.alpha.z.r = alphaX; 673 call.alpha.z.i = alphaY; 674 call.beta.z.r = betaX; 675 call.beta.z.i = betaY; 676 call.incX = incX; 677 call.incY = incY; 678 call.KL = KL; 679 call.KU = KU; 680 681 RsAllocation in_allocs[3]; 682 in_allocs[0] = (RsAllocation)A; 683 in_allocs[1] = (RsAllocation)B; 684 in_allocs[2] = (RsAllocation)C; 685 686 rsScriptForEachMulti((RsContext)con, (RsScript)id, 0, 687 in_allocs, sizeof(in_allocs), nullptr, 688 &call, sizeof(call), nullptr, 0); 689} 690 691 692static void 693nScriptIntrinsicBLAS_BNNM(JNIEnv *_env, jobject _this, jlong con, jlong id, jint M, jint N, jint K, 694 jlong A, jint a_offset, jlong B, jint b_offset, jlong C, jint c_offset, 695 jint c_mult_int) { 696 RsBlasCall call; 697 memset(&call, 0, sizeof(call)); 698 call.func = RsBlas_bnnm; 699 call.M = M; 700 call.N = N; 701 call.K = K; 702 call.a_offset = a_offset; 703 call.b_offset = b_offset; 704 call.c_offset = c_offset; 705 call.c_mult_int = c_mult_int; 706 707 RsAllocation in_allocs[3]; 708 in_allocs[0] = (RsAllocation)A; 709 in_allocs[1] = (RsAllocation)B; 710 in_allocs[2] = (RsAllocation)C; 711 712 rsScriptForEachMulti((RsContext)con, (RsScript)id, 0, 713 in_allocs, sizeof(in_allocs), nullptr, 714 &call, sizeof(call), nullptr, 0); 715} 716 717 718static void 719nAssignName(JNIEnv *_env, jobject _this, jlong con, jlong obj, jbyteArray str) 720{ 721 if (kLogApi) { 722 ALOGD("nAssignName, con(%p), obj(%p)", (RsContext)con, (void *)obj); 723 } 724 jint len = _env->GetArrayLength(str); 725 jbyte * cptr = (jbyte *) _env->GetPrimitiveArrayCritical(str, 0); 726 rsAssignName((RsContext)con, (void *)obj, (const char *)cptr, len); 727 _env->ReleasePrimitiveArrayCritical(str, cptr, JNI_ABORT); 728} 729 730static jstring 731nGetName(JNIEnv *_env, jobject _this, jlong con, jlong obj) 732{ 733 if (kLogApi) { 734 ALOGD("nGetName, con(%p), obj(%p)", (RsContext)con, (void *)obj); 735 } 736 const char *name = nullptr; 737 rsaGetName((RsContext)con, (void *)obj, &name); 738 if(name == nullptr || strlen(name) == 0) { 739 return nullptr; 740 } 741 return _env->NewStringUTF(name); 742} 743 744static void 745nObjDestroy(JNIEnv *_env, jobject _this, jlong con, jlong obj) 746{ 747 if (kLogApi) { 748 ALOGD("nObjDestroy, con(%p) obj(%p)", (RsContext)con, (void *)obj); 749 } 750 rsObjDestroy((RsContext)con, (void *)obj); 751} 752 753// --------------------------------------------------------------------------- 754 755static jlong 756nDeviceCreate(JNIEnv *_env, jobject _this) 757{ 758 if (kLogApi) { 759 ALOGD("nDeviceCreate"); 760 } 761 return (jlong)(uintptr_t)rsDeviceCreate(); 762} 763 764static void 765nDeviceDestroy(JNIEnv *_env, jobject _this, jlong dev) 766{ 767 if (kLogApi) { 768 ALOGD("nDeviceDestroy"); 769 } 770 return rsDeviceDestroy((RsDevice)dev); 771} 772 773static void 774nDeviceSetConfig(JNIEnv *_env, jobject _this, jlong dev, jint p, jint value) 775{ 776 if (kLogApi) { 777 ALOGD("nDeviceSetConfig dev(%p), param(%i), value(%i)", (void *)dev, p, value); 778 } 779 return rsDeviceSetConfig((RsDevice)dev, (RsDeviceParam)p, value); 780} 781 782static jlong 783nContextCreate(JNIEnv *_env, jobject _this, jlong dev, jint flags, jint sdkVer, jint contextType) 784{ 785 if (kLogApi) { 786 ALOGD("nContextCreate"); 787 } 788 return (jlong)(uintptr_t)rsContextCreate((RsDevice)dev, 0, sdkVer, (RsContextType)contextType, flags); 789} 790 791static jlong 792nContextCreateGL(JNIEnv *_env, jobject _this, jlong dev, jint ver, jint sdkVer, 793 jint colorMin, jint colorPref, 794 jint alphaMin, jint alphaPref, 795 jint depthMin, jint depthPref, 796 jint stencilMin, jint stencilPref, 797 jint samplesMin, jint samplesPref, jfloat samplesQ, 798 jint dpi) 799{ 800 RsSurfaceConfig sc; 801 sc.alphaMin = alphaMin; 802 sc.alphaPref = alphaPref; 803 sc.colorMin = colorMin; 804 sc.colorPref = colorPref; 805 sc.depthMin = depthMin; 806 sc.depthPref = depthPref; 807 sc.samplesMin = samplesMin; 808 sc.samplesPref = samplesPref; 809 sc.samplesQ = samplesQ; 810 811 if (kLogApi) { 812 ALOGD("nContextCreateGL"); 813 } 814 return (jlong)(uintptr_t)rsContextCreateGL((RsDevice)dev, ver, sdkVer, sc, dpi); 815} 816 817static void 818nContextSetPriority(JNIEnv *_env, jobject _this, jlong con, jint p) 819{ 820 if (kLogApi) { 821 ALOGD("ContextSetPriority, con(%p), priority(%i)", (RsContext)con, p); 822 } 823 rsContextSetPriority((RsContext)con, p); 824} 825 826static void 827nContextSetCacheDir(JNIEnv *_env, jobject _this, jlong con, jstring cacheDir) 828{ 829 AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir); 830 831 if (kLogApi) { 832 ALOGD("ContextSetCacheDir, con(%p), cacheDir(%s)", (RsContext)con, cacheDirUTF.c_str()); 833 } 834 rsContextSetCacheDir((RsContext)con, cacheDirUTF.c_str(), cacheDirUTF.length()); 835} 836 837 838 839static void 840nContextSetSurface(JNIEnv *_env, jobject _this, jlong con, jint width, jint height, jobject wnd) 841{ 842 if (kLogApi) { 843 ALOGD("nContextSetSurface, con(%p), width(%i), height(%i), surface(%p)", (RsContext)con, 844 width, height, (Surface *)wnd); 845 } 846 847 ANativeWindow * window = nullptr; 848 if (wnd == nullptr) { 849 850 } else { 851 window = android_view_Surface_getNativeWindow(_env, wnd).get(); 852 } 853 854 rsContextSetSurface((RsContext)con, width, height, window); 855} 856 857static void 858nContextDestroy(JNIEnv *_env, jobject _this, jlong con) 859{ 860 if (kLogApi) { 861 ALOGD("nContextDestroy, con(%p)", (RsContext)con); 862 } 863 rsContextDestroy((RsContext)con); 864} 865 866static void 867nContextDump(JNIEnv *_env, jobject _this, jlong con, jint bits) 868{ 869 if (kLogApi) { 870 ALOGD("nContextDump, con(%p) bits(%i)", (RsContext)con, bits); 871 } 872 rsContextDump((RsContext)con, bits); 873} 874 875static void 876nContextPause(JNIEnv *_env, jobject _this, jlong con) 877{ 878 if (kLogApi) { 879 ALOGD("nContextPause, con(%p)", (RsContext)con); 880 } 881 rsContextPause((RsContext)con); 882} 883 884static void 885nContextResume(JNIEnv *_env, jobject _this, jlong con) 886{ 887 if (kLogApi) { 888 ALOGD("nContextResume, con(%p)", (RsContext)con); 889 } 890 rsContextResume((RsContext)con); 891} 892 893 894static jstring 895nContextGetErrorMessage(JNIEnv *_env, jobject _this, jlong con) 896{ 897 if (kLogApi) { 898 ALOGD("nContextGetErrorMessage, con(%p)", (RsContext)con); 899 } 900 char buf[1024]; 901 902 size_t receiveLen; 903 uint32_t subID; 904 int id = rsContextGetMessage((RsContext)con, 905 buf, sizeof(buf), 906 &receiveLen, sizeof(receiveLen), 907 &subID, sizeof(subID)); 908 if (!id && receiveLen) { 909 ALOGV("message receive buffer too small. %zu", receiveLen); 910 } 911 return _env->NewStringUTF(buf); 912} 913 914static jint 915nContextGetUserMessage(JNIEnv *_env, jobject _this, jlong con, jintArray data) 916{ 917 jint len = _env->GetArrayLength(data); 918 if (kLogApi) { 919 ALOGD("nContextGetMessage, con(%p), len(%i)", (RsContext)con, len); 920 } 921 jint *ptr = _env->GetIntArrayElements(data, nullptr); 922 size_t receiveLen; 923 uint32_t subID; 924 int id = rsContextGetMessage((RsContext)con, 925 ptr, len * 4, 926 &receiveLen, sizeof(receiveLen), 927 &subID, sizeof(subID)); 928 if (!id && receiveLen) { 929 ALOGV("message receive buffer too small. %zu", receiveLen); 930 } 931 _env->ReleaseIntArrayElements(data, ptr, 0); 932 return (jint)id; 933} 934 935static jint 936nContextPeekMessage(JNIEnv *_env, jobject _this, jlong con, jintArray auxData) 937{ 938 if (kLogApi) { 939 ALOGD("nContextPeekMessage, con(%p)", (RsContext)con); 940 } 941 jint *auxDataPtr = _env->GetIntArrayElements(auxData, nullptr); 942 size_t receiveLen; 943 uint32_t subID; 944 int id = rsContextPeekMessage((RsContext)con, &receiveLen, sizeof(receiveLen), 945 &subID, sizeof(subID)); 946 auxDataPtr[0] = (jint)subID; 947 auxDataPtr[1] = (jint)receiveLen; 948 _env->ReleaseIntArrayElements(auxData, auxDataPtr, 0); 949 return (jint)id; 950} 951 952static void nContextInitToClient(JNIEnv *_env, jobject _this, jlong con) 953{ 954 if (kLogApi) { 955 ALOGD("nContextInitToClient, con(%p)", (RsContext)con); 956 } 957 rsContextInitToClient((RsContext)con); 958} 959 960static void nContextDeinitToClient(JNIEnv *_env, jobject _this, jlong con) 961{ 962 if (kLogApi) { 963 ALOGD("nContextDeinitToClient, con(%p)", (RsContext)con); 964 } 965 rsContextDeinitToClient((RsContext)con); 966} 967 968static void 969nContextSendMessage(JNIEnv *_env, jobject _this, jlong con, jint id, jintArray data) 970{ 971 jint *ptr = nullptr; 972 jint len = 0; 973 if (data) { 974 len = _env->GetArrayLength(data); 975 ptr = _env->GetIntArrayElements(data, nullptr); 976 } 977 if (kLogApi) { 978 ALOGD("nContextSendMessage, con(%p), id(%i), len(%i)", (RsContext)con, id, len); 979 } 980 rsContextSendMessage((RsContext)con, id, (const uint8_t *)ptr, len * sizeof(int)); 981 if (data) { 982 _env->ReleaseIntArrayElements(data, ptr, JNI_ABORT); 983 } 984} 985 986 987 988static jlong 989nElementCreate(JNIEnv *_env, jobject _this, jlong con, jlong type, jint kind, jboolean norm, 990 jint size) 991{ 992 if (kLogApi) { 993 ALOGD("nElementCreate, con(%p), type(%" PRId64 "), kind(%i), norm(%i), size(%i)", (RsContext)con, 994 type, kind, norm, size); 995 } 996 return (jlong)(uintptr_t)rsElementCreate((RsContext)con, (RsDataType)type, (RsDataKind)kind, 997 norm, size); 998} 999 1000static jlong 1001nElementCreate2(JNIEnv *_env, jobject _this, jlong con, 1002 jlongArray _ids, jobjectArray _names, jintArray _arraySizes) 1003{ 1004 int fieldCount = _env->GetArrayLength(_ids); 1005 if (kLogApi) { 1006 ALOGD("nElementCreate2, con(%p)", (RsContext)con); 1007 } 1008 1009 jlong *jIds = _env->GetLongArrayElements(_ids, nullptr); 1010 jint *jArraySizes = _env->GetIntArrayElements(_arraySizes, nullptr); 1011 1012 RsElement *ids = (RsElement*)malloc(fieldCount * sizeof(RsElement)); 1013 uint32_t *arraySizes = (uint32_t *)malloc(fieldCount * sizeof(uint32_t)); 1014 1015 for(int i = 0; i < fieldCount; i ++) { 1016 ids[i] = (RsElement)jIds[i]; 1017 arraySizes[i] = (uint32_t)jArraySizes[i]; 1018 } 1019 1020 AutoJavaStringArrayToUTF8 names(_env, _names, fieldCount); 1021 1022 const char **nameArray = names.c_str(); 1023 size_t *sizeArray = names.c_str_len(); 1024 1025 jlong id = (jlong)(uintptr_t)rsElementCreate2((RsContext)con, 1026 (const RsElement *)ids, fieldCount, 1027 nameArray, fieldCount * sizeof(size_t), sizeArray, 1028 (const uint32_t *)arraySizes, fieldCount); 1029 1030 free(ids); 1031 free(arraySizes); 1032 _env->ReleaseLongArrayElements(_ids, jIds, JNI_ABORT); 1033 _env->ReleaseIntArrayElements(_arraySizes, jArraySizes, JNI_ABORT); 1034 1035 return (jlong)(uintptr_t)id; 1036} 1037 1038static void 1039nElementGetNativeData(JNIEnv *_env, jobject _this, jlong con, jlong id, jintArray _elementData) 1040{ 1041 int dataSize = _env->GetArrayLength(_elementData); 1042 if (kLogApi) { 1043 ALOGD("nElementGetNativeData, con(%p)", (RsContext)con); 1044 } 1045 1046 // we will pack mType; mKind; mNormalized; mVectorSize; NumSubElements 1047 assert(dataSize == 5); 1048 1049 uintptr_t elementData[5]; 1050 rsaElementGetNativeData((RsContext)con, (RsElement)id, elementData, dataSize); 1051 1052 for(jint i = 0; i < dataSize; i ++) { 1053 const jint data = (jint)elementData[i]; 1054 _env->SetIntArrayRegion(_elementData, i, 1, &data); 1055 } 1056} 1057 1058 1059static void 1060nElementGetSubElements(JNIEnv *_env, jobject _this, jlong con, jlong id, 1061 jlongArray _IDs, 1062 jobjectArray _names, 1063 jintArray _arraySizes) 1064{ 1065 uint32_t dataSize = _env->GetArrayLength(_IDs); 1066 if (kLogApi) { 1067 ALOGD("nElementGetSubElements, con(%p)", (RsContext)con); 1068 } 1069 1070 uintptr_t *ids = (uintptr_t*)malloc(dataSize * sizeof(uintptr_t)); 1071 const char **names = (const char **)malloc(dataSize * sizeof(const char *)); 1072 uint32_t *arraySizes = (uint32_t *)malloc(dataSize * sizeof(uint32_t)); 1073 1074 rsaElementGetSubElements((RsContext)con, (RsElement)id, ids, names, arraySizes, 1075 (uint32_t)dataSize); 1076 1077 for(uint32_t i = 0; i < dataSize; i++) { 1078 const jlong id = (jlong)(uintptr_t)ids[i]; 1079 const jint arraySize = (jint)arraySizes[i]; 1080 _env->SetObjectArrayElement(_names, i, _env->NewStringUTF(names[i])); 1081 _env->SetLongArrayRegion(_IDs, i, 1, &id); 1082 _env->SetIntArrayRegion(_arraySizes, i, 1, &arraySize); 1083 } 1084 1085 free(ids); 1086 free(names); 1087 free(arraySizes); 1088} 1089 1090// ----------------------------------- 1091 1092static jlong 1093nTypeCreate(JNIEnv *_env, jobject _this, jlong con, jlong eid, 1094 jint dimx, jint dimy, jint dimz, jboolean mips, jboolean faces, jint yuv) 1095{ 1096 if (kLogApi) { 1097 ALOGD("nTypeCreate, con(%p) eid(%p), x(%i), y(%i), z(%i), mips(%i), faces(%i), yuv(%i)", 1098 (RsContext)con, (void*)eid, dimx, dimy, dimz, mips, faces, yuv); 1099 } 1100 1101 return (jlong)(uintptr_t)rsTypeCreate((RsContext)con, (RsElement)eid, dimx, dimy, dimz, mips, 1102 faces, yuv); 1103} 1104 1105static void 1106nTypeGetNativeData(JNIEnv *_env, jobject _this, jlong con, jlong id, jlongArray _typeData) 1107{ 1108 // We are packing 6 items: mDimX; mDimY; mDimZ; 1109 // mDimLOD; mDimFaces; mElement; into typeData 1110 int elementCount = _env->GetArrayLength(_typeData); 1111 1112 assert(elementCount == 6); 1113 if (kLogApi) { 1114 ALOGD("nTypeGetNativeData, con(%p)", (RsContext)con); 1115 } 1116 1117 uintptr_t typeData[6]; 1118 rsaTypeGetNativeData((RsContext)con, (RsType)id, typeData, 6); 1119 1120 for(jint i = 0; i < elementCount; i ++) { 1121 const jlong data = (jlong)(uintptr_t)typeData[i]; 1122 _env->SetLongArrayRegion(_typeData, i, 1, &data); 1123 } 1124} 1125 1126// ----------------------------------- 1127 1128static jlong 1129nAllocationCreateTyped(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mips, jint usage, 1130 jlong pointer) 1131{ 1132 if (kLogApi) { 1133 ALOGD("nAllocationCreateTyped, con(%p), type(%p), mip(%i), usage(%i), ptr(%p)", 1134 (RsContext)con, (RsElement)type, mips, usage, (void *)pointer); 1135 } 1136 return (jlong)(uintptr_t) rsAllocationCreateTyped((RsContext)con, (RsType)type, 1137 (RsAllocationMipmapControl)mips, 1138 (uint32_t)usage, (uintptr_t)pointer); 1139} 1140 1141static void 1142nAllocationSyncAll(JNIEnv *_env, jobject _this, jlong con, jlong a, jint bits) 1143{ 1144 if (kLogApi) { 1145 ALOGD("nAllocationSyncAll, con(%p), a(%p), bits(0x%08x)", (RsContext)con, (RsAllocation)a, 1146 bits); 1147 } 1148 rsAllocationSyncAll((RsContext)con, (RsAllocation)a, (RsAllocationUsageType)bits); 1149} 1150 1151static jobject 1152nAllocationGetSurface(JNIEnv *_env, jobject _this, jlong con, jlong a) 1153{ 1154 if (kLogApi) { 1155 ALOGD("nAllocationGetSurface, con(%p), a(%p)", (RsContext)con, (RsAllocation)a); 1156 } 1157 1158 IGraphicBufferProducer *v = (IGraphicBufferProducer *)rsAllocationGetSurface((RsContext)con, 1159 (RsAllocation)a); 1160 sp<IGraphicBufferProducer> bp = v; 1161 v->decStrong(nullptr); 1162 1163 jobject o = android_view_Surface_createFromIGraphicBufferProducer(_env, bp); 1164 return o; 1165} 1166 1167static void 1168nAllocationSetSurface(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject sur) 1169{ 1170 if (kLogApi) { 1171 ALOGD("nAllocationSetSurface, con(%p), alloc(%p), surface(%p)", (RsContext)con, 1172 (RsAllocation)alloc, (Surface *)sur); 1173 } 1174 1175 sp<Surface> s; 1176 if (sur != 0) { 1177 s = android_view_Surface_getSurface(_env, sur); 1178 } 1179 1180 rsAllocationSetSurface((RsContext)con, (RsAllocation)alloc, 1181 static_cast<ANativeWindow *>(s.get())); 1182} 1183 1184static void 1185nAllocationIoSend(JNIEnv *_env, jobject _this, jlong con, jlong alloc) 1186{ 1187 if (kLogApi) { 1188 ALOGD("nAllocationIoSend, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc); 1189 } 1190 rsAllocationIoSend((RsContext)con, (RsAllocation)alloc); 1191} 1192 1193static void 1194nAllocationIoReceive(JNIEnv *_env, jobject _this, jlong con, jlong alloc) 1195{ 1196 if (kLogApi) { 1197 ALOGD("nAllocationIoReceive, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc); 1198 } 1199 rsAllocationIoReceive((RsContext)con, (RsAllocation)alloc); 1200} 1201 1202 1203static void 1204nAllocationGenerateMipmaps(JNIEnv *_env, jobject _this, jlong con, jlong alloc) 1205{ 1206 if (kLogApi) { 1207 ALOGD("nAllocationGenerateMipmaps, con(%p), a(%p)", (RsContext)con, (RsAllocation)alloc); 1208 } 1209 rsAllocationGenerateMipmaps((RsContext)con, (RsAllocation)alloc); 1210} 1211 1212static jlong 1213nAllocationCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mip, 1214 jobject jbitmap, jint usage) 1215{ 1216 SkBitmap bitmap; 1217 GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap); 1218 1219 bitmap.lockPixels(); 1220 const void* ptr = bitmap.getPixels(); 1221 jlong id = (jlong)(uintptr_t)rsAllocationCreateFromBitmap((RsContext)con, 1222 (RsType)type, (RsAllocationMipmapControl)mip, 1223 ptr, bitmap.getSize(), usage); 1224 bitmap.unlockPixels(); 1225 return id; 1226} 1227 1228static jlong 1229nAllocationCreateBitmapBackedAllocation(JNIEnv *_env, jobject _this, jlong con, jlong type, 1230 jint mip, jobject jbitmap, jint usage) 1231{ 1232 SkBitmap bitmap; 1233 GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap); 1234 1235 bitmap.lockPixels(); 1236 const void* ptr = bitmap.getPixels(); 1237 jlong id = (jlong)(uintptr_t)rsAllocationCreateTyped((RsContext)con, 1238 (RsType)type, (RsAllocationMipmapControl)mip, 1239 (uint32_t)usage, (uintptr_t)ptr); 1240 bitmap.unlockPixels(); 1241 return id; 1242} 1243 1244static jlong 1245nAllocationCubeCreateFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong type, jint mip, 1246 jobject jbitmap, jint usage) 1247{ 1248 SkBitmap bitmap; 1249 GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap); 1250 1251 bitmap.lockPixels(); 1252 const void* ptr = bitmap.getPixels(); 1253 jlong id = (jlong)(uintptr_t)rsAllocationCubeCreateFromBitmap((RsContext)con, 1254 (RsType)type, (RsAllocationMipmapControl)mip, 1255 ptr, bitmap.getSize(), usage); 1256 bitmap.unlockPixels(); 1257 return id; 1258} 1259 1260static void 1261nAllocationCopyFromBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap) 1262{ 1263 SkBitmap bitmap; 1264 GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap); 1265 int w = bitmap.width(); 1266 int h = bitmap.height(); 1267 1268 bitmap.lockPixels(); 1269 const void* ptr = bitmap.getPixels(); 1270 rsAllocation2DData((RsContext)con, (RsAllocation)alloc, 0, 0, 1271 0, RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, 1272 w, h, ptr, bitmap.getSize(), 0); 1273 bitmap.unlockPixels(); 1274} 1275 1276static void 1277nAllocationCopyToBitmap(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jobject jbitmap) 1278{ 1279 SkBitmap bitmap; 1280 GraphicsJNI::getSkBitmap(_env, jbitmap, &bitmap); 1281 1282 bitmap.lockPixels(); 1283 void* ptr = bitmap.getPixels(); 1284 rsAllocationCopyToBitmap((RsContext)con, (RsAllocation)alloc, ptr, bitmap.getSize()); 1285 bitmap.unlockPixels(); 1286 bitmap.notifyPixelsChanged(); 1287} 1288 1289// Copies from the Java object data into the Allocation pointed to by _alloc. 1290static void 1291nAllocationData1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod, 1292 jint count, jobject data, jint sizeBytes, jint dataType, jint mSize, 1293 jboolean usePadding) 1294{ 1295 RsAllocation *alloc = (RsAllocation *)_alloc; 1296 if (kLogApi) { 1297 ALOGD("nAllocation1DData, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), " 1298 "dataType(%i)", (RsContext)con, (RsAllocation)alloc, offset, count, sizeBytes, 1299 dataType); 1300 } 1301 PER_ARRAY_TYPE(nullptr, rsAllocation1DData, true, 1302 (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes); 1303} 1304 1305static void 1306nAllocationElementData(JNIEnv *_env, jobject _this, jlong con, jlong alloc, 1307 jint xoff, jint yoff, jint zoff, 1308 jint lod, jint compIdx, jbyteArray data, jint sizeBytes) 1309{ 1310 jint len = _env->GetArrayLength(data); 1311 if (kLogApi) { 1312 ALOGD("nAllocationElementData, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), comp(%i), len(%i), " 1313 "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, compIdx, len, 1314 sizeBytes); 1315 } 1316 jbyte *ptr = _env->GetByteArrayElements(data, nullptr); 1317 rsAllocationElementData((RsContext)con, (RsAllocation)alloc, 1318 xoff, yoff, zoff, 1319 lod, ptr, sizeBytes, compIdx); 1320 _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT); 1321} 1322 1323 1324// Copies from the Java object data into the Allocation pointed to by _alloc. 1325static void 1326nAllocationData2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face, 1327 jint w, jint h, jobject data, jint sizeBytes, jint dataType, jint mSize, 1328 jboolean usePadding) 1329{ 1330 RsAllocation *alloc = (RsAllocation *)_alloc; 1331 RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face; 1332 if (kLogApi) { 1333 ALOGD("nAllocation2DData, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) " 1334 "type(%i)", (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType); 1335 } 1336 int count = w * h; 1337 PER_ARRAY_TYPE(nullptr, rsAllocation2DData, true, 1338 (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0); 1339} 1340 1341// Copies from the Allocation pointed to by srcAlloc into the Allocation 1342// pointed to by dstAlloc. 1343static void 1344nAllocationData2D_alloc(JNIEnv *_env, jobject _this, jlong con, 1345 jlong dstAlloc, jint dstXoff, jint dstYoff, 1346 jint dstMip, jint dstFace, 1347 jint width, jint height, 1348 jlong srcAlloc, jint srcXoff, jint srcYoff, 1349 jint srcMip, jint srcFace) 1350{ 1351 if (kLogApi) { 1352 ALOGD("nAllocation2DData_s, con(%p), dstAlloc(%p), dstXoff(%i), dstYoff(%i)," 1353 " dstMip(%i), dstFace(%i), width(%i), height(%i)," 1354 " srcAlloc(%p), srcXoff(%i), srcYoff(%i), srcMip(%i), srcFace(%i)", 1355 (RsContext)con, (RsAllocation)dstAlloc, dstXoff, dstYoff, dstMip, dstFace, 1356 width, height, (RsAllocation)srcAlloc, srcXoff, srcYoff, srcMip, srcFace); 1357 } 1358 1359 rsAllocationCopy2DRange((RsContext)con, 1360 (RsAllocation)dstAlloc, 1361 dstXoff, dstYoff, 1362 dstMip, dstFace, 1363 width, height, 1364 (RsAllocation)srcAlloc, 1365 srcXoff, srcYoff, 1366 srcMip, srcFace); 1367} 1368 1369// Copies from the Java object data into the Allocation pointed to by _alloc. 1370static void 1371nAllocationData3D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint zoff, jint lod, 1372 jint w, jint h, jint d, jobject data, jint sizeBytes, jint dataType, 1373 jint mSize, jboolean usePadding) 1374{ 1375 RsAllocation *alloc = (RsAllocation *)_alloc; 1376 if (kLogApi) { 1377 ALOGD("nAllocation3DData, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), lod(%i), w(%i)," 1378 " h(%i), d(%i), sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, 1379 lod, w, h, d, sizeBytes); 1380 } 1381 int count = w * h * d; 1382 PER_ARRAY_TYPE(nullptr, rsAllocation3DData, true, 1383 (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0); 1384} 1385 1386// Copies from the Allocation pointed to by srcAlloc into the Allocation 1387// pointed to by dstAlloc. 1388static void 1389nAllocationData3D_alloc(JNIEnv *_env, jobject _this, jlong con, 1390 jlong dstAlloc, jint dstXoff, jint dstYoff, jint dstZoff, 1391 jint dstMip, 1392 jint width, jint height, jint depth, 1393 jlong srcAlloc, jint srcXoff, jint srcYoff, jint srcZoff, 1394 jint srcMip) 1395{ 1396 if (kLogApi) { 1397 ALOGD("nAllocationData3D_alloc, con(%p), dstAlloc(%p), dstXoff(%i), dstYoff(%i)," 1398 " dstMip(%i), width(%i), height(%i)," 1399 " srcAlloc(%p), srcXoff(%i), srcYoff(%i), srcMip(%i)", 1400 (RsContext)con, (RsAllocation)dstAlloc, dstXoff, dstYoff, dstMip, 1401 width, height, (RsAllocation)srcAlloc, srcXoff, srcYoff, srcMip); 1402 } 1403 1404 rsAllocationCopy3DRange((RsContext)con, 1405 (RsAllocation)dstAlloc, 1406 dstXoff, dstYoff, dstZoff, dstMip, 1407 width, height, depth, 1408 (RsAllocation)srcAlloc, 1409 srcXoff, srcYoff, srcZoff, srcMip); 1410} 1411 1412 1413// Copies from the Allocation pointed to by _alloc into the Java object data. 1414static void 1415nAllocationRead(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jobject data, jint dataType, 1416 jint mSize, jboolean usePadding) 1417{ 1418 RsAllocation *alloc = (RsAllocation *)_alloc; 1419 if (kLogApi) { 1420 ALOGD("nAllocationRead, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc); 1421 } 1422 int count = 0; 1423 PER_ARRAY_TYPE(0, rsAllocationRead, false, 1424 (RsContext)con, alloc, ptr, len * typeBytes); 1425} 1426 1427// Copies from the Allocation pointed to by _alloc into the Java object data. 1428static void 1429nAllocationRead1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod, 1430 jint count, jobject data, jint sizeBytes, jint dataType, 1431 jint mSize, jboolean usePadding) 1432{ 1433 RsAllocation *alloc = (RsAllocation *)_alloc; 1434 if (kLogApi) { 1435 ALOGD("nAllocation1DRead, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), " 1436 "dataType(%i)", (RsContext)con, alloc, offset, count, sizeBytes, dataType); 1437 } 1438 PER_ARRAY_TYPE(0, rsAllocation1DRead, false, 1439 (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes); 1440} 1441 1442// Copies from the Element in the Allocation pointed to by _alloc into the Java array data. 1443static void 1444nAllocationElementRead(JNIEnv *_env, jobject _this, jlong con, jlong alloc, 1445 jint xoff, jint yoff, jint zoff, 1446 jint lod, jint compIdx, jbyteArray data, jint sizeBytes) 1447{ 1448 jint len = _env->GetArrayLength(data); 1449 if (kLogApi) { 1450 ALOGD("nAllocationElementRead, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), comp(%i), len(%i), " 1451 "sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, compIdx, len, 1452 sizeBytes); 1453 } 1454 jbyte *ptr = _env->GetByteArrayElements(data, nullptr); 1455 rsAllocationElementRead((RsContext)con, (RsAllocation)alloc, 1456 xoff, yoff, zoff, 1457 lod, ptr, sizeBytes, compIdx); 1458 _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT); 1459} 1460 1461// Copies from the Allocation pointed to by _alloc into the Java object data. 1462static void 1463nAllocationRead2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face, 1464 jint w, jint h, jobject data, jint sizeBytes, jint dataType, 1465 jint mSize, jboolean usePadding) 1466{ 1467 RsAllocation *alloc = (RsAllocation *)_alloc; 1468 RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face; 1469 if (kLogApi) { 1470 ALOGD("nAllocation2DRead, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) " 1471 "type(%i)", (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType); 1472 } 1473 int count = w * h; 1474 PER_ARRAY_TYPE(0, rsAllocation2DRead, false, 1475 (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0); 1476} 1477 1478// Copies from the Allocation pointed to by _alloc into the Java object data. 1479static void 1480nAllocationRead3D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint zoff, jint lod, 1481 jint w, jint h, jint d, jobject data, int sizeBytes, int dataType, 1482 jint mSize, jboolean usePadding) 1483{ 1484 RsAllocation *alloc = (RsAllocation *)_alloc; 1485 if (kLogApi) { 1486 ALOGD("nAllocation3DRead, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), lod(%i), w(%i)," 1487 " h(%i), d(%i), sizeBytes(%i)", (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, 1488 lod, w, h, d, sizeBytes); 1489 } 1490 int count = w * h * d; 1491 PER_ARRAY_TYPE(nullptr, rsAllocation3DRead, false, 1492 (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0); 1493} 1494 1495static jlong 1496nAllocationGetType(JNIEnv *_env, jobject _this, jlong con, jlong a) 1497{ 1498 if (kLogApi) { 1499 ALOGD("nAllocationGetType, con(%p), a(%p)", (RsContext)con, (RsAllocation)a); 1500 } 1501 return (jlong)(uintptr_t) rsaAllocationGetType((RsContext)con, (RsAllocation)a); 1502} 1503 1504static void 1505nAllocationResize1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint dimX) 1506{ 1507 if (kLogApi) { 1508 ALOGD("nAllocationResize1D, con(%p), alloc(%p), sizeX(%i)", (RsContext)con, 1509 (RsAllocation)alloc, dimX); 1510 } 1511 rsAllocationResize1D((RsContext)con, (RsAllocation)alloc, dimX); 1512} 1513 1514 1515static jlong 1516nAllocationAdapterCreate(JNIEnv *_env, jobject _this, jlong con, jlong basealloc, jlong type) 1517{ 1518 if (kLogApi) { 1519 ALOGD("nAllocationAdapterCreate, con(%p), base(%p), type(%p)", 1520 (RsContext)con, (RsAllocation)basealloc, (RsElement)type); 1521 } 1522 return (jlong)(uintptr_t) rsAllocationAdapterCreate((RsContext)con, (RsType)type, 1523 (RsAllocation)basealloc); 1524 1525} 1526 1527static void 1528nAllocationAdapterOffset(JNIEnv *_env, jobject _this, jlong con, jlong alloc, 1529 jint x, jint y, jint z, jint face, jint lod, 1530 jint a1, jint a2, jint a3, jint a4) 1531{ 1532 uint32_t params[] = { 1533 (uint32_t)x, (uint32_t)y, (uint32_t)z, (uint32_t)face, 1534 (uint32_t)lod, (uint32_t)a1, (uint32_t)a2, (uint32_t)a3, (uint32_t)a4 1535 }; 1536 if (kLogApi) { 1537 ALOGD("nAllocationAdapterOffset, con(%p), alloc(%p), x(%i), y(%i), z(%i), face(%i), lod(%i), arrays(%i %i %i %i)", 1538 (RsContext)con, (RsAllocation)alloc, x, y, z, face, lod, a1, a2, a3, a4); 1539 } 1540 rsAllocationAdapterOffset((RsContext)con, (RsAllocation)alloc, 1541 params, sizeof(params)); 1542} 1543 1544 1545// ----------------------------------- 1546 1547static jlong 1548nFileA3DCreateFromAssetStream(JNIEnv *_env, jobject _this, jlong con, jlong native_asset) 1549{ 1550 Asset* asset = reinterpret_cast<Asset*>(native_asset); 1551 ALOGV("______nFileA3D %p", asset); 1552 1553 jlong id = (jlong)(uintptr_t)rsaFileA3DCreateFromMemory((RsContext)con, asset->getBuffer(false), asset->getLength()); 1554 return id; 1555} 1556 1557static jlong 1558nFileA3DCreateFromAsset(JNIEnv *_env, jobject _this, jlong con, jobject _assetMgr, jstring _path) 1559{ 1560 AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr); 1561 if (mgr == nullptr) { 1562 return 0; 1563 } 1564 1565 AutoJavaStringToUTF8 str(_env, _path); 1566 Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER); 1567 if (asset == nullptr) { 1568 return 0; 1569 } 1570 1571 jlong id = (jlong)(uintptr_t)rsaFileA3DCreateFromAsset((RsContext)con, asset); 1572 return id; 1573} 1574 1575static jlong 1576nFileA3DCreateFromFile(JNIEnv *_env, jobject _this, jlong con, jstring fileName) 1577{ 1578 AutoJavaStringToUTF8 fileNameUTF(_env, fileName); 1579 jlong id = (jlong)(uintptr_t)rsaFileA3DCreateFromFile((RsContext)con, fileNameUTF.c_str()); 1580 1581 return id; 1582} 1583 1584static jint 1585nFileA3DGetNumIndexEntries(JNIEnv *_env, jobject _this, jlong con, jlong fileA3D) 1586{ 1587 int32_t numEntries = 0; 1588 rsaFileA3DGetNumIndexEntries((RsContext)con, &numEntries, (RsFile)fileA3D); 1589 return (jint)numEntries; 1590} 1591 1592static void 1593nFileA3DGetIndexEntries(JNIEnv *_env, jobject _this, jlong con, jlong fileA3D, jint numEntries, jintArray _ids, jobjectArray _entries) 1594{ 1595 ALOGV("______nFileA3D %p", (RsFile) fileA3D); 1596 RsFileIndexEntry *fileEntries = (RsFileIndexEntry*)malloc((uint32_t)numEntries * sizeof(RsFileIndexEntry)); 1597 1598 rsaFileA3DGetIndexEntries((RsContext)con, fileEntries, (uint32_t)numEntries, (RsFile)fileA3D); 1599 1600 for(jint i = 0; i < numEntries; i ++) { 1601 _env->SetObjectArrayElement(_entries, i, _env->NewStringUTF(fileEntries[i].objectName)); 1602 _env->SetIntArrayRegion(_ids, i, 1, (const jint*)&fileEntries[i].classID); 1603 } 1604 1605 free(fileEntries); 1606} 1607 1608static jlong 1609nFileA3DGetEntryByIndex(JNIEnv *_env, jobject _this, jlong con, jlong fileA3D, jint index) 1610{ 1611 ALOGV("______nFileA3D %p", (RsFile) fileA3D); 1612 jlong id = (jlong)(uintptr_t)rsaFileA3DGetEntryByIndex((RsContext)con, (uint32_t)index, (RsFile)fileA3D); 1613 return id; 1614} 1615 1616// ----------------------------------- 1617 1618static jlong 1619nFontCreateFromFile(JNIEnv *_env, jobject _this, jlong con, 1620 jstring fileName, jfloat fontSize, jint dpi) 1621{ 1622 AutoJavaStringToUTF8 fileNameUTF(_env, fileName); 1623 jlong id = (jlong)(uintptr_t)rsFontCreateFromFile((RsContext)con, 1624 fileNameUTF.c_str(), fileNameUTF.length(), 1625 fontSize, dpi); 1626 1627 return id; 1628} 1629 1630static jlong 1631nFontCreateFromAssetStream(JNIEnv *_env, jobject _this, jlong con, 1632 jstring name, jfloat fontSize, jint dpi, jlong native_asset) 1633{ 1634 Asset* asset = reinterpret_cast<Asset*>(native_asset); 1635 AutoJavaStringToUTF8 nameUTF(_env, name); 1636 1637 jlong id = (jlong)(uintptr_t)rsFontCreateFromMemory((RsContext)con, 1638 nameUTF.c_str(), nameUTF.length(), 1639 fontSize, dpi, 1640 asset->getBuffer(false), asset->getLength()); 1641 return id; 1642} 1643 1644static jlong 1645nFontCreateFromAsset(JNIEnv *_env, jobject _this, jlong con, jobject _assetMgr, jstring _path, 1646 jfloat fontSize, jint dpi) 1647{ 1648 AssetManager* mgr = assetManagerForJavaObject(_env, _assetMgr); 1649 if (mgr == nullptr) { 1650 return 0; 1651 } 1652 1653 AutoJavaStringToUTF8 str(_env, _path); 1654 Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER); 1655 if (asset == nullptr) { 1656 return 0; 1657 } 1658 1659 jlong id = (jlong)(uintptr_t)rsFontCreateFromMemory((RsContext)con, 1660 str.c_str(), str.length(), 1661 fontSize, dpi, 1662 asset->getBuffer(false), asset->getLength()); 1663 delete asset; 1664 return id; 1665} 1666 1667// ----------------------------------- 1668 1669static void 1670nScriptBindAllocation(JNIEnv *_env, jobject _this, jlong con, jlong script, jlong alloc, jint slot) 1671{ 1672 if (kLogApi) { 1673 ALOGD("nScriptBindAllocation, con(%p), script(%p), alloc(%p), slot(%i)", (RsContext)con, 1674 (RsScript)script, (RsAllocation)alloc, slot); 1675 } 1676 rsScriptBindAllocation((RsContext)con, (RsScript)script, (RsAllocation)alloc, slot); 1677} 1678 1679static void 1680nScriptSetVarI(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jint val) 1681{ 1682 if (kLogApi) { 1683 ALOGD("nScriptSetVarI, con(%p), s(%p), slot(%i), val(%i)", (RsContext)con, (void *)script, 1684 slot, val); 1685 } 1686 rsScriptSetVarI((RsContext)con, (RsScript)script, slot, val); 1687} 1688 1689static jint 1690nScriptGetVarI(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot) 1691{ 1692 if (kLogApi) { 1693 ALOGD("nScriptGetVarI, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot); 1694 } 1695 int value = 0; 1696 rsScriptGetVarV((RsContext)con, (RsScript)script, slot, &value, sizeof(value)); 1697 return value; 1698} 1699 1700static void 1701nScriptSetVarObj(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jlong val) 1702{ 1703 if (kLogApi) { 1704 ALOGD("nScriptSetVarObj, con(%p), s(%p), slot(%i), val(%" PRId64 ")", (RsContext)con, (void *)script, 1705 slot, val); 1706 } 1707 rsScriptSetVarObj((RsContext)con, (RsScript)script, slot, (RsObjectBase)val); 1708} 1709 1710static void 1711nScriptSetVarJ(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jlong val) 1712{ 1713 if (kLogApi) { 1714 ALOGD("nScriptSetVarJ, con(%p), s(%p), slot(%i), val(%" PRId64 ")", (RsContext)con, (void *)script, 1715 slot, val); 1716 } 1717 rsScriptSetVarJ((RsContext)con, (RsScript)script, slot, val); 1718} 1719 1720static jlong 1721nScriptGetVarJ(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot) 1722{ 1723 if (kLogApi) { 1724 ALOGD("nScriptGetVarJ, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot); 1725 } 1726 jlong value = 0; 1727 rsScriptGetVarV((RsContext)con, (RsScript)script, slot, &value, sizeof(value)); 1728 return value; 1729} 1730 1731static void 1732nScriptSetVarF(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, float val) 1733{ 1734 if (kLogApi) { 1735 ALOGD("nScriptSetVarF, con(%p), s(%p), slot(%i), val(%f)", (RsContext)con, (void *)script, 1736 slot, val); 1737 } 1738 rsScriptSetVarF((RsContext)con, (RsScript)script, slot, val); 1739} 1740 1741static jfloat 1742nScriptGetVarF(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot) 1743{ 1744 if (kLogApi) { 1745 ALOGD("nScriptGetVarF, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot); 1746 } 1747 jfloat value = 0; 1748 rsScriptGetVarV((RsContext)con, (RsScript)script, slot, &value, sizeof(value)); 1749 return value; 1750} 1751 1752static void 1753nScriptSetVarD(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, double val) 1754{ 1755 if (kLogApi) { 1756 ALOGD("nScriptSetVarD, con(%p), s(%p), slot(%i), val(%lf)", (RsContext)con, (void *)script, 1757 slot, val); 1758 } 1759 rsScriptSetVarD((RsContext)con, (RsScript)script, slot, val); 1760} 1761 1762static jdouble 1763nScriptGetVarD(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot) 1764{ 1765 if (kLogApi) { 1766 ALOGD("nScriptGetVarD, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot); 1767 } 1768 jdouble value = 0; 1769 rsScriptGetVarV((RsContext)con, (RsScript)script, slot, &value, sizeof(value)); 1770 return value; 1771} 1772 1773static void 1774nScriptSetVarV(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data) 1775{ 1776 if (kLogApi) { 1777 ALOGD("nScriptSetVarV, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot); 1778 } 1779 jint len = _env->GetArrayLength(data); 1780 jbyte *ptr = _env->GetByteArrayElements(data, nullptr); 1781 rsScriptSetVarV((RsContext)con, (RsScript)script, slot, ptr, len); 1782 _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT); 1783} 1784 1785static void 1786nScriptGetVarV(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data) 1787{ 1788 if (kLogApi) { 1789 ALOGD("nScriptSetVarV, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot); 1790 } 1791 jint len = _env->GetArrayLength(data); 1792 jbyte *ptr = _env->GetByteArrayElements(data, nullptr); 1793 rsScriptGetVarV((RsContext)con, (RsScript)script, slot, ptr, len); 1794 _env->ReleaseByteArrayElements(data, ptr, 0); 1795} 1796 1797static void 1798nScriptSetVarVE(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data, 1799 jlong elem, jintArray dims) 1800{ 1801 if (kLogApi) { 1802 ALOGD("nScriptSetVarVE, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot); 1803 } 1804 jint len = _env->GetArrayLength(data); 1805 jbyte *ptr = _env->GetByteArrayElements(data, nullptr); 1806 jint dimsLen = _env->GetArrayLength(dims) * sizeof(int); 1807 jint *dimsPtr = _env->GetIntArrayElements(dims, nullptr); 1808 rsScriptSetVarVE((RsContext)con, (RsScript)script, slot, ptr, len, (RsElement)elem, 1809 (const uint32_t*) dimsPtr, dimsLen); 1810 _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT); 1811 _env->ReleaseIntArrayElements(dims, dimsPtr, JNI_ABORT); 1812} 1813 1814 1815static void 1816nScriptSetTimeZone(JNIEnv *_env, jobject _this, jlong con, jlong script, jbyteArray timeZone) 1817{ 1818 if (kLogApi) { 1819 ALOGD("nScriptCSetTimeZone, con(%p), s(%p)", (RsContext)con, (void *)script); 1820 } 1821 1822 jint length = _env->GetArrayLength(timeZone); 1823 jbyte* timeZone_ptr; 1824 timeZone_ptr = (jbyte *) _env->GetPrimitiveArrayCritical(timeZone, (jboolean *)0); 1825 1826 rsScriptSetTimeZone((RsContext)con, (RsScript)script, (const char *)timeZone_ptr, length); 1827 1828 if (timeZone_ptr) { 1829 _env->ReleasePrimitiveArrayCritical(timeZone, timeZone_ptr, 0); 1830 } 1831} 1832 1833static void 1834nScriptInvoke(JNIEnv *_env, jobject _this, jlong con, jlong obj, jint slot) 1835{ 1836 if (kLogApi) { 1837 ALOGD("nScriptInvoke, con(%p), script(%p)", (RsContext)con, (void *)obj); 1838 } 1839 rsScriptInvoke((RsContext)con, (RsScript)obj, slot); 1840} 1841 1842static void 1843nScriptInvokeV(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, jbyteArray data) 1844{ 1845 if (kLogApi) { 1846 ALOGD("nScriptInvokeV, con(%p), s(%p), slot(%i)", (RsContext)con, (void *)script, slot); 1847 } 1848 jint len = _env->GetArrayLength(data); 1849 jbyte *ptr = _env->GetByteArrayElements(data, nullptr); 1850 rsScriptInvokeV((RsContext)con, (RsScript)script, slot, ptr, len); 1851 _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT); 1852} 1853 1854static void 1855nScriptForEach(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot, 1856 jlongArray ains, jlong aout, jbyteArray params, 1857 jintArray limits) 1858{ 1859 if (kLogApi) { 1860 ALOGD("nScriptForEach, con(%p), s(%p), slot(%i) ains(%p) aout(%" PRId64 ")", (RsContext)con, (void *)script, slot, ains, aout); 1861 } 1862 1863 jint in_len = 0; 1864 jlong *in_ptr = nullptr; 1865 1866 RsAllocation *in_allocs = nullptr; 1867 1868 if (ains != nullptr) { 1869 in_len = _env->GetArrayLength(ains); 1870 if (in_len > (jint)kMaxNumberKernelArguments) { 1871 ALOGE("Too many arguments in kernel launch."); 1872 // TODO (b/20758983): Report back to Java and throw an exception 1873 return; 1874 } 1875 1876 // TODO (b/20760800): Check in_ptr is not null 1877 in_ptr = _env->GetLongArrayElements(ains, nullptr); 1878 if (sizeof(RsAllocation) == sizeof(jlong)) { 1879 in_allocs = (RsAllocation*)in_ptr; 1880 1881 } else { 1882 // Convert from 64-bit jlong types to the native pointer type. 1883 1884 in_allocs = (RsAllocation*)alloca(in_len * sizeof(RsAllocation)); 1885 if (in_allocs == nullptr) { 1886 ALOGE("Failed launching kernel for lack of memory."); 1887 _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT); 1888 return; 1889 } 1890 1891 for (int index = in_len; --index >= 0;) { 1892 in_allocs[index] = (RsAllocation)in_ptr[index]; 1893 } 1894 } 1895 } 1896 1897 jint param_len = 0; 1898 jbyte *param_ptr = nullptr; 1899 1900 if (params != nullptr) { 1901 param_len = _env->GetArrayLength(params); 1902 param_ptr = _env->GetByteArrayElements(params, nullptr); 1903 } 1904 1905 RsScriptCall sc, *sca = nullptr; 1906 uint32_t sc_size = 0; 1907 1908 jint limit_len = 0; 1909 jint *limit_ptr = nullptr; 1910 1911 if (limits != nullptr) { 1912 limit_len = _env->GetArrayLength(limits); 1913 limit_ptr = _env->GetIntArrayElements(limits, nullptr); 1914 1915 assert(limit_len == 6); 1916 UNUSED(limit_len); // As the assert might not be compiled. 1917 1918 sc.xStart = limit_ptr[0]; 1919 sc.xEnd = limit_ptr[1]; 1920 sc.yStart = limit_ptr[2]; 1921 sc.yEnd = limit_ptr[3]; 1922 sc.zStart = limit_ptr[4]; 1923 sc.zEnd = limit_ptr[5]; 1924 sc.strategy = RS_FOR_EACH_STRATEGY_DONT_CARE; 1925 sc.arrayStart = 0; 1926 sc.arrayEnd = 0; 1927 sc.array2Start = 0; 1928 sc.array2End = 0; 1929 sc.array3Start = 0; 1930 sc.array3End = 0; 1931 sc.array4Start = 0; 1932 sc.array4End = 0; 1933 1934 sca = ≻ 1935 } 1936 1937 rsScriptForEachMulti((RsContext)con, (RsScript)script, slot, 1938 in_allocs, in_len, (RsAllocation)aout, 1939 param_ptr, param_len, sca, sc_size); 1940 1941 if (ains != nullptr) { 1942 _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT); 1943 } 1944 1945 if (params != nullptr) { 1946 _env->ReleaseByteArrayElements(params, param_ptr, JNI_ABORT); 1947 } 1948 1949 if (limits != nullptr) { 1950 _env->ReleaseIntArrayElements(limits, limit_ptr, JNI_ABORT); 1951 } 1952} 1953 1954// ----------------------------------- 1955 1956static jlong 1957nScriptCCreate(JNIEnv *_env, jobject _this, jlong con, 1958 jstring resName, jstring cacheDir, 1959 jbyteArray scriptRef, jint length) 1960{ 1961 if (kLogApi) { 1962 ALOGD("nScriptCCreate, con(%p)", (RsContext)con); 1963 } 1964 1965 AutoJavaStringToUTF8 resNameUTF(_env, resName); 1966 AutoJavaStringToUTF8 cacheDirUTF(_env, cacheDir); 1967 jlong ret = 0; 1968 jbyte* script_ptr = nullptr; 1969 jint _exception = 0; 1970 jint remaining; 1971 if (!scriptRef) { 1972 _exception = 1; 1973 //jniThrowException(_env, "java/lang/IllegalArgumentException", "script == null"); 1974 goto exit; 1975 } 1976 if (length < 0) { 1977 _exception = 1; 1978 //jniThrowException(_env, "java/lang/IllegalArgumentException", "length < 0"); 1979 goto exit; 1980 } 1981 remaining = _env->GetArrayLength(scriptRef); 1982 if (remaining < length) { 1983 _exception = 1; 1984 //jniThrowException(_env, "java/lang/IllegalArgumentException", 1985 // "length > script.length - offset"); 1986 goto exit; 1987 } 1988 script_ptr = (jbyte *) 1989 _env->GetPrimitiveArrayCritical(scriptRef, (jboolean *)0); 1990 1991 //rsScriptCSetText((RsContext)con, (const char *)script_ptr, length); 1992 1993 ret = (jlong)(uintptr_t)rsScriptCCreate((RsContext)con, 1994 resNameUTF.c_str(), resNameUTF.length(), 1995 cacheDirUTF.c_str(), cacheDirUTF.length(), 1996 (const char *)script_ptr, length); 1997 1998exit: 1999 if (script_ptr) { 2000 _env->ReleasePrimitiveArrayCritical(scriptRef, script_ptr, 2001 _exception ? JNI_ABORT: 0); 2002 } 2003 2004 return (jlong)(uintptr_t)ret; 2005} 2006 2007static jlong 2008nScriptIntrinsicCreate(JNIEnv *_env, jobject _this, jlong con, jint id, jlong eid) 2009{ 2010 if (kLogApi) { 2011 ALOGD("nScriptIntrinsicCreate, con(%p) id(%i) element(%p)", (RsContext)con, id, 2012 (void *)eid); 2013 } 2014 return (jlong)(uintptr_t)rsScriptIntrinsicCreate((RsContext)con, id, (RsElement)eid); 2015} 2016 2017static jlong 2018nScriptKernelIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot, jint sig) 2019{ 2020 if (kLogApi) { 2021 ALOGD("nScriptKernelIDCreate, con(%p) script(%p), slot(%i), sig(%i)", (RsContext)con, 2022 (void *)sid, slot, sig); 2023 } 2024 return (jlong)(uintptr_t)rsScriptKernelIDCreate((RsContext)con, (RsScript)sid, slot, sig); 2025} 2026 2027static jlong 2028nScriptInvokeIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot) 2029{ 2030 if (kLogApi) { 2031 ALOGD("nScriptInvokeIDCreate, con(%p) script(%p), slot(%i)", (RsContext)con, 2032 (void *)sid, slot); 2033 } 2034 return (jlong)(uintptr_t)rsScriptInvokeIDCreate((RsContext)con, (RsScript)sid, slot); 2035} 2036 2037static jlong 2038nScriptFieldIDCreate(JNIEnv *_env, jobject _this, jlong con, jlong sid, jint slot) 2039{ 2040 if (kLogApi) { 2041 ALOGD("nScriptFieldIDCreate, con(%p) script(%p), slot(%i)", (RsContext)con, (void *)sid, 2042 slot); 2043 } 2044 return (jlong)(uintptr_t)rsScriptFieldIDCreate((RsContext)con, (RsScript)sid, slot); 2045} 2046 2047static jlong 2048nScriptGroupCreate(JNIEnv *_env, jobject _this, jlong con, jlongArray _kernels, jlongArray _src, 2049 jlongArray _dstk, jlongArray _dstf, jlongArray _types) 2050{ 2051 if (kLogApi) { 2052 ALOGD("nScriptGroupCreate, con(%p)", (RsContext)con); 2053 } 2054 2055 jint kernelsLen = _env->GetArrayLength(_kernels); 2056 jlong *jKernelsPtr = _env->GetLongArrayElements(_kernels, nullptr); 2057 RsScriptKernelID* kernelsPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * kernelsLen); 2058 for(int i = 0; i < kernelsLen; ++i) { 2059 kernelsPtr[i] = (RsScriptKernelID)jKernelsPtr[i]; 2060 } 2061 2062 jint srcLen = _env->GetArrayLength(_src); 2063 jlong *jSrcPtr = _env->GetLongArrayElements(_src, nullptr); 2064 RsScriptKernelID* srcPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * srcLen); 2065 for(int i = 0; i < srcLen; ++i) { 2066 srcPtr[i] = (RsScriptKernelID)jSrcPtr[i]; 2067 } 2068 2069 jint dstkLen = _env->GetArrayLength(_dstk); 2070 jlong *jDstkPtr = _env->GetLongArrayElements(_dstk, nullptr); 2071 RsScriptKernelID* dstkPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstkLen); 2072 for(int i = 0; i < dstkLen; ++i) { 2073 dstkPtr[i] = (RsScriptKernelID)jDstkPtr[i]; 2074 } 2075 2076 jint dstfLen = _env->GetArrayLength(_dstf); 2077 jlong *jDstfPtr = _env->GetLongArrayElements(_dstf, nullptr); 2078 RsScriptKernelID* dstfPtr = (RsScriptKernelID*) malloc(sizeof(RsScriptKernelID) * dstfLen); 2079 for(int i = 0; i < dstfLen; ++i) { 2080 dstfPtr[i] = (RsScriptKernelID)jDstfPtr[i]; 2081 } 2082 2083 jint typesLen = _env->GetArrayLength(_types); 2084 jlong *jTypesPtr = _env->GetLongArrayElements(_types, nullptr); 2085 RsType* typesPtr = (RsType*) malloc(sizeof(RsType) * typesLen); 2086 for(int i = 0; i < typesLen; ++i) { 2087 typesPtr[i] = (RsType)jTypesPtr[i]; 2088 } 2089 2090 jlong id = (jlong)(uintptr_t)rsScriptGroupCreate((RsContext)con, 2091 (RsScriptKernelID *)kernelsPtr, kernelsLen * sizeof(RsScriptKernelID), 2092 (RsScriptKernelID *)srcPtr, srcLen * sizeof(RsScriptKernelID), 2093 (RsScriptKernelID *)dstkPtr, dstkLen * sizeof(RsScriptKernelID), 2094 (RsScriptFieldID *)dstfPtr, dstfLen * sizeof(RsScriptKernelID), 2095 (RsType *)typesPtr, typesLen * sizeof(RsType)); 2096 2097 free(kernelsPtr); 2098 free(srcPtr); 2099 free(dstkPtr); 2100 free(dstfPtr); 2101 free(typesPtr); 2102 _env->ReleaseLongArrayElements(_kernels, jKernelsPtr, 0); 2103 _env->ReleaseLongArrayElements(_src, jSrcPtr, 0); 2104 _env->ReleaseLongArrayElements(_dstk, jDstkPtr, 0); 2105 _env->ReleaseLongArrayElements(_dstf, jDstfPtr, 0); 2106 _env->ReleaseLongArrayElements(_types, jTypesPtr, 0); 2107 return id; 2108} 2109 2110static void 2111nScriptGroupSetInput(JNIEnv *_env, jobject _this, jlong con, jlong gid, jlong kid, jlong alloc) 2112{ 2113 if (kLogApi) { 2114 ALOGD("nScriptGroupSetInput, con(%p) group(%p), kernelId(%p), alloc(%p)", (RsContext)con, 2115 (void *)gid, (void *)kid, (void *)alloc); 2116 } 2117 rsScriptGroupSetInput((RsContext)con, (RsScriptGroup)gid, (RsScriptKernelID)kid, (RsAllocation)alloc); 2118} 2119 2120static void 2121nScriptGroupSetOutput(JNIEnv *_env, jobject _this, jlong con, jlong gid, jlong kid, jlong alloc) 2122{ 2123 if (kLogApi) { 2124 ALOGD("nScriptGroupSetOutput, con(%p) group(%p), kernelId(%p), alloc(%p)", (RsContext)con, 2125 (void *)gid, (void *)kid, (void *)alloc); 2126 } 2127 rsScriptGroupSetOutput((RsContext)con, (RsScriptGroup)gid, (RsScriptKernelID)kid, (RsAllocation)alloc); 2128} 2129 2130static void 2131nScriptGroupExecute(JNIEnv *_env, jobject _this, jlong con, jlong gid) 2132{ 2133 if (kLogApi) { 2134 ALOGD("nScriptGroupSetOutput, con(%p) group(%p)", (RsContext)con, (void *)gid); 2135 } 2136 rsScriptGroupExecute((RsContext)con, (RsScriptGroup)gid); 2137} 2138 2139// --------------------------------------------------------------------------- 2140 2141static jlong 2142nProgramStoreCreate(JNIEnv *_env, jobject _this, jlong con, 2143 jboolean colorMaskR, jboolean colorMaskG, jboolean colorMaskB, jboolean colorMaskA, 2144 jboolean depthMask, jboolean ditherEnable, 2145 jint srcFunc, jint destFunc, 2146 jint depthFunc) 2147{ 2148 if (kLogApi) { 2149 ALOGD("nProgramStoreCreate, con(%p)", (RsContext)con); 2150 } 2151 return (jlong)(uintptr_t)rsProgramStoreCreate((RsContext)con, colorMaskR, colorMaskG, colorMaskB, colorMaskA, 2152 depthMask, ditherEnable, (RsBlendSrcFunc)srcFunc, 2153 (RsBlendDstFunc)destFunc, (RsDepthFunc)depthFunc); 2154} 2155 2156// --------------------------------------------------------------------------- 2157 2158static void 2159nProgramBindConstants(JNIEnv *_env, jobject _this, jlong con, jlong vpv, jint slot, jlong a) 2160{ 2161 if (kLogApi) { 2162 ALOGD("nProgramBindConstants, con(%p), vpf(%p), sloat(%i), a(%p)", (RsContext)con, 2163 (RsProgramVertex)vpv, slot, (RsAllocation)a); 2164 } 2165 rsProgramBindConstants((RsContext)con, (RsProgram)vpv, slot, (RsAllocation)a); 2166} 2167 2168static void 2169nProgramBindTexture(JNIEnv *_env, jobject _this, jlong con, jlong vpf, jint slot, jlong a) 2170{ 2171 if (kLogApi) { 2172 ALOGD("nProgramBindTexture, con(%p), vpf(%p), slot(%i), a(%p)", (RsContext)con, 2173 (RsProgramFragment)vpf, slot, (RsAllocation)a); 2174 } 2175 rsProgramBindTexture((RsContext)con, (RsProgramFragment)vpf, slot, (RsAllocation)a); 2176} 2177 2178static void 2179nProgramBindSampler(JNIEnv *_env, jobject _this, jlong con, jlong vpf, jint slot, jlong a) 2180{ 2181 if (kLogApi) { 2182 ALOGD("nProgramBindSampler, con(%p), vpf(%p), slot(%i), a(%p)", (RsContext)con, 2183 (RsProgramFragment)vpf, slot, (RsSampler)a); 2184 } 2185 rsProgramBindSampler((RsContext)con, (RsProgramFragment)vpf, slot, (RsSampler)a); 2186} 2187 2188// --------------------------------------------------------------------------- 2189 2190static jlong 2191nProgramFragmentCreate(JNIEnv *_env, jobject _this, jlong con, jstring shader, 2192 jobjectArray texNames, jlongArray params) 2193{ 2194 AutoJavaStringToUTF8 shaderUTF(_env, shader); 2195 jlong *jParamPtr = _env->GetLongArrayElements(params, nullptr); 2196 jint paramLen = _env->GetArrayLength(params); 2197 2198 int texCount = _env->GetArrayLength(texNames); 2199 AutoJavaStringArrayToUTF8 names(_env, texNames, texCount); 2200 const char ** nameArray = names.c_str(); 2201 size_t* sizeArray = names.c_str_len(); 2202 2203 if (kLogApi) { 2204 ALOGD("nProgramFragmentCreate, con(%p), paramLen(%i)", (RsContext)con, paramLen); 2205 } 2206 2207 uintptr_t * paramPtr = (uintptr_t*) malloc(sizeof(uintptr_t) * paramLen); 2208 for(int i = 0; i < paramLen; ++i) { 2209 paramPtr[i] = (uintptr_t)jParamPtr[i]; 2210 } 2211 jlong ret = (jlong)(uintptr_t)rsProgramFragmentCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(), 2212 nameArray, texCount, sizeArray, 2213 paramPtr, paramLen); 2214 2215 free(paramPtr); 2216 _env->ReleaseLongArrayElements(params, jParamPtr, JNI_ABORT); 2217 return ret; 2218} 2219 2220 2221// --------------------------------------------------------------------------- 2222 2223static jlong 2224nProgramVertexCreate(JNIEnv *_env, jobject _this, jlong con, jstring shader, 2225 jobjectArray texNames, jlongArray params) 2226{ 2227 AutoJavaStringToUTF8 shaderUTF(_env, shader); 2228 jlong *jParamPtr = _env->GetLongArrayElements(params, nullptr); 2229 jint paramLen = _env->GetArrayLength(params); 2230 2231 if (kLogApi) { 2232 ALOGD("nProgramVertexCreate, con(%p), paramLen(%i)", (RsContext)con, paramLen); 2233 } 2234 2235 int texCount = _env->GetArrayLength(texNames); 2236 AutoJavaStringArrayToUTF8 names(_env, texNames, texCount); 2237 const char ** nameArray = names.c_str(); 2238 size_t* sizeArray = names.c_str_len(); 2239 2240 uintptr_t * paramPtr = (uintptr_t*) malloc(sizeof(uintptr_t) * paramLen); 2241 for(int i = 0; i < paramLen; ++i) { 2242 paramPtr[i] = (uintptr_t)jParamPtr[i]; 2243 } 2244 2245 jlong ret = (jlong)(uintptr_t)rsProgramVertexCreate((RsContext)con, shaderUTF.c_str(), shaderUTF.length(), 2246 nameArray, texCount, sizeArray, 2247 paramPtr, paramLen); 2248 2249 free(paramPtr); 2250 _env->ReleaseLongArrayElements(params, jParamPtr, JNI_ABORT); 2251 return ret; 2252} 2253 2254// --------------------------------------------------------------------------- 2255 2256static jlong 2257nProgramRasterCreate(JNIEnv *_env, jobject _this, jlong con, jboolean pointSprite, jint cull) 2258{ 2259 if (kLogApi) { 2260 ALOGD("nProgramRasterCreate, con(%p), pointSprite(%i), cull(%i)", (RsContext)con, 2261 pointSprite, cull); 2262 } 2263 return (jlong)(uintptr_t)rsProgramRasterCreate((RsContext)con, pointSprite, (RsCullMode)cull); 2264} 2265 2266 2267// --------------------------------------------------------------------------- 2268 2269static void 2270nContextBindRootScript(JNIEnv *_env, jobject _this, jlong con, jlong script) 2271{ 2272 if (kLogApi) { 2273 ALOGD("nContextBindRootScript, con(%p), script(%p)", (RsContext)con, (RsScript)script); 2274 } 2275 rsContextBindRootScript((RsContext)con, (RsScript)script); 2276} 2277 2278static void 2279nContextBindProgramStore(JNIEnv *_env, jobject _this, jlong con, jlong pfs) 2280{ 2281 if (kLogApi) { 2282 ALOGD("nContextBindProgramStore, con(%p), pfs(%p)", (RsContext)con, (RsProgramStore)pfs); 2283 } 2284 rsContextBindProgramStore((RsContext)con, (RsProgramStore)pfs); 2285} 2286 2287static void 2288nContextBindProgramFragment(JNIEnv *_env, jobject _this, jlong con, jlong pf) 2289{ 2290 if (kLogApi) { 2291 ALOGD("nContextBindProgramFragment, con(%p), pf(%p)", (RsContext)con, 2292 (RsProgramFragment)pf); 2293 } 2294 rsContextBindProgramFragment((RsContext)con, (RsProgramFragment)pf); 2295} 2296 2297static void 2298nContextBindProgramVertex(JNIEnv *_env, jobject _this, jlong con, jlong pf) 2299{ 2300 if (kLogApi) { 2301 ALOGD("nContextBindProgramVertex, con(%p), pf(%p)", (RsContext)con, (RsProgramVertex)pf); 2302 } 2303 rsContextBindProgramVertex((RsContext)con, (RsProgramVertex)pf); 2304} 2305 2306static void 2307nContextBindProgramRaster(JNIEnv *_env, jobject _this, jlong con, jlong pf) 2308{ 2309 if (kLogApi) { 2310 ALOGD("nContextBindProgramRaster, con(%p), pf(%p)", (RsContext)con, (RsProgramRaster)pf); 2311 } 2312 rsContextBindProgramRaster((RsContext)con, (RsProgramRaster)pf); 2313} 2314 2315 2316// --------------------------------------------------------------------------- 2317 2318static jlong 2319nSamplerCreate(JNIEnv *_env, jobject _this, jlong con, jint magFilter, jint minFilter, 2320 jint wrapS, jint wrapT, jint wrapR, jfloat aniso) 2321{ 2322 if (kLogApi) { 2323 ALOGD("nSamplerCreate, con(%p)", (RsContext)con); 2324 } 2325 return (jlong)(uintptr_t)rsSamplerCreate((RsContext)con, 2326 (RsSamplerValue)magFilter, 2327 (RsSamplerValue)minFilter, 2328 (RsSamplerValue)wrapS, 2329 (RsSamplerValue)wrapT, 2330 (RsSamplerValue)wrapR, 2331 aniso); 2332} 2333 2334// --------------------------------------------------------------------------- 2335 2336static jlong 2337nMeshCreate(JNIEnv *_env, jobject _this, jlong con, jlongArray _vtx, jlongArray _idx, jintArray _prim) 2338{ 2339 if (kLogApi) { 2340 ALOGD("nMeshCreate, con(%p)", (RsContext)con); 2341 } 2342 2343 jint vtxLen = _env->GetArrayLength(_vtx); 2344 jlong *jVtxPtr = _env->GetLongArrayElements(_vtx, nullptr); 2345 RsAllocation* vtxPtr = (RsAllocation*) malloc(sizeof(RsAllocation) * vtxLen); 2346 for(int i = 0; i < vtxLen; ++i) { 2347 vtxPtr[i] = (RsAllocation)(uintptr_t)jVtxPtr[i]; 2348 } 2349 2350 jint idxLen = _env->GetArrayLength(_idx); 2351 jlong *jIdxPtr = _env->GetLongArrayElements(_idx, nullptr); 2352 RsAllocation* idxPtr = (RsAllocation*) malloc(sizeof(RsAllocation) * idxLen); 2353 for(int i = 0; i < idxLen; ++i) { 2354 idxPtr[i] = (RsAllocation)(uintptr_t)jIdxPtr[i]; 2355 } 2356 2357 jint primLen = _env->GetArrayLength(_prim); 2358 jint *primPtr = _env->GetIntArrayElements(_prim, nullptr); 2359 2360 jlong id = (jlong)(uintptr_t)rsMeshCreate((RsContext)con, 2361 (RsAllocation *)vtxPtr, vtxLen, 2362 (RsAllocation *)idxPtr, idxLen, 2363 (uint32_t *)primPtr, primLen); 2364 2365 free(vtxPtr); 2366 free(idxPtr); 2367 _env->ReleaseLongArrayElements(_vtx, jVtxPtr, 0); 2368 _env->ReleaseLongArrayElements(_idx, jIdxPtr, 0); 2369 _env->ReleaseIntArrayElements(_prim, primPtr, 0); 2370 return id; 2371} 2372 2373static jint 2374nMeshGetVertexBufferCount(JNIEnv *_env, jobject _this, jlong con, jlong mesh) 2375{ 2376 if (kLogApi) { 2377 ALOGD("nMeshGetVertexBufferCount, con(%p), Mesh(%p)", (RsContext)con, (RsMesh)mesh); 2378 } 2379 jint vtxCount = 0; 2380 rsaMeshGetVertexBufferCount((RsContext)con, (RsMesh)mesh, &vtxCount); 2381 return vtxCount; 2382} 2383 2384static jint 2385nMeshGetIndexCount(JNIEnv *_env, jobject _this, jlong con, jlong mesh) 2386{ 2387 if (kLogApi) { 2388 ALOGD("nMeshGetIndexCount, con(%p), Mesh(%p)", (RsContext)con, (RsMesh)mesh); 2389 } 2390 jint idxCount = 0; 2391 rsaMeshGetIndexCount((RsContext)con, (RsMesh)mesh, &idxCount); 2392 return idxCount; 2393} 2394 2395static void 2396nMeshGetVertices(JNIEnv *_env, jobject _this, jlong con, jlong mesh, jlongArray _ids, jint numVtxIDs) 2397{ 2398 if (kLogApi) { 2399 ALOGD("nMeshGetVertices, con(%p), Mesh(%p)", (RsContext)con, (RsMesh)mesh); 2400 } 2401 2402 RsAllocation *allocs = (RsAllocation*)malloc((uint32_t)numVtxIDs * sizeof(RsAllocation)); 2403 rsaMeshGetVertices((RsContext)con, (RsMesh)mesh, allocs, (uint32_t)numVtxIDs); 2404 2405 for(jint i = 0; i < numVtxIDs; i ++) { 2406 const jlong alloc = (jlong)(uintptr_t)allocs[i]; 2407 _env->SetLongArrayRegion(_ids, i, 1, &alloc); 2408 } 2409 2410 free(allocs); 2411} 2412 2413static void 2414nMeshGetIndices(JNIEnv *_env, jobject _this, jlong con, jlong mesh, jlongArray _idxIds, jintArray _primitives, jint numIndices) 2415{ 2416 if (kLogApi) { 2417 ALOGD("nMeshGetVertices, con(%p), Mesh(%p)", (RsContext)con, (RsMesh)mesh); 2418 } 2419 2420 RsAllocation *allocs = (RsAllocation*)malloc((uint32_t)numIndices * sizeof(RsAllocation)); 2421 uint32_t *prims= (uint32_t*)malloc((uint32_t)numIndices * sizeof(uint32_t)); 2422 2423 rsaMeshGetIndices((RsContext)con, (RsMesh)mesh, allocs, prims, (uint32_t)numIndices); 2424 2425 for(jint i = 0; i < numIndices; i ++) { 2426 const jlong alloc = (jlong)(uintptr_t)allocs[i]; 2427 const jint prim = (jint)prims[i]; 2428 _env->SetLongArrayRegion(_idxIds, i, 1, &alloc); 2429 _env->SetIntArrayRegion(_primitives, i, 1, &prim); 2430 } 2431 2432 free(allocs); 2433 free(prims); 2434} 2435 2436static jint 2437nSystemGetPointerSize(JNIEnv *_env, jobject _this) { 2438 return (jint)sizeof(void*); 2439} 2440 2441 2442// --------------------------------------------------------------------------- 2443 2444 2445static const char *classPathName = "android/renderscript/RenderScript"; 2446 2447static JNINativeMethod methods[] = { 2448{"_nInit", "()V", (void*)_nInit }, 2449 2450{"nDeviceCreate", "()J", (void*)nDeviceCreate }, 2451{"nDeviceDestroy", "(J)V", (void*)nDeviceDestroy }, 2452{"nDeviceSetConfig", "(JII)V", (void*)nDeviceSetConfig }, 2453{"nContextGetUserMessage", "(J[I)I", (void*)nContextGetUserMessage }, 2454{"nContextGetErrorMessage", "(J)Ljava/lang/String;", (void*)nContextGetErrorMessage }, 2455{"nContextPeekMessage", "(J[I)I", (void*)nContextPeekMessage }, 2456 2457{"nContextInitToClient", "(J)V", (void*)nContextInitToClient }, 2458{"nContextDeinitToClient", "(J)V", (void*)nContextDeinitToClient }, 2459 2460 2461// All methods below are thread protected in java. 2462{"rsnContextCreate", "(JIII)J", (void*)nContextCreate }, 2463{"rsnContextCreateGL", "(JIIIIIIIIIIIIFI)J", (void*)nContextCreateGL }, 2464{"rsnContextFinish", "(J)V", (void*)nContextFinish }, 2465{"rsnContextSetPriority", "(JI)V", (void*)nContextSetPriority }, 2466{"rsnContextSetCacheDir", "(JLjava/lang/String;)V", (void*)nContextSetCacheDir }, 2467{"rsnContextSetSurface", "(JIILandroid/view/Surface;)V", (void*)nContextSetSurface }, 2468{"rsnContextDestroy", "(J)V", (void*)nContextDestroy }, 2469{"rsnContextDump", "(JI)V", (void*)nContextDump }, 2470{"rsnContextPause", "(J)V", (void*)nContextPause }, 2471{"rsnContextResume", "(J)V", (void*)nContextResume }, 2472{"rsnContextSendMessage", "(JI[I)V", (void*)nContextSendMessage }, 2473{"rsnClosureCreate", "(JJJ[J[J[I[J[J)J", (void*)nClosureCreate }, 2474{"rsnInvokeClosureCreate", "(JJ[B[J[J[I)J", (void*)nInvokeClosureCreate }, 2475{"rsnClosureSetArg", "(JJIJI)V", (void*)nClosureSetArg }, 2476{"rsnClosureSetGlobal", "(JJJJI)V", (void*)nClosureSetGlobal }, 2477{"rsnAssignName", "(JJ[B)V", (void*)nAssignName }, 2478{"rsnGetName", "(JJ)Ljava/lang/String;", (void*)nGetName }, 2479{"rsnObjDestroy", "(JJ)V", (void*)nObjDestroy }, 2480 2481{"rsnFileA3DCreateFromFile", "(JLjava/lang/String;)J", (void*)nFileA3DCreateFromFile }, 2482{"rsnFileA3DCreateFromAssetStream", "(JJ)J", (void*)nFileA3DCreateFromAssetStream }, 2483{"rsnFileA3DCreateFromAsset", "(JLandroid/content/res/AssetManager;Ljava/lang/String;)J", (void*)nFileA3DCreateFromAsset }, 2484{"rsnFileA3DGetNumIndexEntries", "(JJ)I", (void*)nFileA3DGetNumIndexEntries }, 2485{"rsnFileA3DGetIndexEntries", "(JJI[I[Ljava/lang/String;)V", (void*)nFileA3DGetIndexEntries }, 2486{"rsnFileA3DGetEntryByIndex", "(JJI)J", (void*)nFileA3DGetEntryByIndex }, 2487 2488{"rsnFontCreateFromFile", "(JLjava/lang/String;FI)J", (void*)nFontCreateFromFile }, 2489{"rsnFontCreateFromAssetStream", "(JLjava/lang/String;FIJ)J", (void*)nFontCreateFromAssetStream }, 2490{"rsnFontCreateFromAsset", "(JLandroid/content/res/AssetManager;Ljava/lang/String;FI)J", (void*)nFontCreateFromAsset }, 2491 2492{"rsnElementCreate", "(JJIZI)J", (void*)nElementCreate }, 2493{"rsnElementCreate2", "(J[J[Ljava/lang/String;[I)J", (void*)nElementCreate2 }, 2494{"rsnElementGetNativeData", "(JJ[I)V", (void*)nElementGetNativeData }, 2495{"rsnElementGetSubElements", "(JJ[J[Ljava/lang/String;[I)V", (void*)nElementGetSubElements }, 2496 2497{"rsnTypeCreate", "(JJIIIZZI)J", (void*)nTypeCreate }, 2498{"rsnTypeGetNativeData", "(JJ[J)V", (void*)nTypeGetNativeData }, 2499 2500{"rsnAllocationCreateTyped", "(JJIIJ)J", (void*)nAllocationCreateTyped }, 2501{"rsnAllocationCreateFromBitmap", "(JJILandroid/graphics/Bitmap;I)J", (void*)nAllocationCreateFromBitmap }, 2502{"rsnAllocationCreateBitmapBackedAllocation", "(JJILandroid/graphics/Bitmap;I)J", (void*)nAllocationCreateBitmapBackedAllocation }, 2503{"rsnAllocationCubeCreateFromBitmap","(JJILandroid/graphics/Bitmap;I)J", (void*)nAllocationCubeCreateFromBitmap }, 2504 2505{"rsnAllocationCopyFromBitmap", "(JJLandroid/graphics/Bitmap;)V", (void*)nAllocationCopyFromBitmap }, 2506{"rsnAllocationCopyToBitmap", "(JJLandroid/graphics/Bitmap;)V", (void*)nAllocationCopyToBitmap }, 2507 2508{"rsnAllocationSyncAll", "(JJI)V", (void*)nAllocationSyncAll }, 2509{"rsnAllocationGetSurface", "(JJ)Landroid/view/Surface;", (void*)nAllocationGetSurface }, 2510{"rsnAllocationSetSurface", "(JJLandroid/view/Surface;)V", (void*)nAllocationSetSurface }, 2511{"rsnAllocationIoSend", "(JJ)V", (void*)nAllocationIoSend }, 2512{"rsnAllocationIoReceive", "(JJ)V", (void*)nAllocationIoReceive }, 2513{"rsnAllocationData1D", "(JJIIILjava/lang/Object;IIIZ)V", (void*)nAllocationData1D }, 2514{"rsnAllocationElementData", "(JJIIIII[BI)V", (void*)nAllocationElementData }, 2515{"rsnAllocationData2D", "(JJIIIIIILjava/lang/Object;IIIZ)V", (void*)nAllocationData2D }, 2516{"rsnAllocationData2D", "(JJIIIIIIJIIII)V", (void*)nAllocationData2D_alloc }, 2517{"rsnAllocationData3D", "(JJIIIIIIILjava/lang/Object;IIIZ)V", (void*)nAllocationData3D }, 2518{"rsnAllocationData3D", "(JJIIIIIIIJIIII)V", (void*)nAllocationData3D_alloc }, 2519{"rsnAllocationRead", "(JJLjava/lang/Object;IIZ)V", (void*)nAllocationRead }, 2520{"rsnAllocationRead1D", "(JJIIILjava/lang/Object;IIIZ)V", (void*)nAllocationRead1D }, 2521{"rsnAllocationElementRead", "(JJIIIII[BI)V", (void*)nAllocationElementRead }, 2522{"rsnAllocationRead2D", "(JJIIIIIILjava/lang/Object;IIIZ)V", (void*)nAllocationRead2D }, 2523{"rsnAllocationRead3D", "(JJIIIIIIILjava/lang/Object;IIIZ)V", (void*)nAllocationRead3D }, 2524{"rsnAllocationGetType", "(JJ)J", (void*)nAllocationGetType}, 2525{"rsnAllocationResize1D", "(JJI)V", (void*)nAllocationResize1D }, 2526{"rsnAllocationGenerateMipmaps", "(JJ)V", (void*)nAllocationGenerateMipmaps }, 2527 2528{"rsnAllocationAdapterCreate", "(JJJ)J", (void*)nAllocationAdapterCreate }, 2529{"rsnAllocationAdapterOffset", "(JJIIIIIIIII)V", (void*)nAllocationAdapterOffset }, 2530 2531{"rsnScriptBindAllocation", "(JJJI)V", (void*)nScriptBindAllocation }, 2532{"rsnScriptSetTimeZone", "(JJ[B)V", (void*)nScriptSetTimeZone }, 2533{"rsnScriptInvoke", "(JJI)V", (void*)nScriptInvoke }, 2534{"rsnScriptInvokeV", "(JJI[B)V", (void*)nScriptInvokeV }, 2535 2536{"rsnScriptForEach", "(JJI[JJ[B[I)V", (void*)nScriptForEach }, 2537 2538{"rsnScriptSetVarI", "(JJII)V", (void*)nScriptSetVarI }, 2539{"rsnScriptGetVarI", "(JJI)I", (void*)nScriptGetVarI }, 2540{"rsnScriptSetVarJ", "(JJIJ)V", (void*)nScriptSetVarJ }, 2541{"rsnScriptGetVarJ", "(JJI)J", (void*)nScriptGetVarJ }, 2542{"rsnScriptSetVarF", "(JJIF)V", (void*)nScriptSetVarF }, 2543{"rsnScriptGetVarF", "(JJI)F", (void*)nScriptGetVarF }, 2544{"rsnScriptSetVarD", "(JJID)V", (void*)nScriptSetVarD }, 2545{"rsnScriptGetVarD", "(JJI)D", (void*)nScriptGetVarD }, 2546{"rsnScriptSetVarV", "(JJI[B)V", (void*)nScriptSetVarV }, 2547{"rsnScriptGetVarV", "(JJI[B)V", (void*)nScriptGetVarV }, 2548{"rsnScriptSetVarVE", "(JJI[BJ[I)V", (void*)nScriptSetVarVE }, 2549{"rsnScriptSetVarObj", "(JJIJ)V", (void*)nScriptSetVarObj }, 2550 2551{"rsnScriptCCreate", "(JLjava/lang/String;Ljava/lang/String;[BI)J", (void*)nScriptCCreate }, 2552{"rsnScriptIntrinsicCreate", "(JIJ)J", (void*)nScriptIntrinsicCreate }, 2553{"rsnScriptKernelIDCreate", "(JJII)J", (void*)nScriptKernelIDCreate }, 2554{"rsnScriptInvokeIDCreate", "(JJI)J", (void*)nScriptInvokeIDCreate }, 2555{"rsnScriptFieldIDCreate", "(JJI)J", (void*)nScriptFieldIDCreate }, 2556{"rsnScriptGroupCreate", "(J[J[J[J[J[J)J", (void*)nScriptGroupCreate }, 2557{"rsnScriptGroup2Create", "(JLjava/lang/String;Ljava/lang/String;[J)J", (void*)nScriptGroup2Create }, 2558{"rsnScriptGroupSetInput", "(JJJJ)V", (void*)nScriptGroupSetInput }, 2559{"rsnScriptGroupSetOutput", "(JJJJ)V", (void*)nScriptGroupSetOutput }, 2560{"rsnScriptGroupExecute", "(JJ)V", (void*)nScriptGroupExecute }, 2561{"rsnScriptGroup2Execute", "(JJ)V", (void*)nScriptGroup2Execute }, 2562 2563{"rsnScriptIntrinsicBLAS_Single", "(JJIIIIIIIIIFJJFJIIII)V", (void*)nScriptIntrinsicBLAS_Single }, 2564{"rsnScriptIntrinsicBLAS_Double", "(JJIIIIIIIIIDJJDJIIII)V", (void*)nScriptIntrinsicBLAS_Double }, 2565{"rsnScriptIntrinsicBLAS_Complex", "(JJIIIIIIIIIFFJJFFJIIII)V", (void*)nScriptIntrinsicBLAS_Complex }, 2566{"rsnScriptIntrinsicBLAS_Z", "(JJIIIIIIIIIDDJJDDJIIII)V", (void*)nScriptIntrinsicBLAS_Z }, 2567 2568{"rsnScriptIntrinsicBLAS_BNNM", "(JJIIIJIJIJII)V", (void*)nScriptIntrinsicBLAS_BNNM }, 2569 2570{"rsnProgramStoreCreate", "(JZZZZZZIII)J", (void*)nProgramStoreCreate }, 2571 2572{"rsnProgramBindConstants", "(JJIJ)V", (void*)nProgramBindConstants }, 2573{"rsnProgramBindTexture", "(JJIJ)V", (void*)nProgramBindTexture }, 2574{"rsnProgramBindSampler", "(JJIJ)V", (void*)nProgramBindSampler }, 2575 2576{"rsnProgramFragmentCreate", "(JLjava/lang/String;[Ljava/lang/String;[J)J", (void*)nProgramFragmentCreate }, 2577{"rsnProgramRasterCreate", "(JZI)J", (void*)nProgramRasterCreate }, 2578{"rsnProgramVertexCreate", "(JLjava/lang/String;[Ljava/lang/String;[J)J", (void*)nProgramVertexCreate }, 2579 2580{"rsnContextBindRootScript", "(JJ)V", (void*)nContextBindRootScript }, 2581{"rsnContextBindProgramStore", "(JJ)V", (void*)nContextBindProgramStore }, 2582{"rsnContextBindProgramFragment", "(JJ)V", (void*)nContextBindProgramFragment }, 2583{"rsnContextBindProgramVertex", "(JJ)V", (void*)nContextBindProgramVertex }, 2584{"rsnContextBindProgramRaster", "(JJ)V", (void*)nContextBindProgramRaster }, 2585 2586{"rsnSamplerCreate", "(JIIIIIF)J", (void*)nSamplerCreate }, 2587 2588{"rsnMeshCreate", "(J[J[J[I)J", (void*)nMeshCreate }, 2589 2590{"rsnMeshGetVertexBufferCount", "(JJ)I", (void*)nMeshGetVertexBufferCount }, 2591{"rsnMeshGetIndexCount", "(JJ)I", (void*)nMeshGetIndexCount }, 2592{"rsnMeshGetVertices", "(JJ[JI)V", (void*)nMeshGetVertices }, 2593{"rsnMeshGetIndices", "(JJ[J[II)V", (void*)nMeshGetIndices }, 2594 2595{"rsnSystemGetPointerSize", "()I", (void*)nSystemGetPointerSize }, 2596}; 2597 2598static int registerFuncs(JNIEnv *_env) 2599{ 2600 return android::AndroidRuntime::registerNativeMethods( 2601 _env, classPathName, methods, NELEM(methods)); 2602} 2603 2604// --------------------------------------------------------------------------- 2605 2606jint JNI_OnLoad(JavaVM* vm, void* reserved) 2607{ 2608 JNIEnv* env = nullptr; 2609 jint result = -1; 2610 2611 if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { 2612 ALOGE("ERROR: GetEnv failed\n"); 2613 goto bail; 2614 } 2615 assert(env != nullptr); 2616 2617 if (registerFuncs(env) < 0) { 2618 ALOGE("ERROR: Renderscript native registration failed\n"); 2619 goto bail; 2620 } 2621 2622 /* success -- return valid version number */ 2623 result = JNI_VERSION_1_4; 2624 2625bail: 2626 return result; 2627} 2628