rsType.cpp revision 2353ae303868d04e3a26002b2f2dc456c15e8170
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#ifndef ANDROID_RS_BUILD_FOR_HOST
18#include "rsContext.h"
19#include <GLES/gl.h>
20#else
21#include "rsContextHostStub.h"
22#include <OpenGL/gl.h>
23#endif
24
25using namespace android;
26using namespace android::renderscript;
27
28Type::Type(Context *rsc) : ObjectBase(rsc)
29{
30    mAllocFile = __FILE__;
31    mAllocLine = __LINE__;
32    mLODs = 0;
33    mLODCount = 0;
34    mAttribs = NULL;
35    mAttribsSize = 0;
36    clear();
37}
38
39Type::~Type()
40{
41    for (uint32_t ct = 0; ct < mRSC->mStateType.mTypes.size(); ct++) {
42        if (mRSC->mStateType.mTypes[ct] == this) {
43            mRSC->mStateType.mTypes.removeAt(ct);
44            break;
45        }
46    }
47    if (mLODs) {
48        delete [] mLODs;
49        mLODs = NULL;
50    }
51    if(mAttribs) {
52        delete [] mAttribs;
53        mAttribs = NULL;
54    }
55}
56
57void Type::clear()
58{
59    if (mLODs) {
60        delete [] mLODs;
61        mLODs = NULL;
62    }
63    mDimX = 0;
64    mDimY = 0;
65    mDimZ = 0;
66    mDimLOD = 0;
67    mFaces = false;
68    mElement.clear();
69}
70
71TypeState::TypeState()
72{
73}
74
75TypeState::~TypeState()
76{
77}
78
79size_t Type::getOffsetForFace(uint32_t face) const
80{
81    rsAssert(mFaces);
82    return 0;
83}
84
85void Type::compute()
86{
87    uint32_t oldLODCount = mLODCount;
88    if (mDimLOD) {
89        uint32_t l2x = rsFindHighBit(mDimX) + 1;
90        uint32_t l2y = rsFindHighBit(mDimY) + 1;
91        uint32_t l2z = rsFindHighBit(mDimZ) + 1;
92
93        mLODCount = rsMax(l2x, l2y);
94        mLODCount = rsMax(mLODCount, l2z);
95    } else {
96        mLODCount = 1;
97    }
98    if (mLODCount != oldLODCount) {
99        if(mLODs){
100            delete [] mLODs;
101        }
102        mLODs = new LOD[mLODCount];
103    }
104
105    uint32_t tx = mDimX;
106    uint32_t ty = mDimY;
107    uint32_t tz = mDimZ;
108    size_t offset = 0;
109    for (uint32_t lod=0; lod < mLODCount; lod++) {
110        mLODs[lod].mX = tx;
111        mLODs[lod].mY = ty;
112        mLODs[lod].mZ = tz;
113        mLODs[lod].mOffset = offset;
114        offset += tx * rsMax(ty, 1u) * rsMax(tz, 1u) * mElement->getSizeBytes();
115        if (tx > 1) tx >>= 1;
116        if (ty > 1) ty >>= 1;
117        if (tz > 1) tz >>= 1;
118    }
119
120    // At this point the offset is the size of a mipmap chain;
121    mMipChainSizeBytes = offset;
122
123    if (mFaces) {
124        offset *= 6;
125    }
126    mTotalSizeBytes = offset;
127
128    makeGLComponents();
129}
130
131uint32_t Type::getLODOffset(uint32_t lod, uint32_t x) const
132{
133    uint32_t offset = mLODs[lod].mOffset;
134    offset += x * mElement->getSizeBytes();
135    return offset;
136}
137
138uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y) const
139{
140    uint32_t offset = mLODs[lod].mOffset;
141    offset += (x + y * mLODs[lod].mX) * mElement->getSizeBytes();
142    return offset;
143}
144
145uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y, uint32_t z) const
146{
147    uint32_t offset = mLODs[lod].mOffset;
148    offset += (x + y*mLODs[lod].mX + z*mLODs[lod].mX*mLODs[lod].mY) * mElement->getSizeBytes();
149    return offset;
150}
151
152bool Type::isValidGLComponent(uint32_t fieldIdx) {
153    // Do not create attribs for padding
154    if(mElement->getFieldName(fieldIdx)[0] == '#') {
155        return false;
156    }
157
158    // Only GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, GL_FLOAT are accepted.
159    // Filter rs types accordingly
160    RsDataType dt = mElement->getField(fieldIdx)->getComponent().getType();
161    if(dt != RS_TYPE_FLOAT_32 && dt != RS_TYPE_UNSIGNED_8 &&
162       dt != RS_TYPE_UNSIGNED_16 && dt != RS_TYPE_SIGNED_8 &&
163       dt != RS_TYPE_SIGNED_16) {
164        return false;
165    }
166
167    // Now make sure they are not arrays
168    uint32_t arraySize = mElement->getFieldArraySize(fieldIdx);
169    if(arraySize != 1) {
170        return false;
171    }
172
173    return true;
174}
175
176void Type::makeGLComponents()
177{
178    // Count the number of gl attrs to initialize
179    mAttribsSize = 0;
180
181    for (uint32_t ct=0; ct < mElement->getFieldCount(); ct++) {
182        if(isValidGLComponent(ct)) {
183            mAttribsSize ++;
184        }
185    }
186    if(mAttribs) {
187        delete [] mAttribs;
188        mAttribs = NULL;
189    }
190    if(mAttribsSize) {
191        mAttribs = new VertexArray::Attrib[mAttribsSize];
192    }
193
194    uint32_t userNum = 0;
195    for (uint32_t ct=0; ct < mElement->getFieldCount(); ct++) {
196        const Component &c = mElement->getField(ct)->getComponent();
197
198        if(!isValidGLComponent(ct)) {
199            continue;
200        }
201
202        mAttribs[userNum].size = c.getVectorSize();
203        mAttribs[userNum].offset = mElement->getFieldOffsetBytes(ct);
204        mAttribs[userNum].type = c.getGLType();
205        mAttribs[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized();
206        String8 tmp(RS_SHADER_ATTR);
207        tmp.append(mElement->getFieldName(ct));
208        mAttribs[userNum].name.setTo(tmp.string());
209
210        userNum ++;
211    }
212}
213
214
215void Type::enableGLVertexBuffer(VertexArray *va) const
216{
217    uint32_t stride = mElement->getSizeBytes();
218    for (uint32_t ct=0; ct < mAttribsSize; ct++) {
219        // Load up to RS_MAX_ATTRIBS inputs
220        // TODO: grow vertexarray dynamically
221        if(ct >= RS_MAX_ATTRIBS) {
222            LOGE("More GL attributes than we can handle");
223            break;
224        }
225        if (mAttribs[ct].size) {
226            va->add(mAttribs[ct], stride);
227        }
228    }
229}
230
231
232
233void Type::dumpLOGV(const char *prefix) const
234{
235    char buf[1024];
236    ObjectBase::dumpLOGV(prefix);
237    LOGV("%s   Type: x=%i y=%i z=%i mip=%i face=%i", prefix, mDimX, mDimY, mDimZ, mDimLOD, mFaces);
238    sprintf(buf, "%s element: ", prefix);
239    mElement->dumpLOGV(buf);
240}
241
242void Type::serialize(OStream *stream) const
243{
244    // Need to identify ourselves
245    stream->addU32((uint32_t)getClassId());
246
247    String8 name(getName());
248    stream->addString(&name);
249
250    mElement->serialize(stream);
251
252    stream->addU32(mDimX);
253    stream->addU32(mDimY);
254    stream->addU32(mDimZ);
255
256    stream->addU8((uint8_t)(mDimLOD ? 1 : 0));
257    stream->addU8((uint8_t)(mFaces ? 1 : 0));
258}
259
260Type *Type::createFromStream(Context *rsc, IStream *stream)
261{
262    // First make sure we are reading the correct object
263    RsA3DClassID classID = (RsA3DClassID)stream->loadU32();
264    if(classID != RS_A3D_CLASS_ID_TYPE) {
265        LOGE("type loading skipped due to invalid class id\n");
266        return NULL;
267    }
268
269    String8 name;
270    stream->loadString(&name);
271
272    Element *elem = Element::createFromStream(rsc, stream);
273    if(!elem) {
274        return NULL;
275    }
276
277    Type *type = new Type(rsc);
278    type->mDimX = stream->loadU32();
279    type->mDimY = stream->loadU32();
280    type->mDimZ = stream->loadU32();
281
282    uint8_t temp = stream->loadU8();
283    type->mDimLOD = temp != 0;
284
285    temp = stream->loadU8();
286    type->mFaces = temp != 0;
287
288    type->setElement(elem);
289
290    return type;
291}
292
293bool Type::getIsNp2() const
294{
295    uint32_t x = getDimX();
296    uint32_t y = getDimY();
297    uint32_t z = getDimZ();
298
299    if (x && (x & (x-1))) {
300        return true;
301    }
302    if (y && (y & (y-1))) {
303        return true;
304    }
305    if (z && (z & (z-1))) {
306        return true;
307    }
308    return false;
309}
310
311bool Type::isEqual(const Type *other) const {
312    if(other == NULL) {
313        return false;
314    }
315    if (other->getElement()->isEqual(getElement()) &&
316        other->getDimX() == mDimX &&
317        other->getDimY() == mDimY &&
318        other->getDimZ() == mDimZ &&
319        other->getDimLOD() == mDimLOD &&
320        other->getDimFaces() == mFaces) {
321        return true;
322    }
323    return false;
324}
325
326Type * Type::cloneAndResize1D(Context *rsc, uint32_t dimX) const
327{
328    TypeState * stc = &rsc->mStateType;
329    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
330        Type *t = stc->mTypes[ct];
331        if (t->getElement() != mElement.get()) continue;
332        if (t->getDimX() != dimX) continue;
333        if (t->getDimY() != mDimY) continue;
334        if (t->getDimZ() != mDimZ) continue;
335        if (t->getDimLOD() != mDimLOD) continue;
336        if (t->getDimFaces() != mFaces) continue;
337        t->incUserRef();
338        return t;
339    }
340
341    Type *nt = new Type(rsc);
342    nt->mElement.set(mElement);
343    nt->mDimX = dimX;
344    nt->mDimY = mDimY;
345    nt->mDimZ = mDimZ;
346    nt->mDimLOD = mDimLOD;
347    nt->mFaces = mFaces;
348    nt->compute();
349    return nt;
350}
351
352Type * Type::cloneAndResize2D(Context *rsc, uint32_t dimX, uint32_t dimY) const
353{
354    TypeState * stc = &rsc->mStateType;
355    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
356        Type *t = stc->mTypes[ct];
357        if (t->getElement() != mElement.get()) continue;
358        if (t->getDimX() != dimX) continue;
359        if (t->getDimY() != dimY) continue;
360        if (t->getDimZ() != mDimZ) continue;
361        if (t->getDimLOD() != mDimLOD) continue;
362        if (t->getDimFaces() != mFaces) continue;
363        t->incUserRef();
364        return t;
365    }
366
367    Type *nt = new Type(rsc);
368    nt->mElement.set(mElement);
369    nt->mDimX = dimX;
370    nt->mDimY = dimY;
371    nt->mDimZ = mDimZ;
372    nt->mDimLOD = mDimLOD;
373    nt->mFaces = mFaces;
374    nt->compute();
375    return nt;
376}
377
378
379//////////////////////////////////////////////////
380//
381namespace android {
382namespace renderscript {
383
384void rsi_TypeGetNativeData(Context *rsc, RsType type, uint32_t *typeData, uint32_t typeDataSize)
385{
386    rsAssert(typeDataSize == 6);
387    // Pack the data in the follofing way mDimX; mDimY; mDimZ;
388    // mDimLOD; mDimFaces; mElement; into typeData
389    Type *t = static_cast<Type *>(type);
390
391    (*typeData++) = t->getDimX();
392    (*typeData++) = t->getDimY();
393    (*typeData++) = t->getDimZ();
394    (*typeData++) = t->getDimLOD();
395    (*typeData++) = t->getDimFaces() ? 1 : 0;
396    (*typeData++) = (uint32_t)t->getElement();
397
398}
399
400
401}
402}
403
404void * rsaTypeCreate(RsContext con, RsElement _e, uint32_t dimCount,
405                     const RsDimension *dims, const uint32_t *vals)
406{
407    Context *rsc = static_cast<Context *>(con);
408    Element *e = static_cast<Element *>(_e);
409    TypeState * stc = &rsc->mStateType;
410
411    uint32_t dimX = 0;
412    uint32_t dimY = 0;
413    uint32_t dimZ = 0;
414    uint32_t dimLOD = 0;
415    uint32_t dimFaces = 0;
416
417    for (uint32_t ct=0; ct < dimCount; ct++) {
418        switch(dims[ct]) {
419        case RS_DIMENSION_X: dimX = vals[ct]; break;
420        case RS_DIMENSION_Y: dimY = vals[ct]; break;
421        case RS_DIMENSION_Z: dimZ = vals[ct]; break;
422        case RS_DIMENSION_LOD: dimLOD = vals[ct]; break;
423        case RS_DIMENSION_FACE: dimFaces = vals[ct]; break;
424
425        default:
426            LOGE("rsaTypeCreate: Bad dimension");
427            rsAssert(0);
428        }
429    }
430
431    ObjectBase::lockUserRef();
432    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
433        Type *t = stc->mTypes[ct];
434        if (t->getElement() != e) continue;
435        if (t->getDimX() != dimX) continue;
436        if (t->getDimY() != dimY) continue;
437        if (t->getDimZ() != dimZ) continue;
438        if (t->getDimLOD() != dimLOD) continue;
439        if (t->getDimFaces() != dimFaces) continue;
440        t->prelockedIncUserRef();
441        ObjectBase::unlockUserRef();
442        return t;
443    }
444    ObjectBase::unlockUserRef();
445
446    Type * st = new Type(rsc);
447    st->incUserRef();
448    st->setDimX(dimX);
449    st->setDimY(dimY);
450    st->setDimZ(dimZ);
451    st->setElement(e);
452    st->setDimLOD(dimLOD);
453    st->setDimFaces(dimFaces);
454    st->compute();
455
456    ObjectBase::lockUserRef();
457    stc->mTypes.push(st);
458    ObjectBase::unlockUserRef();
459    return st;
460}
461
462