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