1#include "rsClosure.h"
2
3#include "cpu_ref/rsCpuCore.h"
4#include "rsContext.h" // XXX: necessary to avoid compiler error on rsScript.h below
5#include "rsScript.h"
6#include "rsType.h"
7
8namespace android {
9namespace renderscript {
10
11RsClosure rsi_ClosureCreate(Context* context, RsScriptKernelID kernelID,
12                            RsAllocation returnValue,
13                            RsScriptFieldID* fieldIDs, size_t fieldIDs_length,
14                            const int64_t* values, size_t values_length,
15                            const int* sizes, size_t sizes_length,
16                            RsClosure* depClosures, size_t depClosures_length,
17                            RsScriptFieldID* depFieldIDs,
18                            size_t depFieldIDs_length) {
19    rsAssert(fieldIDs_length == values_length && values_length == sizes_length &&
20             sizes_length == depClosures_length &&
21             depClosures_length == depFieldIDs_length);
22
23    Closure* c = new Closure(
24        context, (const ScriptKernelID*)kernelID, (Allocation*)returnValue,
25        fieldIDs_length, (const ScriptFieldID**)fieldIDs, values,
26        sizes, (const Closure**)depClosures,
27        (const ScriptFieldID**)depFieldIDs);
28    c->incUserRef();
29    return static_cast<RsClosure>(c);
30}
31
32RsClosure rsi_InvokeClosureCreate(Context* context, RsScriptInvokeID invokeID,
33                                  const void* params, const size_t paramLength,
34                                  const RsScriptFieldID* fieldIDs, const size_t fieldIDs_length,
35                                  const int64_t* values, const size_t values_length,
36                                  const int* sizes, const size_t sizes_length) {
37    rsAssert(fieldIDs_length == values_length && values_length == sizes_length);
38    Closure* c = new Closure(
39        context, (const ScriptInvokeID*)invokeID, params, paramLength,
40        fieldIDs_length, (const ScriptFieldID**)fieldIDs, values,
41        sizes);
42    c->incUserRef();
43    return static_cast<RsClosure>(c);
44}
45
46void rsi_ClosureSetArg(Context* rsc, RsClosure closure, uint32_t index,
47                       uintptr_t value, int size) {
48    ((Closure*)closure)->setArg(index, (const void*)value, size);
49}
50
51void rsi_ClosureSetGlobal(Context* rsc, RsClosure closure,
52                          RsScriptFieldID fieldID, int64_t value,
53                          int size) {
54    ((Closure*)closure)->setGlobal((const ScriptFieldID*)fieldID,
55                                   value, size);
56}
57
58Closure::Closure(Context* context,
59                 const ScriptKernelID* kernelID,
60                 Allocation* returnValue,
61                 const int numValues,
62                 const ScriptFieldID** fieldIDs,
63                 const int64_t* values,
64                 const int* sizes,
65                 const Closure** depClosures,
66                 const ScriptFieldID** depFieldIDs) :
67    ObjectBase(context), mContext(context), mFunctionID((IDBase*)kernelID),
68    mIsKernel(true), mReturnValue(returnValue), mParams(nullptr),
69    mParamLength(0) {
70    size_t i;
71
72    for (i = 0; i < (size_t)numValues && fieldIDs[i] == nullptr; i++);
73
74    mNumArg = i;
75    mArgs = new const void*[mNumArg];
76    for (size_t j = 0; j < mNumArg; j++) {
77        mArgs[j] = (const void*)values[j];
78    }
79
80    for (; i < (size_t)numValues; i++) {
81        rsAssert(fieldIDs[i] != nullptr);
82        mGlobals[fieldIDs[i]] = make_pair(values[i], sizes[i]);
83    }
84
85    for (i = 0; i < mNumArg; i++) {
86        const Closure* dep = depClosures[i];
87        if (dep != nullptr) {
88            auto mapping = mArgDeps[dep];
89            if (mapping == nullptr) {
90                mapping = new Map<int, ObjectBaseRef<ScriptFieldID>>();
91                mArgDeps[dep] = mapping;
92            }
93            (*mapping)[i].set(const_cast<ScriptFieldID*>(depFieldIDs[i]));
94        }
95    }
96
97    for (; i < (size_t)numValues; i++) {
98        const Closure* dep = depClosures[i];
99        if (dep != nullptr) {
100            auto mapping = mGlobalDeps[dep];
101            if (mapping == nullptr) {
102                mapping = new Map<const ScriptFieldID*,
103                                  ObjectBaseRef<ScriptFieldID>>();
104                mGlobalDeps[dep] = mapping;
105            }
106            fieldIDs[i]->incSysRef();
107            (*mapping)[fieldIDs[i]].set(const_cast<ScriptFieldID*>(depFieldIDs[i]));
108        }
109    }
110}
111
112Closure::Closure(Context* context, const ScriptInvokeID* invokeID,
113                 const void* params, const size_t paramLength,
114                 const size_t numValues, const ScriptFieldID** fieldIDs,
115                 const int64_t* values, const int* sizes) :
116    ObjectBase(context), mContext(context), mFunctionID((IDBase*)invokeID), mIsKernel(false),
117    mArgs(nullptr), mNumArg(0),
118    mReturnValue(nullptr), mParamLength(paramLength) {
119    mParams = new uint8_t[mParamLength];
120    memcpy(mParams, params, mParamLength);
121    for (size_t i = 0; i < numValues; i++) {
122        mGlobals[fieldIDs[i]] = make_pair(values[i], sizes[i]);
123    }
124}
125
126Closure::~Closure() {
127    for (const auto& p : mArgDeps) {
128        delete p.second;
129    }
130
131    for (const auto& p : mGlobalDeps) {
132        auto map = p.second;
133        for (const auto& p1 : *map) {
134            p1.first->decSysRef();
135        }
136        delete p.second;
137    }
138
139    delete[] mArgs;
140    delete[] mParams;
141}
142
143void Closure::setArg(const uint32_t index, const void* value, const int size) {
144    mArgs[index] = value;
145}
146
147void Closure::setGlobal(const ScriptFieldID* fieldID, const int64_t value,
148                        const int size) {
149    mGlobals[fieldID] = make_pair(value, size);
150}
151
152}  // namespace renderscript
153}  // namespace android
154