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