rsType.cpp revision 39f2ef6fed00a99c5c389e12c4597884027d4858
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_TypeBegin(Context *rsc, RsElement vse)
385{
386    TypeState * stc = &rsc->mStateType;
387
388    stc->mX = 0;
389    stc->mY = 0;
390    stc->mZ = 0;
391    stc->mLOD = false;
392    stc->mFaces = false;
393    stc->mElement.set(static_cast<const Element *>(vse));
394}
395
396void rsi_TypeAdd(Context *rsc, RsDimension dim, size_t value)
397{
398    TypeState * stc = &rsc->mStateType;
399
400    if (dim < 0) {
401        //error
402        return;
403    }
404
405
406    switch (dim) {
407    case RS_DIMENSION_X:
408        stc->mX = value;
409        return;
410    case RS_DIMENSION_Y:
411        stc->mY = value;
412        return;
413    case RS_DIMENSION_Z:
414        stc->mZ = value;
415        return;
416    case RS_DIMENSION_FACE:
417        stc->mFaces = (value != 0);
418        return;
419    case RS_DIMENSION_LOD:
420        stc->mLOD = (value != 0);
421        return;
422    default:
423        break;
424    }
425
426    if ((dim < 0) || (dim > RS_DIMENSION_MAX)) {
427        LOGE("rsTypeAdd: Bad dimension");
428        //error
429        return;
430    }
431
432    // todo: implement array support
433
434}
435
436RsType rsi_TypeCreate(Context *rsc)
437{
438    TypeState * stc = &rsc->mStateType;
439
440    for (uint32_t ct=0; ct < stc->mTypes.size(); ct++) {
441        Type *t = stc->mTypes[ct];
442        if (t->getElement() != stc->mElement.get()) continue;
443        if (t->getDimX() != stc->mX) continue;
444        if (t->getDimY() != stc->mY) continue;
445        if (t->getDimZ() != stc->mZ) continue;
446        if (t->getDimLOD() != stc->mLOD) continue;
447        if (t->getDimFaces() != stc->mFaces) continue;
448        t->incUserRef();
449        return t;
450    }
451
452    Type * st = new Type(rsc);
453    st->incUserRef();
454    st->setDimX(stc->mX);
455    st->setDimY(stc->mY);
456    st->setDimZ(stc->mZ);
457    st->setElement(stc->mElement.get());
458    st->setDimLOD(stc->mLOD);
459    st->setDimFaces(stc->mFaces);
460    st->compute();
461    stc->mElement.clear();
462    stc->mTypes.push(st);
463    return st;
464}
465
466void rsi_TypeGetNativeData(Context *rsc, RsType type, uint32_t *typeData, uint32_t typeDataSize)
467{
468    rsAssert(typeDataSize == 6);
469    // Pack the data in the follofing way mDimX; mDimY; mDimZ;
470    // mDimLOD; mDimFaces; mElement; into typeData
471    Type *t = static_cast<Type *>(type);
472
473    (*typeData++) = t->getDimX();
474    (*typeData++) = t->getDimY();
475    (*typeData++) = t->getDimZ();
476    (*typeData++) = t->getDimLOD();
477    (*typeData++) = t->getDimFaces() ? 1 : 0;
478    (*typeData++) = (uint32_t)t->getElement();
479
480}
481
482
483}
484}
485
486