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