RenderScript.cpp revision 66f0a168c4227d4e302f4ffb21ec7e9d7b9ca828
1/* 2 * Copyright (C) 2013 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#include <malloc.h> 18#include <string.h> 19#include <pthread.h> 20 21#include "RenderScript.h" 22#include "rsCppStructs.h" 23#include "rsCppInternal.h" 24#include "rsDispatch.h" 25 26#include <dlfcn.h> 27#include <unistd.h> 28 29#if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB) && defined(HAVE_ANDROID_OS) 30#include <cutils/properties.h> 31#else 32#include "rsCompatibilityLib.h" 33#endif 34 35 36using namespace android; 37using namespace RSC; 38 39bool RS::gInitialized = false; 40bool RS::usingNative = false; 41pthread_mutex_t RS::gInitMutex = PTHREAD_MUTEX_INITIALIZER; 42dispatchTable* RS::dispatch = nullptr; 43static int gInitError = 0; 44 45RS::RS() { 46 mDev = nullptr; 47 mContext = nullptr; 48 mErrorFunc = nullptr; 49 mMessageFunc = nullptr; 50 mMessageRun = false; 51 mInit = false; 52 mCurrentError = RS_SUCCESS; 53 54 memset(&mElements, 0, sizeof(mElements)); 55 memset(&mSamplers, 0, sizeof(mSamplers)); 56} 57 58RS::~RS() { 59 if (mInit == true) { 60 mMessageRun = false; 61 62 if (mContext) { 63 RS::dispatch->ContextDeinitToClient(mContext); 64 65 void *res = nullptr; 66 int status = pthread_join(mMessageThreadId, &res); 67 68 RS::dispatch->ContextDestroy(mContext); 69 mContext = nullptr; 70 } 71 if (mDev) { 72 RS::dispatch->DeviceDestroy(mDev); 73 mDev = nullptr; 74 } 75 } 76} 77 78bool RS::init(std::string name, uint32_t flags) { 79 return RS::init(name, RS_VERSION, flags); 80} 81 82static bool loadSymbols(void* handle) { 83 84 RS::dispatch->AllocationGetType = (AllocationGetTypeFnPtr)dlsym(handle, "rsaAllocationGetType"); 85 if (RS::dispatch->AllocationGetType == nullptr) { 86 ALOGV("Couldn't initialize RS::dispatch->AllocationGetType"); 87 return false; 88 } 89 RS::dispatch->TypeGetNativeData = (TypeGetNativeDataFnPtr)dlsym(handle, "rsaTypeGetNativeData"); 90 if (RS::dispatch->TypeGetNativeData == nullptr) { 91 ALOGV("Couldn't initialize RS::dispatch->TypeGetNativeData"); 92 return false; 93 } 94 RS::dispatch->ElementGetNativeData = (ElementGetNativeDataFnPtr)dlsym(handle, "rsaElementGetNativeData"); 95 if (RS::dispatch->ElementGetNativeData == nullptr) { 96 ALOGV("Couldn't initialize RS::dispatch->ElementGetNativeData"); 97 return false; 98 } 99 RS::dispatch->ElementGetSubElements = (ElementGetSubElementsFnPtr)dlsym(handle, "rsaElementGetSubElements"); 100 if (RS::dispatch->ElementGetSubElements == nullptr) { 101 ALOGV("Couldn't initialize RS::dispatch->ElementGetSubElements"); 102 return false; 103 } 104 RS::dispatch->DeviceCreate = (DeviceCreateFnPtr)dlsym(handle, "rsDeviceCreate"); 105 if (RS::dispatch->DeviceCreate == nullptr) { 106 ALOGV("Couldn't initialize RS::dispatch->DeviceCreate"); 107 return false; 108 } 109 RS::dispatch->DeviceDestroy = (DeviceDestroyFnPtr)dlsym(handle, "rsDeviceDestroy"); 110 if (RS::dispatch->DeviceDestroy == nullptr) { 111 ALOGV("Couldn't initialize RS::dispatch->DeviceDestroy"); 112 return false; 113 } 114 RS::dispatch->DeviceSetConfig = (DeviceSetConfigFnPtr)dlsym(handle, "rsDeviceSetConfig"); 115 if (RS::dispatch->DeviceSetConfig == nullptr) { 116 ALOGV("Couldn't initialize RS::dispatch->DeviceSetConfig"); 117 return false; 118 } 119 RS::dispatch->ContextCreate = (ContextCreateFnPtr)dlsym(handle, "rsContextCreate");; 120 if (RS::dispatch->ContextCreate == nullptr) { 121 ALOGV("Couldn't initialize RS::dispatch->ContextCreate"); 122 return false; 123 } 124 RS::dispatch->GetName = (GetNameFnPtr)dlsym(handle, "rsaGetName");; 125 if (RS::dispatch->GetName == nullptr) { 126 ALOGV("Couldn't initialize RS::dispatch->GetName"); 127 return false; 128 } 129 RS::dispatch->ContextDestroy = (ContextDestroyFnPtr)dlsym(handle, "rsContextDestroy"); 130 if (RS::dispatch->ContextDestroy == nullptr) { 131 ALOGV("Couldn't initialize RS::dispatch->ContextDestroy"); 132 return false; 133 } 134 RS::dispatch->ContextGetMessage = (ContextGetMessageFnPtr)dlsym(handle, "rsContextGetMessage"); 135 if (RS::dispatch->ContextGetMessage == nullptr) { 136 ALOGV("Couldn't initialize RS::dispatch->ContextGetMessage"); 137 return false; 138 } 139 RS::dispatch->ContextPeekMessage = (ContextPeekMessageFnPtr)dlsym(handle, "rsContextPeekMessage"); 140 if (RS::dispatch->ContextPeekMessage == nullptr) { 141 ALOGV("Couldn't initialize RS::dispatch->ContextPeekMessage"); 142 return false; 143 } 144 RS::dispatch->ContextSendMessage = (ContextSendMessageFnPtr)dlsym(handle, "rsContextSendMessage"); 145 if (RS::dispatch->ContextSendMessage == nullptr) { 146 ALOGV("Couldn't initialize RS::dispatch->ContextSendMessage"); 147 return false; 148 } 149 RS::dispatch->ContextInitToClient = (ContextInitToClientFnPtr)dlsym(handle, "rsContextInitToClient"); 150 if (RS::dispatch->ContextInitToClient == nullptr) { 151 ALOGV("Couldn't initialize RS::dispatch->ContextInitToClient"); 152 return false; 153 } 154 RS::dispatch->ContextDeinitToClient = (ContextDeinitToClientFnPtr)dlsym(handle, "rsContextDeinitToClient"); 155 if (RS::dispatch->ContextDeinitToClient == nullptr) { 156 ALOGV("Couldn't initialize RS::dispatch->ContextDeinitToClient"); 157 return false; 158 } 159 RS::dispatch->TypeCreate = (TypeCreateFnPtr)dlsym(handle, "rsTypeCreate"); 160 if (RS::dispatch->TypeCreate == nullptr) { 161 ALOGV("Couldn't initialize RS::dispatch->TypeCreate"); 162 return false; 163 } 164 RS::dispatch->AllocationCreateTyped = (AllocationCreateTypedFnPtr)dlsym(handle, "rsAllocationCreateTyped"); 165 if (RS::dispatch->AllocationCreateTyped == nullptr) { 166 ALOGV("Couldn't initialize RS::dispatch->AllocationCreateTyped"); 167 return false; 168 } 169 RS::dispatch->AllocationCreateFromBitmap = (AllocationCreateFromBitmapFnPtr)dlsym(handle, "rsAllocationCreateFromBitmap"); 170 if (RS::dispatch->AllocationCreateFromBitmap == nullptr) { 171 ALOGV("Couldn't initialize RS::dispatch->AllocationCreateFromBitmap"); 172 return false; 173 } 174 RS::dispatch->AllocationCubeCreateFromBitmap = (AllocationCubeCreateFromBitmapFnPtr)dlsym(handle, "rsAllocationCubeCreateFromBitmap"); 175 if (RS::dispatch->AllocationCubeCreateFromBitmap == nullptr) { 176 ALOGV("Couldn't initialize RS::dispatch->AllocationCubeCreateFromBitmap"); 177 return false; 178 } 179 RS::dispatch->AllocationGetSurface = (AllocationGetSurfaceFnPtr)dlsym(handle, "rsAllocationGetSurface"); 180 if (RS::dispatch->AllocationGetSurface == nullptr) { 181 ALOGV("Couldn't initialize RS::dispatch->AllocationGetSurface"); 182 return false; 183 } 184 RS::dispatch->AllocationSetSurface = (AllocationSetSurfaceFnPtr)dlsym(handle, "rsAllocationSetSurface"); 185 if (RS::dispatch->AllocationSetSurface == nullptr) { 186 ALOGV("Couldn't initialize RS::dispatch->AllocationSetSurface"); 187 return false; 188 } 189 RS::dispatch->ContextFinish = (ContextFinishFnPtr)dlsym(handle, "rsContextFinish"); 190 if (RS::dispatch->ContextFinish == nullptr) { 191 ALOGV("Couldn't initialize RS::dispatch->ContextFinish"); 192 return false; 193 } 194 RS::dispatch->ContextDump = (ContextDumpFnPtr)dlsym(handle, "rsContextDump"); 195 if (RS::dispatch->ContextDump == nullptr) { 196 ALOGV("Couldn't initialize RS::dispatch->ContextDump"); 197 return false; 198 } 199 RS::dispatch->ContextSetPriority = (ContextSetPriorityFnPtr)dlsym(handle, "rsContextSetPriority"); 200 if (RS::dispatch->ContextSetPriority == nullptr) { 201 ALOGV("Couldn't initialize RS::dispatch->ContextSetPriority"); 202 return false; 203 } 204 RS::dispatch->AssignName = (AssignNameFnPtr)dlsym(handle, "rsAssignName"); 205 if (RS::dispatch->AssignName == nullptr) { 206 ALOGV("Couldn't initialize RS::dispatch->AssignName"); 207 return false; 208 } 209 RS::dispatch->ObjDestroy = (ObjDestroyFnPtr)dlsym(handle, "rsObjDestroy"); 210 if (RS::dispatch->ObjDestroy == nullptr) { 211 ALOGV("Couldn't initialize RS::dispatch->ObjDestroy"); 212 return false; 213 } 214 RS::dispatch->ElementCreate = (ElementCreateFnPtr)dlsym(handle, "rsElementCreate"); 215 if (RS::dispatch->ElementCreate == nullptr) { 216 ALOGV("Couldn't initialize RS::dispatch->ElementCreate"); 217 return false; 218 } 219 RS::dispatch->ElementCreate2 = (ElementCreate2FnPtr)dlsym(handle, "rsElementCreate2"); 220 if (RS::dispatch->ElementCreate2 == nullptr) { 221 ALOGV("Couldn't initialize RS::dispatch->ElementCreate2"); 222 return false; 223 } 224 RS::dispatch->AllocationCopyToBitmap = (AllocationCopyToBitmapFnPtr)dlsym(handle, "rsAllocationCopyToBitmap"); 225 if (RS::dispatch->AllocationCopyToBitmap == nullptr) { 226 ALOGV("Couldn't initialize RS::dispatch->AllocationCopyToBitmap"); 227 return false; 228 } 229 RS::dispatch->Allocation1DData = (Allocation1DDataFnPtr)dlsym(handle, "rsAllocation1DData"); 230 if (RS::dispatch->Allocation1DData == nullptr) { 231 ALOGV("Couldn't initialize RS::dispatch->Allocation1DData"); 232 return false; 233 } 234 RS::dispatch->Allocation1DElementData = (Allocation1DElementDataFnPtr)dlsym(handle, "rsAllocation1DElementData"); 235 if (RS::dispatch->Allocation1DElementData == nullptr) { 236 ALOGV("Couldn't initialize RS::dispatch->Allocation1DElementData"); 237 return false; 238 } 239 RS::dispatch->Allocation2DData = (Allocation2DDataFnPtr)dlsym(handle, "rsAllocation2DData"); 240 if (RS::dispatch->Allocation2DData == nullptr) { 241 ALOGV("Couldn't initialize RS::dispatch->Allocation2DData"); 242 return false; 243 } 244 RS::dispatch->Allocation3DData = (Allocation3DDataFnPtr)dlsym(handle, "rsAllocation3DData"); 245 if (RS::dispatch->Allocation3DData == nullptr) { 246 ALOGV("Couldn't initialize RS::dispatch->Allocation3DData"); 247 return false; 248 } 249 RS::dispatch->AllocationGenerateMipmaps = (AllocationGenerateMipmapsFnPtr)dlsym(handle, "rsAllocationGenerateMipmaps"); 250 if (RS::dispatch->AllocationGenerateMipmaps == nullptr) { 251 ALOGV("Couldn't initialize RS::dispatch->AllocationGenerateMipmaps"); 252 return false; 253 } 254 RS::dispatch->AllocationRead = (AllocationReadFnPtr)dlsym(handle, "rsAllocationRead"); 255 if (RS::dispatch->AllocationRead == nullptr) { 256 ALOGV("Couldn't initialize RS::dispatch->AllocationRead"); 257 return false; 258 } 259 RS::dispatch->Allocation1DRead = (Allocation1DReadFnPtr)dlsym(handle, "rsAllocation1DRead"); 260 if (RS::dispatch->Allocation1DRead == nullptr) { 261 ALOGV("Couldn't initialize RS::dispatch->Allocation1DRead"); 262 return false; 263 } 264 RS::dispatch->Allocation2DRead = (Allocation2DReadFnPtr)dlsym(handle, "rsAllocation2DRead"); 265 if (RS::dispatch->Allocation2DRead == nullptr) { 266 ALOGV("Couldn't initialize RS::dispatch->Allocation2DRead"); 267 return false; 268 } 269 RS::dispatch->AllocationSyncAll = (AllocationSyncAllFnPtr)dlsym(handle, "rsAllocationSyncAll"); 270 if (RS::dispatch->AllocationSyncAll == nullptr) { 271 ALOGV("Couldn't initialize RS::dispatch->AllocationSyncAll"); 272 return false; 273 } 274 RS::dispatch->AllocationResize1D = (AllocationResize1DFnPtr)dlsym(handle, "rsAllocationResize1D"); 275 if (RS::dispatch->AllocationResize1D == nullptr) { 276 ALOGV("Couldn't initialize RS::dispatch->AllocationResize1D"); 277 return false; 278 } 279 RS::dispatch->AllocationCopy2DRange = (AllocationCopy2DRangeFnPtr)dlsym(handle, "rsAllocationCopy2DRange"); 280 if (RS::dispatch->AllocationCopy2DRange == nullptr) { 281 ALOGV("Couldn't initialize RS::dispatch->AllocationCopy2DRange"); 282 return false; 283 } 284 RS::dispatch->AllocationCopy3DRange = (AllocationCopy3DRangeFnPtr)dlsym(handle, "rsAllocationCopy3DRange"); 285 if (RS::dispatch->AllocationCopy3DRange == nullptr) { 286 ALOGV("Couldn't initialize RS::dispatch->AllocationCopy3DRange"); 287 return false; 288 } 289 RS::dispatch->SamplerCreate = (SamplerCreateFnPtr)dlsym(handle, "rsSamplerCreate"); 290 if (RS::dispatch->SamplerCreate == nullptr) { 291 ALOGV("Couldn't initialize RS::dispatch->SamplerCreate"); 292 return false; 293 } 294 RS::dispatch->ScriptBindAllocation = (ScriptBindAllocationFnPtr)dlsym(handle, "rsScriptBindAllocation"); 295 if (RS::dispatch->ScriptBindAllocation == nullptr) { 296 ALOGV("Couldn't initialize RS::dispatch->ScriptBindAllocation"); 297 return false; 298 } 299 RS::dispatch->ScriptSetTimeZone = (ScriptSetTimeZoneFnPtr)dlsym(handle, "rsScriptSetTimeZone"); 300 if (RS::dispatch->ScriptSetTimeZone == nullptr) { 301 ALOGV("Couldn't initialize RS::dispatch->ScriptSetTimeZone"); 302 return false; 303 } 304 RS::dispatch->ScriptInvoke = (ScriptInvokeFnPtr)dlsym(handle, "rsScriptInvoke"); 305 if (RS::dispatch->ScriptInvoke == nullptr) { 306 ALOGV("Couldn't initialize RS::dispatch->ScriptInvoke"); 307 return false; 308 } 309 RS::dispatch->ScriptInvokeV = (ScriptInvokeVFnPtr)dlsym(handle, "rsScriptInvokeV"); 310 if (RS::dispatch->ScriptInvokeV == nullptr) { 311 ALOGV("Couldn't initialize RS::dispatch->ScriptInvokeV"); 312 return false; 313 } 314 RS::dispatch->ScriptForEach = (ScriptForEachFnPtr)dlsym(handle, "rsScriptForEach"); 315 if (RS::dispatch->ScriptForEach == nullptr) { 316 ALOGV("Couldn't initialize RS::dispatch->ScriptForEach"); 317 return false; 318 } 319 RS::dispatch->ScriptSetVarI = (ScriptSetVarIFnPtr)dlsym(handle, "rsScriptSetVarI"); 320 if (RS::dispatch->ScriptSetVarI == nullptr) { 321 ALOGV("Couldn't initialize RS::dispatch->ScriptSetVarI"); 322 return false; 323 } 324 RS::dispatch->ScriptSetVarObj = (ScriptSetVarObjFnPtr)dlsym(handle, "rsScriptSetVarObj"); 325 if (RS::dispatch->ScriptSetVarObj == nullptr) { 326 ALOGV("Couldn't initialize RS::dispatch->ScriptSetVarObj"); 327 return false; 328 } 329 RS::dispatch->ScriptSetVarJ = (ScriptSetVarJFnPtr)dlsym(handle, "rsScriptSetVarJ"); 330 if (RS::dispatch->ScriptSetVarJ == nullptr) { 331 ALOGV("Couldn't initialize RS::dispatch->ScriptSetVarJ"); 332 return false; 333 } 334 RS::dispatch->ScriptSetVarF = (ScriptSetVarFFnPtr)dlsym(handle, "rsScriptSetVarF"); 335 if (RS::dispatch->ScriptSetVarF == nullptr) { 336 ALOGV("Couldn't initialize RS::dispatch->ScriptSetVarF"); 337 return false; 338 } 339 RS::dispatch->ScriptSetVarD = (ScriptSetVarDFnPtr)dlsym(handle, "rsScriptSetVarD"); 340 if (RS::dispatch->ScriptSetVarD == nullptr) { 341 ALOGV("Couldn't initialize RS::dispatch->ScriptSetVarD"); 342 return false; 343 } 344 RS::dispatch->ScriptSetVarV = (ScriptSetVarVFnPtr)dlsym(handle, "rsScriptSetVarV"); 345 if (RS::dispatch->ScriptSetVarV == nullptr) { 346 ALOGV("Couldn't initialize RS::dispatch->ScriptSetVarV"); 347 return false; 348 } 349 RS::dispatch->ScriptGetVarV = (ScriptGetVarVFnPtr)dlsym(handle, "rsScriptGetVarV"); 350 if (RS::dispatch->ScriptGetVarV == nullptr) { 351 ALOGV("Couldn't initialize RS::dispatch->ScriptGetVarV"); 352 return false; 353 } 354 RS::dispatch->ScriptSetVarVE = (ScriptSetVarVEFnPtr)dlsym(handle, "rsScriptSetVarVE"); 355 if (RS::dispatch->ScriptSetVarVE == nullptr) { 356 ALOGV("Couldn't initialize RS::dispatch->ScriptSetVarVE"); 357 return false; 358 } 359 RS::dispatch->ScriptCCreate = (ScriptCCreateFnPtr)dlsym(handle, "rsScriptCCreate"); 360 if (RS::dispatch->ScriptCCreate == nullptr) { 361 ALOGV("Couldn't initialize RS::dispatch->ScriptCCreate"); 362 return false; 363 } 364 RS::dispatch->ScriptIntrinsicCreate = (ScriptIntrinsicCreateFnPtr)dlsym(handle, "rsScriptIntrinsicCreate"); 365 if (RS::dispatch->ScriptIntrinsicCreate == nullptr) { 366 ALOGV("Couldn't initialize RS::dispatch->ScriptIntrinsicCreate"); 367 return false; 368 } 369 RS::dispatch->ScriptKernelIDCreate = (ScriptKernelIDCreateFnPtr)dlsym(handle, "rsScriptKernelIDCreate"); 370 if (RS::dispatch->ScriptKernelIDCreate == nullptr) { 371 ALOGV("Couldn't initialize RS::dispatch->ScriptKernelIDCreate"); 372 return false; 373 } 374 RS::dispatch->ScriptFieldIDCreate = (ScriptFieldIDCreateFnPtr)dlsym(handle, "rsScriptFieldIDCreate"); 375 if (RS::dispatch->ScriptFieldIDCreate == nullptr) { 376 ALOGV("Couldn't initialize RS::dispatch->ScriptFieldIDCreate"); 377 return false; 378 } 379 RS::dispatch->ScriptGroupCreate = (ScriptGroupCreateFnPtr)dlsym(handle, "rsScriptGroupCreate"); 380 if (RS::dispatch->ScriptGroupCreate == nullptr) { 381 ALOGV("Couldn't initialize RS::dispatch->ScriptGroupCreate"); 382 return false; 383 } 384 RS::dispatch->ScriptGroupSetOutput = (ScriptGroupSetOutputFnPtr)dlsym(handle, "rsScriptGroupSetOutput"); 385 if (RS::dispatch->ScriptGroupSetOutput == nullptr) { 386 ALOGV("Couldn't initialize RS::dispatch->ScriptGroupSetOutput"); 387 return false; 388 } 389 RS::dispatch->ScriptGroupSetInput = (ScriptGroupSetInputFnPtr)dlsym(handle, "rsScriptGroupSetInput"); 390 if (RS::dispatch->ScriptGroupSetInput == nullptr) { 391 ALOGV("Couldn't initialize RS::dispatch->ScriptGroupSetInput"); 392 return false; 393 } 394 RS::dispatch->ScriptGroupExecute = (ScriptGroupExecuteFnPtr)dlsym(handle, "rsScriptGroupExecute"); 395 if (RS::dispatch->ScriptGroupExecute == nullptr) { 396 ALOGV("Couldn't initialize RS::dispatch->ScriptGroupExecute"); 397 return false; 398 } 399 RS::dispatch->AllocationIoSend = (AllocationIoSendFnPtr)dlsym(handle, "rsAllocationIoSend"); 400 if (RS::dispatch->AllocationIoSend == nullptr) { 401 ALOGV("Couldn't initialize RS::dispatch->AllocationIoSend"); 402 return false; 403 } 404 RS::dispatch->AllocationIoReceive = (AllocationIoReceiveFnPtr)dlsym(handle, "rsAllocationIoReceive"); 405 if (RS::dispatch->AllocationIoReceive == nullptr) { 406 ALOGV("Couldn't initialize RS::dispatch->AllocationIoReceive"); 407 return false; 408 } 409 RS::dispatch->AllocationGetPointer = (AllocationGetPointerFnPtr)dlsym(handle, "rsAllocationGetPointer"); 410 if (RS::dispatch->AllocationGetPointer == nullptr) { 411 ALOGV("Couldn't initialize RS::dispatch->AllocationGetPointer"); 412 //return false; 413 } 414 415 return true; 416} 417 418// this will only open API 19+ libRS 419// because that's when we changed libRS to extern "C" entry points 420static bool loadSO(const char* filename) { 421 void* handle = dlopen(filename, RTLD_LAZY | RTLD_LOCAL); 422 if (handle == nullptr) { 423 ALOGV("couldn't dlopen %s, %s", filename, dlerror()); 424 return false; 425 } 426 427 if (loadSymbols(handle) == false) { 428 ALOGV("%s init failed!", filename); 429 return false; 430 } 431 //ALOGE("Successfully loaded %s", filename); 432 return true; 433} 434 435static uint32_t getProp(const char *str) { 436#if !defined(__LP64__) && !defined(RS_SERVER) && defined(HAVE_ANDROID_OS) 437 char buf[256]; 438 property_get(str, buf, "0"); 439 return atoi(buf); 440#else 441 return 0; 442#endif 443} 444 445bool RS::initDispatch(int targetApi) { 446 pthread_mutex_lock(&gInitMutex); 447 if (gInitError) { 448 goto error; 449 } else if (gInitialized) { 450 pthread_mutex_unlock(&gInitMutex); 451 return true; 452 } 453 454 RS::dispatch = new dispatchTable; 455 456 // attempt to load libRS, load libRSSupport on failure 457 // if property is set, proceed directly to libRSSupport 458 if (getProp("debug.rs.forcecompat") == 0) { 459 usingNative = loadSO("libRS.so"); 460 } 461 if (usingNative == false) { 462 if (loadSO("libRSSupport.so") == false) { 463 ALOGE("Failed to load libRS.so and libRSSupport.so"); 464 goto error; 465 } 466 } 467 468 gInitialized = true; 469 470 pthread_mutex_unlock(&gInitMutex); 471 return true; 472 473 error: 474 gInitError = 1; 475 pthread_mutex_unlock(&gInitMutex); 476 return false; 477} 478 479bool RS::init(std::string &name, int targetApi, uint32_t flags) { 480 if (mInit) { 481 return true; 482 } 483 484 if (initDispatch(targetApi) == false) { 485 ALOGE("Couldn't initialize dispatch table"); 486 return false; 487 } 488 489 mCacheDir = name; 490 491 mDev = RS::dispatch->DeviceCreate(); 492 if (mDev == 0) { 493 ALOGE("Device creation failed"); 494 return false; 495 } 496 497 if (flags & ~(RS_CONTEXT_SYNCHRONOUS | RS_CONTEXT_LOW_LATENCY | 498 RS_CONTEXT_LOW_POWER)) { 499 ALOGE("Invalid flags passed"); 500 return false; 501 } 502 503 mContext = RS::dispatch->ContextCreate(mDev, 0, targetApi, RS_CONTEXT_TYPE_NORMAL, flags); 504 if (mContext == 0) { 505 ALOGE("Context creation failed"); 506 return false; 507 } 508 509 pid_t mNativeMessageThreadId; 510 511 int status = pthread_create(&mMessageThreadId, nullptr, threadProc, this); 512 if (status) { 513 ALOGE("Failed to start RS message thread."); 514 return false; 515 } 516 // Wait for the message thread to be active. 517 while (!mMessageRun) { 518 usleep(1000); 519 } 520 521 mInit = true; 522 523 return true; 524} 525 526void RS::throwError(RSError error, const char *errMsg) { 527 if (mCurrentError == RS_SUCCESS) { 528 mCurrentError = error; 529 ALOGE("RS CPP error: %s", errMsg); 530 } else { 531 ALOGE("RS CPP error (masked by previous error): %s", errMsg); 532 } 533} 534 535RSError RS::getError() { 536 return mCurrentError; 537} 538 539 540void * RS::threadProc(void *vrsc) { 541 RS *rs = static_cast<RS *>(vrsc); 542 size_t rbuf_size = 256; 543 void * rbuf = malloc(rbuf_size); 544 545 RS::dispatch->ContextInitToClient(rs->mContext); 546 rs->mMessageRun = true; 547 548 while (rs->mMessageRun) { 549 size_t receiveLen = 0; 550 uint32_t usrID = 0; 551 uint32_t subID = 0; 552 RsMessageToClientType r = RS::dispatch->ContextPeekMessage(rs->mContext, 553 &receiveLen, sizeof(receiveLen), 554 &usrID, sizeof(usrID)); 555 556 if (receiveLen >= rbuf_size) { 557 rbuf_size = receiveLen + 32; 558 rbuf = realloc(rbuf, rbuf_size); 559 } 560 if (!rbuf) { 561 ALOGE("RS::message handler realloc error %zu", rbuf_size); 562 // No clean way to recover now? 563 } 564 RS::dispatch->ContextGetMessage(rs->mContext, rbuf, rbuf_size, &receiveLen, sizeof(receiveLen), 565 &subID, sizeof(subID)); 566 567 switch(r) { 568 case RS_MESSAGE_TO_CLIENT_ERROR: 569 ALOGE("RS Error %s", (const char *)rbuf); 570 rs->throwError(RS_ERROR_RUNTIME_ERROR, "Error returned from runtime"); 571 if(rs->mMessageFunc != nullptr) { 572 rs->mErrorFunc(usrID, (const char *)rbuf); 573 } 574 break; 575 case RS_MESSAGE_TO_CLIENT_NONE: 576 case RS_MESSAGE_TO_CLIENT_EXCEPTION: 577 case RS_MESSAGE_TO_CLIENT_RESIZE: 578 // teardown. But we want to avoid starving other threads during 579 // teardown by yielding until the next line in the destructor can 580 // execute to set mRun = false. Note that the FIFO sends an 581 // empty NONE message when it reaches its destructor. 582 usleep(1000); 583 break; 584 case RS_MESSAGE_TO_CLIENT_USER: 585 if(rs->mMessageFunc != nullptr) { 586 rs->mMessageFunc(usrID, rbuf, receiveLen); 587 } else { 588 ALOGE("Received a message from the script with no message handler installed."); 589 } 590 break; 591 592 default: 593 ALOGE("RS unknown message type %i", r); 594 } 595 } 596 597 if (rbuf) { 598 free(rbuf); 599 } 600 ALOGV("RS Message thread exiting."); 601 return nullptr; 602} 603 604void RS::setErrorHandler(ErrorHandlerFunc_t func) { 605 mErrorFunc = func; 606} 607 608void RS::setMessageHandler(MessageHandlerFunc_t func) { 609 mMessageFunc = func; 610} 611 612void RS::finish() { 613 RS::dispatch->ContextFinish(mContext); 614} 615