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