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