1 /*
2  * Copyright (C) 2009 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 
18 #include "rsContext.h"
19 
20 namespace android {
21 namespace renderscript {
22 
Element(Context * rsc)23 Element::Element(Context *rsc) : ObjectBase(rsc) {
24     mBits = 0;
25     mBitsUnpadded = 0;
26     mFields = nullptr;
27     mFieldCount = 0;
28     mHasReference = false;
29     memset(&mHal, 0, sizeof(mHal));
30 }
31 
~Element()32 Element::~Element() {
33     clear();
34 }
35 
operator delete(void * ptr)36 void Element::operator delete(void* ptr) {
37     if (ptr) {
38         Element *e = (Element*) ptr;
39         e->getContext()->mHal.funcs.freeRuntimeMem(ptr);
40     }
41 }
42 
preDestroy() const43 void Element::preDestroy() const {
44     auto& elements = mRSC->mStateElement.mElements;
45     for (uint32_t ct = 0; ct < elements.size(); ct++) {
46         if (elements[ct] == this) {
47             elements.erase(elements.begin() + ct);
48             break;
49         }
50     }
51 }
52 
clear()53 void Element::clear() {
54     if (mFields) {
55         for (size_t i = 0; i < mFieldCount; i++) {
56             delete[] mFields[i].name;
57         }
58         delete [] mFields;
59     }
60     mFields = nullptr;
61     mFieldCount = 0;
62     mHasReference = false;
63 
64     delete [] mHal.state.fields;
65     delete [] mHal.state.fieldArraySizes;
66     delete [] mHal.state.fieldNames;
67     delete [] mHal.state.fieldNameLengths;
68     delete [] mHal.state.fieldOffsetBytes;
69 }
70 
getSizeBits() const71 size_t Element::getSizeBits() const {
72     if (!mFieldCount) {
73         return mBits;
74     }
75 
76     size_t total = 0;
77     for (size_t ct=0; ct < mFieldCount; ct++) {
78         total += mFields[ct].e->mBits * mFields[ct].arraySize;
79     }
80     return total;
81 }
82 
getSizeBitsUnpadded() const83 size_t Element::getSizeBitsUnpadded() const {
84     if (!mFieldCount) {
85         return mBitsUnpadded;
86     }
87 
88     size_t total = 0;
89     for (size_t ct=0; ct < mFieldCount; ct++) {
90         total += mFields[ct].e->mBitsUnpadded * mFields[ct].arraySize;
91     }
92     return total;
93 }
94 
dumpLOGV(const char * prefix) const95 void Element::dumpLOGV(const char *prefix) const {
96     ObjectBase::dumpLOGV(prefix);
97     ALOGV("%s Element: fieldCount: %zu,  size bytes: %zu", prefix, mFieldCount, getSizeBytes());
98     mComponent.dumpLOGV(prefix);
99     for (uint32_t ct = 0; ct < mFieldCount; ct++) {
100         ALOGV("%s Element field index: %u ------------------", prefix, ct);
101         ALOGV("%s name: %s, offsetBits: %u, arraySize: %u",
102              prefix, mFields[ct].name, mFields[ct].offsetBits, mFields[ct].arraySize);
103         mFields[ct].e->dumpLOGV(prefix);
104     }
105 }
106 
serialize(Context * rsc,OStream * stream) const107 void Element::serialize(Context *rsc, OStream *stream) const {
108     // Need to identify ourselves
109     stream->addU32((uint32_t)getClassId());
110     stream->addString(getName());
111 
112     mComponent.serialize(stream);
113 
114     // Now serialize all the fields
115     stream->addU32(mFieldCount);
116     for (uint32_t ct = 0; ct < mFieldCount; ct++) {
117         stream->addString(mFields[ct].name);
118         stream->addU32(mFields[ct].arraySize);
119         mFields[ct].e->serialize(rsc, stream);
120     }
121 }
122 
createFromStream(Context * rsc,IStream * stream)123 Element *Element::createFromStream(Context *rsc, IStream *stream) {
124     // First make sure we are reading the correct object
125     RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
126     if (classID != RS_A3D_CLASS_ID_ELEMENT) {
127         ALOGE("element loading skipped due to invalid class id\n");
128         return nullptr;
129     }
130 
131     const char *name = stream->loadString();
132 
133     Component component;
134     component.loadFromStream(stream);
135 
136     uint32_t fieldCount = stream->loadU32();
137     if (!fieldCount) {
138         return (Element *)Element::create(rsc,
139                                           component.getType(),
140                                           component.getKind(),
141                                           component.getIsNormalized(),
142                                           component.getVectorSize());
143     }
144 
145     const Element **subElems = new const Element *[fieldCount];
146     const char **subElemNames = new const char *[fieldCount];
147     size_t *subElemNamesLengths = new size_t[fieldCount];
148     uint32_t *arraySizes = new uint32_t[fieldCount];
149 
150     for (uint32_t ct = 0; ct < fieldCount; ct ++) {
151         subElemNames[ct] = stream->loadString();
152         subElemNamesLengths[ct] = strlen(subElemNames[ct]);
153         arraySizes[ct] = stream->loadU32();
154         subElems[ct] = Element::createFromStream(rsc, stream);
155     }
156 
157     const Element *elem = Element::create(rsc, fieldCount, subElems, subElemNames,
158                                           subElemNamesLengths, arraySizes);
159     for (uint32_t ct = 0; ct < fieldCount; ct ++) {
160         delete [] subElemNames[ct];
161         subElems[ct]->decUserRef();
162     }
163     delete[] name;
164     delete[] subElems;
165     delete[] subElemNames;
166     delete[] subElemNamesLengths;
167     delete[] arraySizes;
168 
169     return (Element *)elem;
170 }
171 
compute()172 void Element::compute() {
173     mHal.state.dataType = mComponent.getType();
174     mHal.state.dataKind = mComponent.getKind();
175     mHal.state.vectorSize = mComponent.getVectorSize();
176 
177     if (mFieldCount == 0) {
178         mBits = mComponent.getBits();
179         mBitsUnpadded = mComponent.getBitsUnpadded();
180         mHasReference = mComponent.isReference();
181 
182         mHal.state.elementSizeBytes = getSizeBytes();
183         return;
184     }
185 
186     uint32_t noPaddingFieldCount = 0;
187     for (uint32_t ct = 0; ct < mFieldCount; ct ++) {
188         if (mFields[ct].name[0] != '#') {
189             noPaddingFieldCount ++;
190         }
191     }
192 
193     mHal.state.fields = new const Element*[noPaddingFieldCount];
194     mHal.state.fieldArraySizes = new uint32_t[noPaddingFieldCount];
195     mHal.state.fieldNames = new const char*[noPaddingFieldCount];
196     mHal.state.fieldNameLengths = new uint32_t[noPaddingFieldCount];
197     mHal.state.fieldOffsetBytes = new uint32_t[noPaddingFieldCount];
198     mHal.state.fieldsCount = noPaddingFieldCount;
199 
200     size_t bits = 0;
201     size_t bitsUnpadded = 0;
202     for (size_t ct = 0, ctNoPadding = 0; ct < mFieldCount; ct++) {
203         mFields[ct].offsetBits = bits;
204         mFields[ct].offsetBitsUnpadded = bitsUnpadded;
205         bits += mFields[ct].e->getSizeBits() * mFields[ct].arraySize;
206         bitsUnpadded += mFields[ct].e->getSizeBitsUnpadded() * mFields[ct].arraySize;
207 
208         if (mFields[ct].e->mHasReference) {
209             mHasReference = true;
210         }
211 
212         if (mFields[ct].name[0] == '#') {
213             continue;
214         }
215 
216         mHal.state.fields[ctNoPadding] = mFields[ct].e.get();
217         mHal.state.fieldArraySizes[ctNoPadding] = mFields[ct].arraySize;
218         mHal.state.fieldNames[ctNoPadding] = mFields[ct].name;
219         mHal.state.fieldNameLengths[ctNoPadding] = strlen(mFields[ct].name) + 1; // to include 0
220         mHal.state.fieldOffsetBytes[ctNoPadding] = mFields[ct].offsetBits >> 3;
221 
222         ctNoPadding ++;
223     }
224 
225     mBits = bits;
226     mBitsUnpadded = bitsUnpadded;
227     mHal.state.elementSizeBytes = getSizeBytes();
228 }
229 
createRef(Context * rsc,RsDataType dt,RsDataKind dk,bool isNorm,uint32_t vecSize)230 ObjectBaseRef<const Element> Element::createRef(Context *rsc, RsDataType dt, RsDataKind dk,
231                                 bool isNorm, uint32_t vecSize) {
232     ObjectBaseRef<const Element> returnRef;
233     // Look for an existing match.
234     ObjectBase::asyncLock();
235     for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
236         const Element *ee = rsc->mStateElement.mElements[ct];
237         if (!ee->getFieldCount() &&
238             (ee->getComponent().getType() == dt) &&
239             (ee->getComponent().getKind() == dk) &&
240             (ee->getComponent().getIsNormalized() == isNorm) &&
241             (ee->getComponent().getVectorSize() == vecSize)) {
242             // Match
243             returnRef.set(ee);
244             ObjectBase::asyncUnlock();
245             return ee;
246         }
247     }
248     ObjectBase::asyncUnlock();
249 
250     // Element objects must use allocator specified by the driver
251     void* allocMem = rsc->mHal.funcs.allocRuntimeMem(sizeof(Element), 0);
252     if (!allocMem) {
253         rsc->setError(RS_ERROR_FATAL_DRIVER, "Couldn't allocate memory for Element");
254         return nullptr;
255     }
256 
257     Element *e = new (allocMem) Element(rsc);
258     returnRef.set(e);
259     e->mComponent.set(dt, dk, isNorm, vecSize);
260     e->compute();
261 
262 #ifdef RS_FIND_OFFSETS
263     ALOGE("pointer for element: %p", e);
264     ALOGE("pointer for element.drv: %p", &e->mHal.drv);
265 #endif
266 
267 
268     ObjectBase::asyncLock();
269     rsc->mStateElement.mElements.push_back(e);
270     ObjectBase::asyncUnlock();
271 
272     return returnRef;
273 }
274 
createRef(Context * rsc,size_t count,const Element ** ein,const char ** nin,const size_t * lengths,const uint32_t * asin)275 ObjectBaseRef<const Element> Element::createRef(Context *rsc, size_t count, const Element **ein,
276                             const char **nin, const size_t * lengths, const uint32_t *asin) {
277 
278     ObjectBaseRef<const Element> returnRef;
279     // Look for an existing match.
280     ObjectBase::asyncLock();
281     for (uint32_t ct=0; ct < rsc->mStateElement.mElements.size(); ct++) {
282         const Element *ee = rsc->mStateElement.mElements[ct];
283         if (ee->getFieldCount() == count) {
284             bool match = true;
285             for (uint32_t i=0; i < count; i++) {
286                 size_t len;
287                 uint32_t asize = 1;
288                 if (lengths) {
289                     len = lengths[i];
290                 } else {
291                     len = strlen(nin[i]);
292                 }
293                 if (asin) {
294                     asize = asin[i];
295                 }
296 
297                 if ((ee->mFields[i].e.get() != ein[i]) ||
298                     (strlen(ee->mFields[i].name) != len) ||
299                     strcmp(ee->mFields[i].name, nin[i]) ||
300                     (ee->mFields[i].arraySize != asize)) {
301                     match = false;
302                     break;
303                 }
304             }
305             if (match) {
306                 returnRef.set(ee);
307                 ObjectBase::asyncUnlock();
308                 return returnRef;
309             }
310         }
311     }
312     ObjectBase::asyncUnlock();
313 
314     // Element objects must use allocator specified by the driver
315     void* allocMem = rsc->mHal.funcs.allocRuntimeMem(sizeof(Element), 0);
316     if (!allocMem) {
317         rsc->setError(RS_ERROR_FATAL_DRIVER, "Couldn't allocate memory for Element");
318         return nullptr;
319     }
320 
321     Element *e = new (allocMem) Element(rsc);
322     returnRef.set(e);
323     e->mFields = new ElementField_t [count];
324     e->mFieldCount = count;
325     for (size_t ct=0; ct < count; ct++) {
326         size_t len;
327         uint32_t asize = 1;
328         if (lengths) {
329             len = lengths[ct];
330         } else {
331             len = strlen(nin[ct]);
332         }
333         if (asin) {
334             asize = asin[ct];
335         }
336 
337         e->mFields[ct].e.set(ein[ct]);
338         e->mFields[ct].name = rsuCopyString(nin[ct], len);
339         e->mFields[ct].arraySize = asize;
340     }
341     e->compute();
342 
343     ObjectBase::asyncLock();
344     rsc->mStateElement.mElements.push_back(e);
345     ObjectBase::asyncUnlock();
346 
347     return returnRef;
348 }
349 
incRefs(const void * ptr) const350 void Element::incRefs(const void *ptr) const {
351     if (!mFieldCount) {
352         if (mComponent.isReference()) {
353             ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr);
354             ObjectBase *ob = obp[0];
355             if (ob) ob->incSysRef();
356         }
357         return;
358     }
359 
360     const uint8_t *p = static_cast<const uint8_t *>(ptr);
361     for (uint32_t i=0; i < mFieldCount; i++) {
362         if (mFields[i].e->mHasReference) {
363             const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
364             for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
365                 mFields[i].e->incRefs(p2);
366                 p2 += mFields[i].e->getSizeBytes();
367             }
368         }
369     }
370 }
371 
decRefs(const void * ptr) const372 void Element::decRefs(const void *ptr) const {
373     if (!mFieldCount) {
374         if (mComponent.isReference()) {
375             ObjectBase *const*obp = static_cast<ObjectBase *const*>(ptr);
376             ObjectBase *ob = obp[0];
377             if (ob) ob->decSysRef();
378         }
379         return;
380     }
381 
382     const uint8_t *p = static_cast<const uint8_t *>(ptr);
383     for (uint32_t i=0; i < mFieldCount; i++) {
384         if (mFields[i].e->mHasReference) {
385             const uint8_t *p2 = &p[mFields[i].offsetBits >> 3];
386             for (uint32_t ct=0; ct < mFields[i].arraySize; ct++) {
387                 mFields[i].e->decRefs(p2);
388                 p2 += mFields[i].e->getSizeBytes();
389             }
390         }
391     }
392 }
393 
callUpdateCacheObject(const Context * rsc,void * dstObj) const394 void Element::callUpdateCacheObject(const Context *rsc, void *dstObj) const {
395     if (rsc->mHal.funcs.element.updateCachedObject != nullptr) {
396         rsc->mHal.funcs.element.updateCachedObject(rsc, this, (rs_element *)dstObj);
397     } else {
398         *((const void **)dstObj) = this;
399     }
400 }
401 
ElementState()402 ElementState::ElementState() {
403 }
404 
~ElementState()405 ElementState::~ElementState() {
406     rsAssert(!mElements.size());
407 }
408 
409 /////////////////////////////////////////
410 //
411 
rsi_ElementCreate(Context * rsc,RsDataType dt,RsDataKind dk,bool norm,uint32_t vecSize)412 RsElement rsi_ElementCreate(Context *rsc,
413                             RsDataType dt,
414                             RsDataKind dk,
415                             bool norm,
416                             uint32_t vecSize) {
417     return (RsElement)Element::create(rsc, dt, dk, norm, vecSize);
418 }
419 
420 
rsi_ElementCreate2(Context * rsc,const RsElement * ein,size_t ein_length,const char ** names,size_t nameLengths_length,const size_t * nameLengths,const uint32_t * arraySizes,size_t arraySizes_length)421 RsElement rsi_ElementCreate2(Context *rsc,
422                              const RsElement * ein,
423                              size_t ein_length,
424 
425                              const char ** names,
426                              size_t nameLengths_length,
427                              const size_t * nameLengths,
428 
429                              const uint32_t * arraySizes,
430                              size_t arraySizes_length) {
431     return (RsElement)Element::create(rsc, ein_length, (const Element **)ein,
432                                       names, nameLengths, arraySizes);
433 }
434 
435 } // namespace renderscript
436 } // namespace android
437