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