rsClosure.cpp revision eb9aa675754c49f613c6ad71d41472b30f38b007
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
42void rsi_ClosureEval(Context* rsc, RsClosure closure) {
43    ((Closure*)closure)->eval();
44}
45
46void rsi_ClosureSetArg(Context* rsc, RsClosure closure, uint32_t index,
47                       uintptr_t value, size_t size) {
48    ((Closure*)closure)->setArg(index, (const void*)value, size);
49}
50
51void rsi_ClosureSetGlobal(Context* rsc, RsClosure closure,
52                          RsScriptFieldID fieldID, uintptr_t value,
53                          size_t size) {
54    ((Closure*)closure)->setGlobal((const ScriptFieldID*)fieldID,
55                                   (const void*)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 void** values,
64                 const size_t* sizes,
65                 const Closure** depClosures,
66                 const ScriptFieldID** depFieldIDs) :
67    ObjectBase(context), mContext(context), mKernelID((ScriptKernelID*)kernelID),
68    mInvokeID(nullptr), 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  vector<const void*> args(values, values + i);
75  mArgs.swap(args);
76
77  for (; i < (size_t)numValues; i++) {
78    mGlobals[fieldIDs[i]] = std::make_pair(values[i], sizes[i]);
79  }
80
81  mDependences.insert(depClosures, depClosures + numValues);
82
83  for (i = 0; i < mArgs.size(); i++) {
84    const Closure* dep = depClosures[i];
85    if (dep != nullptr) {
86      auto mapping = mArgDeps[dep];
87      if (mapping == nullptr) {
88        mapping = new map<int, const ObjectBaseRef<ScriptFieldID>*>();
89        mArgDeps[dep] = mapping;
90      }
91      (*mapping)[i] = new ObjectBaseRef<ScriptFieldID>(
92          const_cast<ScriptFieldID*>(depFieldIDs[i]));
93    }
94  }
95
96  for (; i < (size_t)numValues; i++) {
97    const Closure* dep = depClosures[i];
98    if (dep != nullptr) {
99      auto mapping = mGlobalDeps[dep];
100      if (mapping == nullptr) {
101        mapping = new map<const ObjectBaseRef<ScriptFieldID>*,
102            const ObjectBaseRef<ScriptFieldID>*>();
103        mGlobalDeps[dep] = mapping;
104      }
105      (*mapping)[new ObjectBaseRef<ScriptFieldID>(
106          const_cast<ScriptFieldID*>(fieldIDs[i]))] =
107          new ObjectBaseRef<ScriptFieldID>(
108              const_cast<ScriptFieldID*>(depFieldIDs[i]));
109    }
110  }
111}
112
113Closure::Closure(Context* context, const ScriptInvokeID* invokeID,
114                 const void* params, const size_t paramLength,
115                 const size_t numValues, const ScriptFieldID** fieldIDs,
116                 const void** values, const size_t* sizes) :
117    ObjectBase(context), mContext(context), mKernelID(nullptr), mInvokeID(invokeID),
118    mReturnValue(nullptr), mParams(params), mParamLength(paramLength) {
119    for (size_t i = 0; i < numValues; i++) {
120        mGlobals[fieldIDs[i]] = std::make_pair(values[i], sizes[i]);
121    }
122}
123
124Closure::~Closure() {
125    for (const auto& p : mArgDeps) {
126        auto map = p.second;
127        for (const auto& p1 : *map) {
128            delete p1.second;
129        }
130        delete p.second;
131    }
132
133    for (const auto& p : mGlobalDeps) {
134        auto map = p.second;
135        for (const auto& p1 : *map) {
136            delete p1.first;
137            delete p1.second;
138        }
139        delete p.second;
140    }
141}
142
143void Closure::eval() {
144    Script *s = mKernelID->mScript;
145
146    for (const auto& p : mGlobals) {
147        const void* value = p.second.first;
148        int size = p.second.second;
149        // We use -1 size to indicate an ObjectBase rather than a primitive type
150        if (size < 0) {
151            s->setVarObj(p.first->mSlot, (ObjectBase*)value);
152        } else {
153            s->setVar(p.first->mSlot, (const void*)&value, size);
154        }
155    }
156
157    s->runForEach(mContext, mKernelID->mSlot, (const Allocation **)(&mArgs[0]),
158                  mArgs.size(), mReturnValue, nullptr, 0, nullptr);
159}
160
161void Closure::setArg(const uint32_t index, const void* value, const size_t size) {
162    mArgs[index] = value;
163}
164
165void Closure::setGlobal(const ScriptFieldID* fieldID, const void* value,
166                        const size_t size) {
167    mGlobals[fieldID] = std::make_pair(value, size);
168}
169
170}  // namespace renderscript
171}  // namespace android
172