RenderScript.cpp revision caf4126512b2152ea5f6573ce5d9ca29767b9678
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 31using namespace android; 32using namespace RSC; 33 34bool RS::gInitialized = false; 35bool RS::usingNative = false; 36pthread_mutex_t RS::gInitMutex = PTHREAD_MUTEX_INITIALIZER; 37dispatchTable* RS::dispatch = NULL; 38static int gInitError = 0; 39 40RS::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 53RS::~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 69bool RS::init(std::string name, uint32_t flags) { 70 return RS::init(name, RS_VERSION, flags); 71} 72 73static bool loadSymbols(void* handle) { 74 75 RS::dispatch->AllocationGetType = (AllocationGetTypeFnPtr)dlsym(handle, "rsaAllocationGetType"); 76 if (RS::dispatch->AllocationGetType == NULL) { 77 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 ALOGV("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 406static bool loadSO(const char* filename) { 407 void* handle = dlopen(filename, RTLD_LAZY | RTLD_LOCAL); 408 if (handle == NULL) { 409 ALOGV("couldn't dlopen %s, %s", filename, dlerror()); 410 return false; 411 } 412 413 if (loadSymbols(handle) == false) { 414 ALOGV("%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(std::string &name, int targetApi, uint32_t flags) { 466 if (mInit) { 467 return true; 468 } 469 470 if (initDispatch(targetApi) == false) { 471 ALOGE("Couldn't initialize dispatch table"); 472 return false; 473 } 474 475 mCacheDir = name; 476 mCacheDir += "/com.android.renderscript.cache/"; 477 478 mDev = RS::dispatch->DeviceCreate(); 479 if (mDev == 0) { 480 ALOGE("Device creation failed"); 481 return false; 482 } 483 484 if (flags >= RS_CONTEXT_MAX) { 485 ALOGE("Invalid flags passed"); 486 return false; 487 } 488 489 mContext = RS::dispatch->ContextCreate(mDev, 0, targetApi, RS_CONTEXT_TYPE_NORMAL, flags); 490 if (mContext == 0) { 491 ALOGE("Context creation failed"); 492 return false; 493 } 494 495 pid_t mNativeMessageThreadId; 496 497 int status = pthread_create(&mMessageThreadId, NULL, threadProc, this); 498 if (status) { 499 ALOGE("Failed to start RS message thread."); 500 return false; 501 } 502 // Wait for the message thread to be active. 503 while (!mMessageRun) { 504 usleep(1000); 505 } 506 507 mInit = true; 508 509 return true; 510} 511 512void RS::throwError(RSError error, const char *errMsg) { 513 if (mCurrentError == RS_SUCCESS) { 514 mCurrentError = error; 515 ALOGE("RS CPP error: %s", errMsg); 516 } else { 517 ALOGE("RS CPP error (masked by previous error): %s", errMsg); 518 } 519} 520 521RSError RS::getError() { 522 return mCurrentError; 523} 524 525 526void * RS::threadProc(void *vrsc) { 527 RS *rs = static_cast<RS *>(vrsc); 528 size_t rbuf_size = 256; 529 void * rbuf = malloc(rbuf_size); 530 531 RS::dispatch->ContextInitToClient(rs->mContext); 532 rs->mMessageRun = true; 533 534 while (rs->mMessageRun) { 535 size_t receiveLen = 0; 536 uint32_t usrID = 0; 537 uint32_t subID = 0; 538 RsMessageToClientType r = RS::dispatch->ContextPeekMessage(rs->mContext, 539 &receiveLen, sizeof(receiveLen), 540 &usrID, sizeof(usrID)); 541 542 if (receiveLen >= rbuf_size) { 543 rbuf_size = receiveLen + 32; 544 rbuf = realloc(rbuf, rbuf_size); 545 } 546 if (!rbuf) { 547 ALOGE("RS::message handler realloc error %zu", rbuf_size); 548 // No clean way to recover now? 549 } 550 RS::dispatch->ContextGetMessage(rs->mContext, rbuf, rbuf_size, &receiveLen, sizeof(receiveLen), 551 &subID, sizeof(subID)); 552 553 switch(r) { 554 case RS_MESSAGE_TO_CLIENT_ERROR: 555 ALOGE("RS Error %s", (const char *)rbuf); 556 rs->throwError(RS_ERROR_RUNTIME_ERROR, "Error returned from runtime"); 557 if(rs->mMessageFunc != NULL) { 558 rs->mErrorFunc(usrID, (const char *)rbuf); 559 } 560 break; 561 case RS_MESSAGE_TO_CLIENT_NONE: 562 case RS_MESSAGE_TO_CLIENT_EXCEPTION: 563 case RS_MESSAGE_TO_CLIENT_RESIZE: 564 // teardown. But we want to avoid starving other threads during 565 // teardown by yielding until the next line in the destructor can 566 // execute to set mRun = false. Note that the FIFO sends an 567 // empty NONE message when it reaches its destructor. 568 usleep(1000); 569 break; 570 case RS_MESSAGE_TO_CLIENT_USER: 571 if(rs->mMessageFunc != NULL) { 572 rs->mMessageFunc(usrID, rbuf, receiveLen); 573 } else { 574 ALOGE("Received a message from the script with no message handler installed."); 575 } 576 break; 577 578 default: 579 ALOGE("RS unknown message type %i", r); 580 } 581 } 582 583 if (rbuf) { 584 free(rbuf); 585 } 586 ALOGV("RS Message thread exiting."); 587 return NULL; 588} 589 590void RS::setErrorHandler(ErrorHandlerFunc_t func) { 591 mErrorFunc = func; 592} 593 594void RS::setMessageHandler(MessageHandlerFunc_t func) { 595 mMessageFunc = func; 596} 597 598void RS::finish() { 599 RS::dispatch->ContextFinish(mContext); 600} 601