rsType.cpp revision 554d08c462bd244dcbeb46df861bae4a380deb53
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 "rsContext.h"
18
19#if !defined(RS_SERVER) && !defined(RS_COMPATIBILITY_LIB)
20#include "system/graphics.h"
21#endif
22
23#ifdef RS_COMPATIBILITY_LIB
24#include "rsCompatibilityLib.h"
25#endif
26
27using namespace android;
28using namespace android::renderscript;
29
30Type::Type(Context *rsc) : ObjectBase(rsc) {
31    memset(&mHal, 0, sizeof(mHal));
32    mDimLOD = false;
33}
34
35void Type::preDestroy() const {
36    auto &types = mRSC->mStateType.mTypes;
37
38    for (auto typeIter = types.begin(), endIter = types.end();
39         typeIter != endIter; typeIter++) {
40
41        if (this == *typeIter) {
42            types.erase(typeIter);
43            return;
44        }
45    }
46}
47
48Type::~Type() {
49    clear();
50}
51
52void Type::operator delete(void* ptr) {
53    if (ptr) {
54        Type *t = (Type*) ptr;
55        t->getContext()->mHal.funcs.freeRuntimeMem(ptr);
56    }
57}
58
59void Type::clear() {
60    if (mHal.state.lodCount) {
61        delete [] mHal.state.lodDimX;
62        delete [] mHal.state.lodDimY;
63        delete [] mHal.state.lodDimZ;
64    }
65    if (mHal.state.arrayCount > 0) {
66        delete [] mHal.state.arrays;
67    }
68    mElement.clear();
69    memset(&mHal, 0, sizeof(mHal));
70}
71
72TypeState::TypeState() {
73}
74
75TypeState::~TypeState() {
76    rsAssert(!mTypes.size());
77}
78
79void Type::compute() {
80    uint32_t oldLODCount = mHal.state.lodCount;
81    if (mDimLOD) {
82        uint32_t l2x = rsFindHighBit(mHal.state.dimX) + 1;
83        uint32_t l2y = rsFindHighBit(mHal.state.dimY) + 1;
84        uint32_t l2z = rsFindHighBit(mHal.state.dimZ) + 1;
85
86        mHal.state.lodCount = rsMax(l2x, l2y);
87        mHal.state.lodCount = rsMax(mHal.state.lodCount, l2z);
88    } else {
89        if (mHal.state.dimYuv) {
90            mHal.state.lodCount = 3;
91        } else {
92            mHal.state.lodCount = 1;
93        }
94    }
95    if (mHal.state.lodCount != oldLODCount) {
96        if (oldLODCount) {
97            delete [] mHal.state.lodDimX;
98            delete [] mHal.state.lodDimY;
99            delete [] mHal.state.lodDimZ;
100        }
101        mHal.state.lodDimX = new uint32_t[mHal.state.lodCount];
102        mHal.state.lodDimY = new uint32_t[mHal.state.lodCount];
103        mHal.state.lodDimZ = new uint32_t[mHal.state.lodCount];
104    }
105
106    uint32_t tx = mHal.state.dimX;
107    uint32_t ty = mHal.state.dimY;
108    uint32_t tz = mHal.state.dimZ;
109    mCellCount = 0;
110    if (!mHal.state.dimYuv) {
111        for (uint32_t lod=0; lod < mHal.state.lodCount; lod++) {
112            mHal.state.lodDimX[lod] = tx;
113            mHal.state.lodDimY[lod] = ty;
114            mHal.state.lodDimZ[lod]  = tz;
115            mCellCount += tx * rsMax(ty, 1u) * rsMax(tz, 1u);
116            if (tx > 1) tx >>= 1;
117            if (ty > 1) ty >>= 1;
118            if (tz > 1) tz >>= 1;
119        }
120    }
121
122    if (mHal.state.faces) {
123        mCellCount *= 6;
124    }
125#ifndef RS_SERVER
126    // YUV only supports basic 2d
127    // so we can stash the plane pointers in the mipmap levels.
128    if (mHal.state.dimYuv) {
129        mHal.state.lodDimX[1] = mHal.state.lodDimX[0] / 2;
130        mHal.state.lodDimY[1] = mHal.state.lodDimY[0] / 2;
131        mHal.state.lodDimX[2] = mHal.state.lodDimX[0] / 2;
132        mHal.state.lodDimY[2] = mHal.state.lodDimY[0] / 2;
133        mCellCount += mHal.state.lodDimX[0] * mHal.state.lodDimY[0];
134        mCellCount += mHal.state.lodDimX[1] * mHal.state.lodDimY[1];
135        mCellCount += mHal.state.lodDimX[2] * mHal.state.lodDimY[2];
136
137        switch(mHal.state.dimYuv) {
138        case HAL_PIXEL_FORMAT_YV12:
139            break;
140        case HAL_PIXEL_FORMAT_YCrCb_420_SP:  // NV21
141            mHal.state.lodDimX[1] = mHal.state.lodDimX[0];
142            break;
143#ifndef RS_COMPATIBILITY_LIB
144        case HAL_PIXEL_FORMAT_YCbCr_420_888:
145            break;
146#endif
147        default:
148            rsAssert(0);
149        }
150    }
151#endif
152    mHal.state.element = mElement.get();
153}
154
155void Type::dumpLOGV(const char *prefix) const {
156    char buf[1024];
157    ObjectBase::dumpLOGV(prefix);
158    ALOGV("%s   Type: x=%u y=%u z=%u mip=%i face=%i", prefix,
159                                                      mHal.state.dimX,
160                                                      mHal.state.dimY,
161                                                      mHal.state.dimZ,
162                                                      mHal.state.lodCount,
163                                                      mHal.state.faces);
164    snprintf(buf, sizeof(buf), "%s element: ", prefix);
165    mElement->dumpLOGV(buf);
166}
167
168void Type::serialize(Context *rsc, OStream *stream) const {
169    // Need to identify ourselves
170    stream->addU32((uint32_t)getClassId());
171    stream->addString(getName());
172
173    mElement->serialize(rsc, stream);
174
175    stream->addU32(mHal.state.dimX);
176    stream->addU32(mHal.state.dimY);
177    stream->addU32(mHal.state.dimZ);
178
179    stream->addU8((uint8_t)(mHal.state.lodCount ? 1 : 0));
180    stream->addU8((uint8_t)(mHal.state.faces ? 1 : 0));
181}
182
183Type *Type::createFromStream(Context *rsc, IStream *stream) {
184    // First make sure we are reading the correct object
185    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
186    if (classID != RS_A3D_CLASS_ID_TYPE) {
187        ALOGE("type loading skipped due to invalid class id\n");
188        return nullptr;
189    }
190
191    const char *name = stream->loadString();
192
193    Element *elem = Element::createFromStream(rsc, stream);
194    if (!elem) {
195        return nullptr;
196    }
197
198    RsTypeCreateParams p;
199    memset(&p, 0, sizeof(p));
200    p.dimX = stream->loadU32();
201    p.dimY = stream->loadU32();
202    p.dimZ = stream->loadU32();
203    p.mipmaps = stream->loadU8();
204    p.faces = stream->loadU8();
205    Type *type = Type::getType(rsc, elem, &p, sizeof(p));
206    elem->decUserRef();
207
208    delete [] name;
209    return type;
210}
211
212bool Type::getIsNp2() const {
213    uint32_t x = getDimX();
214    uint32_t y = getDimY();
215    uint32_t z = getDimZ();
216
217    if (x && (x & (x-1))) {
218        return true;
219    }
220    if (y && (y & (y-1))) {
221        return true;
222    }
223    if (z && (z & (z-1))) {
224        return true;
225    }
226    return false;
227}
228
229ObjectBaseRef<Type> Type::getTypeRef(Context *rsc, const Element *e,
230                                     const RsTypeCreateParams *params, size_t len) {
231    ObjectBaseRef<Type> returnRef;
232
233    TypeState * stc = &rsc->mStateType;
234
235    ObjectBase::asyncLock();
236    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
237        Type *t = stc->mTypes[ct];
238        if (t->getElement() != e) continue;
239        if (t->getDimX() != params->dimX) continue;
240        if (t->getDimY() != params->dimY) continue;
241        if (t->getDimZ() != params->dimZ) continue;
242        if (t->getDimLOD() != params->mipmaps) continue;
243        if (t->getDimFaces() != params->faces) continue;
244        if (t->getDimYuv() != params->yuv) continue;
245        if (t->getArray(0) != params->array0) continue;
246        if (t->getArray(1) != params->array1) continue;
247        if (t->getArray(2) != params->array2) continue;
248        if (t->getArray(3) != params->array3) continue;
249        returnRef.set(t);
250        ObjectBase::asyncUnlock();
251        return returnRef;
252    }
253    ObjectBase::asyncUnlock();
254
255    // Type objects must use allocator specified by the driver
256    void* allocMem = rsc->mHal.funcs.allocRuntimeMem(sizeof(Type), 0);
257    if (!allocMem) {
258        rsc->setError(RS_ERROR_FATAL_DRIVER, "Couldn't allocate memory for Type");
259        return nullptr;
260    }
261
262    Type *nt = new (allocMem) Type(rsc);
263
264#ifdef RS_FIND_OFFSETS
265    ALOGE("pointer for type: %p", nt);
266    ALOGE("pointer for type.drv: %p", &nt->mHal.drv);
267#endif
268
269    nt->mDimLOD = params->mipmaps;
270    returnRef.set(nt);
271    nt->mElement.set(e);
272    nt->mHal.state.dimX = params->dimX;
273    nt->mHal.state.dimY = params->dimY;
274    nt->mHal.state.dimZ = params->dimZ;
275    nt->mHal.state.faces = params->faces;
276    nt->mHal.state.dimYuv = params->yuv;
277
278    nt->mHal.state.arrayCount = 0;
279    if (params->array0 > 0) nt->mHal.state.arrayCount ++;
280    if (params->array1 > 0) nt->mHal.state.arrayCount ++;
281    if (params->array2 > 0) nt->mHal.state.arrayCount ++;
282    if (params->array3 > 0) nt->mHal.state.arrayCount ++;
283    if (nt->mHal.state.arrayCount > 0) {
284        nt->mHal.state.arrays = new uint32_t[nt->mHal.state.arrayCount];
285        if (params->array0 > 0) nt->mHal.state.arrays[0] = params->array0;
286        if (params->array1 > 1) nt->mHal.state.arrays[1] = params->array1;
287        if (params->array2 > 2) nt->mHal.state.arrays[2] = params->array2;
288        if (params->array3 > 3) nt->mHal.state.arrays[3] = params->array3;
289    }
290
291    nt->compute();
292
293    ObjectBase::asyncLock();
294    stc->mTypes.push_back(nt);
295    ObjectBase::asyncUnlock();
296
297    return returnRef;
298}
299
300ObjectBaseRef<Type> Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const {
301    RsTypeCreateParams p;
302    memset(&p, 0, sizeof(p));
303    p.dimX = dimX;
304    p.dimY = getDimY();
305    p.dimZ = getDimZ();
306    p.mipmaps = getDimLOD();
307    return getTypeRef(rsc, mElement.get(), &p, sizeof(p));
308}
309
310ObjectBaseRef<Type> Type::cloneAndResize2D(Context *rsc,
311                              uint32_t dimX,
312                              uint32_t dimY) const {
313    RsTypeCreateParams p;
314    memset(&p, 0, sizeof(p));
315    p.dimX = dimX;
316    p.dimY = dimY;
317    p.dimZ = getDimZ();
318    p.mipmaps = getDimLOD();
319    p.faces = getDimFaces();
320    p.yuv = getDimYuv();
321    return getTypeRef(rsc, mElement.get(), &p, sizeof(p));
322}
323
324
325void Type::incRefs(const void *ptr, size_t ct, size_t startOff) const {
326    const uint8_t *p = static_cast<const uint8_t *>(ptr);
327    const Element *e = mHal.state.element;
328    uint32_t stride = e->getSizeBytes();
329
330    p += stride * startOff;
331    while (ct > 0) {
332        e->incRefs(p);
333        ct--;
334        p += stride;
335    }
336}
337
338
339void Type::decRefs(const void *ptr, size_t ct, size_t startOff) const {
340    if (!mHal.state.element->getHasReferences()) {
341        return;
342    }
343    const uint8_t *p = static_cast<const uint8_t *>(ptr);
344    const Element *e = mHal.state.element;
345    uint32_t stride = e->getSizeBytes();
346
347    p += stride * startOff;
348    while (ct > 0) {
349        e->decRefs(p);
350        ct--;
351        p += stride;
352    }
353}
354
355void Type::callUpdateCacheObject(const Context *rsc, void *dstObj) const {
356    if (rsc->mHal.funcs.type.updateCachedObject != nullptr) {
357        rsc->mHal.funcs.type.updateCachedObject(rsc, this, (rs_type *)dstObj);
358    } else {
359        *((const void **)dstObj) = this;
360    }
361}
362
363//////////////////////////////////////////////////
364//
365namespace android {
366namespace renderscript {
367
368RsType rsi_TypeCreate(Context *rsc, RsElement _e, uint32_t dimX,
369                     uint32_t dimY, uint32_t dimZ, bool mipmaps, bool faces, uint32_t yuv) {
370    Element *e = static_cast<Element *>(_e);
371
372    RsTypeCreateParams p;
373    memset(&p, 0, sizeof(p));
374    p.dimX = dimX;
375    p.dimY = dimY;
376    p.dimZ = dimZ;
377    p.mipmaps = mipmaps;
378    p.faces = faces;
379    p.yuv = yuv;
380    return Type::getType(rsc, e, &p, sizeof(p));
381}
382
383RsType rsi_TypeCreate2(Context *rsc, const RsTypeCreateParams *p, size_t len) {
384    Element *e = static_cast<Element *>(p->e);
385    return Type::getType(rsc, e, p, len);
386}
387
388}
389}
390
391extern "C" void rsaTypeGetNativeData(RsContext con, RsType type, uintptr_t *typeData, uint32_t typeDataSize) {
392    rsAssert(typeDataSize == 6);
393    // Pack the data in the follofing way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ;
394    // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
395    Type *t = static_cast<Type *>(type);
396
397    (*typeData++) = t->getDimX();
398    (*typeData++) = t->getDimY();
399    (*typeData++) = t->getDimZ();
400    (*typeData++) = t->getDimLOD() ? 1 : 0;
401    (*typeData++) = t->getDimFaces() ? 1 : 0;
402    (*typeData++) = (uintptr_t)t->getElement();
403    t->getElement()->incUserRef();
404}
405