rsClosure.cpp revision 062c287f573ecc06c38ee4295e5627e12c52ac3d
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                            uintptr_t* values, size_t values_length,
15                            size_t* 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    return (RsClosure)(new Closure(
24        context, (const ScriptKernelID*)kernelID, (Allocation*)returnValue,
25        fieldIDs_length, (const ScriptFieldID**)fieldIDs, (const void**)values,
26        sizes, (const Closure**)depClosures,
27        (const ScriptFieldID**)depFieldIDs));
28}
29
30RsClosure rsi_InvokeClosureCreate(Context* context, RsScriptInvokeID invokeID,
31                                  const void* params, const size_t paramLength,
32                                  const RsScriptFieldID* fieldIDs, const size_t fieldIDs_length,
33                                  const uintptr_t* values, const size_t values_length,
34                                  const size_t* sizes, const size_t sizes_length) {
35    rsAssert(fieldIDs_length == values_length && values_length == sizes_length);
36    return (RsClosure)(new Closure(
37        context, (const ScriptInvokeID*)invokeID, params, paramLength,
38        fieldIDs_length, (const ScriptFieldID**)fieldIDs, (const void**)values,
39        sizes));
40}
41
42#if 0
43void rsi_ClosureEval(Context* rsc, RsClosure closure) {
44    ((Closure*)closure)->eval();
45}
46#endif
47
48void rsi_ClosureSetArg(Context* rsc, RsClosure closure, uint32_t index,
49                       uintptr_t value, size_t size) {
50    ((Closure*)closure)->setArg(index, (const void*)value, size);
51}
52
53void rsi_ClosureSetGlobal(Context* rsc, RsClosure closure,
54                          RsScriptFieldID fieldID, uintptr_t value,
55                          size_t size) {
56    ((Closure*)closure)->setGlobal((const ScriptFieldID*)fieldID,
57                                   (const void*)value, size);
58}
59
60Closure::Closure(Context* context,
61                 const ScriptKernelID* kernelID,
62                 Allocation* returnValue,
63                 const int numValues,
64                 const ScriptFieldID** fieldIDs,
65                 const void** values,
66                 const size_t* sizes,
67                 const Closure** depClosures,
68                 const ScriptFieldID** depFieldIDs) :
69    ObjectBase(context), mContext(context), mFunctionID((IDBase*)kernelID),
70    mIsKernel(true), mReturnValue(returnValue), mParams(nullptr),
71    mParamLength(0) {
72    size_t i;
73
74    for (i = 0; i < (size_t)numValues && fieldIDs[i] == nullptr; i++);
75
76    mNumArg = i;
77    mArgs = new const void*[mNumArg];
78    memcpy(mArgs, values, sizeof(const void*) * mNumArg);
79
80    for (; i < (size_t)numValues; i++) {
81        rsAssert(fieldIDs[i] != nullptr);
82        mGlobals[fieldIDs[i]] = make_pair(values[i], sizes[i]);
83        ALOGV("Creating closure %p, binding field %p (Script %p, slot: %d)",
84              this, fieldIDs[i], fieldIDs[i]->mScript, fieldIDs[i]->mSlot);
85    }
86
87    size_t j = mNumArg;
88    for (const auto& p : mGlobals) {
89        rsAssert(p.first == fieldIDs[j]);
90        rsAssert(p.second.first == values[j]);
91        rsAssert(p.second.second == sizes[j]);
92        j++;
93    }
94
95    for (i = 0; i < mNumArg; i++) {
96        const Closure* dep = depClosures[i];
97        if (dep != nullptr) {
98            auto mapping = mArgDeps[dep];
99            if (mapping == nullptr) {
100                mapping = new Map<int, const ObjectBaseRef<ScriptFieldID>*>();
101                mArgDeps[dep] = mapping;
102            }
103            (*mapping)[i] = new ObjectBaseRef<ScriptFieldID>(
104                const_cast<ScriptFieldID*>(depFieldIDs[i]));
105        }
106    }
107
108    for (; i < (size_t)numValues; i++) {
109        const Closure* dep = depClosures[i];
110        if (dep != nullptr) {
111            auto mapping = mGlobalDeps[dep];
112            if (mapping == nullptr) {
113                mapping = new Map<const ObjectBaseRef<ScriptFieldID>*,
114                                  const ObjectBaseRef<ScriptFieldID>*>();
115                mGlobalDeps[dep] = mapping;
116            }
117            (*mapping)[new ObjectBaseRef<ScriptFieldID>(
118                const_cast<ScriptFieldID*>(fieldIDs[i]))] =
119                    new ObjectBaseRef<ScriptFieldID>(
120                        const_cast<ScriptFieldID*>(depFieldIDs[i]));
121        }
122    }
123}
124
125Closure::Closure(Context* context, const ScriptInvokeID* invokeID,
126                 const void* params, const size_t paramLength,
127                 const size_t numValues, const ScriptFieldID** fieldIDs,
128                 const void** values, const size_t* sizes) :
129    ObjectBase(context), mContext(context), mFunctionID((IDBase*)invokeID), mIsKernel(false),
130    mReturnValue(nullptr), mParams(params), mParamLength(paramLength) {
131    for (size_t i = 0; i < numValues; i++) {
132        mGlobals[fieldIDs[i]] = make_pair(values[i], sizes[i]);
133    }
134}
135
136Closure::~Closure() {
137    for (const auto& p : mArgDeps) {
138        auto map = p.second;
139        for (const auto& p1 : *map) {
140            delete p1.second;
141        }
142        delete p.second;
143    }
144
145    for (const auto& p : mGlobalDeps) {
146        auto map = p.second;
147        for (const auto& p1 : *map) {
148            delete p1.first;
149            delete p1.second;
150        }
151        delete p.second;
152    }
153
154    delete[] mArgs;
155}
156
157void Closure::setArg(const uint32_t index, const void* value, const size_t size) {
158    mArgs[index] = value;
159}
160
161void Closure::setGlobal(const ScriptFieldID* fieldID, const void* value,
162                        const size_t size) {
163    mGlobals[fieldID] = make_pair(value, size);
164}
165
166}  // namespace renderscript
167}  // namespace android
168