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