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