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