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