Home | History | Annotate | Download | only in rs
      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 #include "rsContext.h"
     18 
     19 #include <GLES/gl.h>
     20 #include <GLES2/gl2.h>
     21 #include <GLES/glext.h>
     22 
     23 using namespace android;
     24 using namespace android::renderscript;
     25 
     26 Allocation::Allocation(Context *rsc, const Type *type) : ObjectBase(rsc)
     27 {
     28     init(rsc, type);
     29 
     30     mPtr = malloc(mType->getSizeBytes());
     31     if (!mPtr) {
     32         LOGE("Allocation::Allocation, alloc failure");
     33     }
     34 }
     35 
     36 Allocation::Allocation(Context *rsc, const Type *type, void *bmp,
     37                        void *callbackData, RsBitmapCallback_t callback)
     38 : ObjectBase(rsc)
     39 {
     40     init(rsc, type);
     41 
     42     mPtr = bmp;
     43     mUserBitmapCallback = callback;
     44     mUserBitmapCallbackData = callbackData;
     45 }
     46 
     47 void Allocation::init(Context *rsc, const Type *type)
     48 {
     49     mAllocFile = __FILE__;
     50     mAllocLine = __LINE__;
     51     mPtr = NULL;
     52 
     53     mCpuWrite = false;
     54     mCpuRead = false;
     55     mGpuWrite = false;
     56     mGpuRead = false;
     57 
     58     mReadWriteRatio = 0;
     59     mUpdateSize = 0;
     60 
     61     mIsTexture = false;
     62     mTextureID = 0;
     63     mIsVertexBuffer = false;
     64     mBufferID = 0;
     65     mUploadDefered = false;
     66 
     67     mUserBitmapCallback = NULL;
     68     mUserBitmapCallbackData = NULL;
     69 
     70     mType.set(type);
     71     rsAssert(type);
     72 
     73     mPtr = NULL;
     74 }
     75 
     76 Allocation::~Allocation()
     77 {
     78     if (mUserBitmapCallback != NULL) {
     79         mUserBitmapCallback(mUserBitmapCallbackData);
     80     } else {
     81         free(mPtr);
     82     }
     83     mPtr = NULL;
     84 
     85     if (mBufferID) {
     86         // Causes a SW crash....
     87         //LOGV(" mBufferID %i", mBufferID);
     88         //glDeleteBuffers(1, &mBufferID);
     89         //mBufferID = 0;
     90     }
     91     if (mTextureID) {
     92         glDeleteTextures(1, &mTextureID);
     93         mTextureID = 0;
     94     }
     95 }
     96 
     97 void Allocation::setCpuWritable(bool)
     98 {
     99 }
    100 
    101 void Allocation::setGpuWritable(bool)
    102 {
    103 }
    104 
    105 void Allocation::setCpuReadable(bool)
    106 {
    107 }
    108 
    109 void Allocation::setGpuReadable(bool)
    110 {
    111 }
    112 
    113 bool Allocation::fixAllocation()
    114 {
    115     return false;
    116 }
    117 
    118 void Allocation::deferedUploadToTexture(const Context *rsc, bool genMipmap, uint32_t lodOffset)
    119 {
    120     rsAssert(lodOffset < mType->getLODCount());
    121     mIsTexture = true;
    122     mTextureLOD = lodOffset;
    123     mUploadDefered = true;
    124     mTextureGenMipmap = !mType->getDimLOD() && genMipmap;
    125 }
    126 
    127 void Allocation::uploadToTexture(const Context *rsc)
    128 {
    129     //rsAssert(!mTextureId);
    130 
    131     mIsTexture = true;
    132     if (!rsc->checkDriver()) {
    133         mUploadDefered = true;
    134         return;
    135     }
    136 
    137     GLenum type = mType->getElement()->getComponent().getGLType();
    138     GLenum format = mType->getElement()->getComponent().getGLFormat();
    139 
    140     if (!type || !format) {
    141         return;
    142     }
    143 
    144     if (!mTextureID) {
    145         glGenTextures(1, &mTextureID);
    146 
    147         if (!mTextureID) {
    148             // This should not happen, however, its likely the cause of the
    149             // white sqare bug.
    150             // Force a crash to 1: restart the app, 2: make sure we get a bugreport.
    151             LOGE("Upload to texture failed to gen mTextureID");
    152             rsc->dumpDebug();
    153             mUploadDefered = true;
    154             return;
    155         }
    156     }
    157     glBindTexture(GL_TEXTURE_2D, mTextureID);
    158     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    159 
    160     Adapter2D adapt(getContext(), this);
    161     for(uint32_t lod = 0; (lod + mTextureLOD) < mType->getLODCount(); lod++) {
    162         adapt.setLOD(lod+mTextureLOD);
    163 
    164         uint16_t * ptr = static_cast<uint16_t *>(adapt.getElement(0,0));
    165         glTexImage2D(GL_TEXTURE_2D, lod, format,
    166                      adapt.getDimX(), adapt.getDimY(),
    167                      0, format, type, ptr);
    168     }
    169     if (mTextureGenMipmap) {
    170         glGenerateMipmap(GL_TEXTURE_2D);
    171     }
    172 
    173 }
    174 
    175 void Allocation::deferedUploadToBufferObject(const Context *rsc)
    176 {
    177     mIsVertexBuffer = true;
    178     mUploadDefered = true;
    179 }
    180 
    181 void Allocation::uploadToBufferObject(const Context *rsc)
    182 {
    183     rsAssert(!mType->getDimY());
    184     rsAssert(!mType->getDimZ());
    185 
    186     mIsVertexBuffer = true;
    187     if (!rsc->checkDriver()) {
    188         mUploadDefered = true;
    189         return;
    190     }
    191 
    192     if (!mBufferID) {
    193         glGenBuffers(1, &mBufferID);
    194     }
    195     if (!mBufferID) {
    196         LOGE("Upload to buffer object failed");
    197         mUploadDefered = true;
    198         return;
    199     }
    200 
    201     glBindBuffer(GL_ARRAY_BUFFER, mBufferID);
    202     glBufferData(GL_ARRAY_BUFFER, mType->getSizeBytes(), getPtr(), GL_DYNAMIC_DRAW);
    203     glBindBuffer(GL_ARRAY_BUFFER, 0);
    204 }
    205 
    206 void Allocation::uploadCheck(const Context *rsc)
    207 {
    208     if (mUploadDefered) {
    209         mUploadDefered = false;
    210         if (mIsVertexBuffer) {
    211             uploadToBufferObject(rsc);
    212         }
    213         if (mIsTexture) {
    214             uploadToTexture(rsc);
    215         }
    216     }
    217 }
    218 
    219 
    220 void Allocation::data(const void *data, uint32_t sizeBytes)
    221 {
    222     uint32_t size = mType->getSizeBytes();
    223     if (size != sizeBytes) {
    224         LOGE("Allocation::data called with mismatched size expected %i, got %i", size, sizeBytes);
    225         return;
    226     }
    227     memcpy(mPtr, data, size);
    228     sendDirty();
    229     mUploadDefered = true;
    230 }
    231 
    232 void Allocation::read(void *data)
    233 {
    234     memcpy(data, mPtr, mType->getSizeBytes());
    235 }
    236 
    237 void Allocation::subData(uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes)
    238 {
    239     uint32_t eSize = mType->getElementSizeBytes();
    240     uint8_t * ptr = static_cast<uint8_t *>(mPtr);
    241     ptr += eSize * xoff;
    242     uint32_t size = count * eSize;
    243 
    244     if (size != sizeBytes) {
    245         LOGE("Allocation::subData called with mismatched size expected %i, got %i", size, sizeBytes);
    246         mType->dumpLOGV("type info");
    247         return;
    248     }
    249     memcpy(ptr, data, size);
    250     sendDirty();
    251     mUploadDefered = true;
    252 }
    253 
    254 void Allocation::subData(uint32_t xoff, uint32_t yoff,
    255              uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes)
    256 {
    257     uint32_t eSize = mType->getElementSizeBytes();
    258     uint32_t lineSize = eSize * w;
    259     uint32_t destW = mType->getDimX();
    260 
    261     const uint8_t *src = static_cast<const uint8_t *>(data);
    262     uint8_t *dst = static_cast<uint8_t *>(mPtr);
    263     dst += eSize * (xoff + yoff * destW);
    264 
    265     if ((lineSize * eSize * h) != sizeBytes) {
    266         rsAssert(!"Allocation::subData called with mismatched size");
    267         return;
    268     }
    269 
    270     for (uint32_t line=yoff; line < (yoff+h); line++) {
    271         uint8_t * ptr = static_cast<uint8_t *>(mPtr);
    272         memcpy(dst, src, lineSize);
    273         src += lineSize;
    274         dst += destW * eSize;
    275     }
    276     sendDirty();
    277     mUploadDefered = true;
    278 }
    279 
    280 void Allocation::subData(uint32_t xoff, uint32_t yoff, uint32_t zoff,
    281              uint32_t w, uint32_t h, uint32_t d, const void *data, uint32_t sizeBytes)
    282 {
    283 }
    284 
    285 void Allocation::addProgramToDirty(const Program *p)
    286 {
    287     mToDirtyList.add(p);
    288 }
    289 
    290 void Allocation::removeProgramToDirty(const Program *p)
    291 {
    292     for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
    293         if (mToDirtyList[ct] == p) {
    294             mToDirtyList.removeAt(ct);
    295             return;
    296         }
    297     }
    298     rsAssert(0);
    299 }
    300 
    301 void Allocation::dumpLOGV(const char *prefix) const
    302 {
    303     ObjectBase::dumpLOGV(prefix);
    304 
    305     String8 s(prefix);
    306     s.append(" type ");
    307     if (mType.get()) {
    308         mType->dumpLOGV(s.string());
    309     }
    310 
    311     LOGV("%s allocation ptr=%p mCpuWrite=%i, mCpuRead=%i, mGpuWrite=%i, mGpuRead=%i",
    312           prefix, mPtr, mCpuWrite, mCpuRead, mGpuWrite, mGpuRead);
    313 
    314     LOGV("%s allocation mIsTexture=%i mTextureID=%i, mIsVertexBuffer=%i, mBufferID=%i",
    315           prefix, mIsTexture, mTextureID, mIsVertexBuffer, mBufferID);
    316 
    317 }
    318 
    319 void Allocation::sendDirty() const
    320 {
    321     for (size_t ct=0; ct < mToDirtyList.size(); ct++) {
    322         mToDirtyList[ct]->forceDirty();
    323     }
    324 }
    325 
    326 /////////////////
    327 //
    328 
    329 
    330 namespace android {
    331 namespace renderscript {
    332 
    333 RsAllocation rsi_AllocationCreateTyped(Context *rsc, RsType vtype)
    334 {
    335     const Type * type = static_cast<const Type *>(vtype);
    336 
    337     Allocation * alloc = new Allocation(rsc, type);
    338     alloc->incUserRef();
    339     return alloc;
    340 }
    341 
    342 RsAllocation rsi_AllocationCreateSized(Context *rsc, RsElement e, size_t count)
    343 {
    344     Type * type = new Type(rsc);
    345     type->setDimX(count);
    346     type->setElement(static_cast<Element *>(e));
    347     type->compute();
    348     return rsi_AllocationCreateTyped(rsc, type);
    349 }
    350 
    351 void rsi_AllocationUploadToTexture(Context *rsc, RsAllocation va, bool genmip, uint32_t baseMipLevel)
    352 {
    353     Allocation *alloc = static_cast<Allocation *>(va);
    354     alloc->deferedUploadToTexture(rsc, genmip, baseMipLevel);
    355 }
    356 
    357 void rsi_AllocationUploadToBufferObject(Context *rsc, RsAllocation va)
    358 {
    359     Allocation *alloc = static_cast<Allocation *>(va);
    360     alloc->deferedUploadToBufferObject(rsc);
    361 }
    362 
    363 static void mip565(const Adapter2D &out, const Adapter2D &in)
    364 {
    365     uint32_t w = out.getDimX();
    366     uint32_t h = out.getDimY();
    367 
    368     for (uint32_t y=0; y < h; y++) {
    369         uint16_t *oPtr = static_cast<uint16_t *>(out.getElement(0, y));
    370         const uint16_t *i1 = static_cast<uint16_t *>(in.getElement(0, y*2));
    371         const uint16_t *i2 = static_cast<uint16_t *>(in.getElement(0, y*2+1));
    372 
    373         for (uint32_t x=0; x < w; x++) {
    374             *oPtr = rsBoxFilter565(i1[0], i1[1], i2[0], i2[1]);
    375             oPtr ++;
    376             i1 += 2;
    377             i2 += 2;
    378         }
    379     }
    380 }
    381 
    382 static void mip8888(const Adapter2D &out, const Adapter2D &in)
    383 {
    384     uint32_t w = out.getDimX();
    385     uint32_t h = out.getDimY();
    386 
    387     for (uint32_t y=0; y < h; y++) {
    388         uint32_t *oPtr = static_cast<uint32_t *>(out.getElement(0, y));
    389         const uint32_t *i1 = static_cast<uint32_t *>(in.getElement(0, y*2));
    390         const uint32_t *i2 = static_cast<uint32_t *>(in.getElement(0, y*2+1));
    391 
    392         for (uint32_t x=0; x < w; x++) {
    393             *oPtr = rsBoxFilter8888(i1[0], i1[1], i2[0], i2[1]);
    394             oPtr ++;
    395             i1 += 2;
    396             i2 += 2;
    397         }
    398     }
    399 }
    400 
    401 static void mip8(const Adapter2D &out, const Adapter2D &in)
    402 {
    403     uint32_t w = out.getDimX();
    404     uint32_t h = out.getDimY();
    405 
    406     for (uint32_t y=0; y < h; y++) {
    407         uint8_t *oPtr = static_cast<uint8_t *>(out.getElement(0, y));
    408         const uint8_t *i1 = static_cast<uint8_t *>(in.getElement(0, y*2));
    409         const uint8_t *i2 = static_cast<uint8_t *>(in.getElement(0, y*2+1));
    410 
    411         for (uint32_t x=0; x < w; x++) {
    412             *oPtr = (uint8_t)(((uint32_t)i1[0] + i1[1] + i2[0] + i2[1]) * 0.25f);
    413             oPtr ++;
    414             i1 += 2;
    415             i2 += 2;
    416         }
    417     }
    418 }
    419 
    420 static void mip(const Adapter2D &out, const Adapter2D &in)
    421 {
    422     switch(out.getBaseType()->getElement()->getSizeBits()) {
    423     case 32:
    424         mip8888(out, in);
    425         break;
    426     case 16:
    427         mip565(out, in);
    428         break;
    429     case 8:
    430         mip8(out, in);
    431         break;
    432 
    433     }
    434 
    435 }
    436 
    437 typedef void (*ElementConverter_t)(void *dst, const void *src, uint32_t count);
    438 
    439 static void elementConverter_cpy_16(void *dst, const void *src, uint32_t count)
    440 {
    441     memcpy(dst, src, count * 2);
    442 }
    443 static void elementConverter_cpy_8(void *dst, const void *src, uint32_t count)
    444 {
    445     memcpy(dst, src, count);
    446 }
    447 static void elementConverter_cpy_32(void *dst, const void *src, uint32_t count)
    448 {
    449     memcpy(dst, src, count * 4);
    450 }
    451 
    452 
    453 static void elementConverter_888_to_565(void *dst, const void *src, uint32_t count)
    454 {
    455     uint16_t *d = static_cast<uint16_t *>(dst);
    456     const uint8_t *s = static_cast<const uint8_t *>(src);
    457 
    458     while(count--) {
    459         *d = rs888to565(s[0], s[1], s[2]);
    460         d++;
    461         s+= 3;
    462     }
    463 }
    464 
    465 static void elementConverter_8888_to_565(void *dst, const void *src, uint32_t count)
    466 {
    467     uint16_t *d = static_cast<uint16_t *>(dst);
    468     const uint8_t *s = static_cast<const uint8_t *>(src);
    469 
    470     while(count--) {
    471         *d = rs888to565(s[0], s[1], s[2]);
    472         d++;
    473         s+= 4;
    474     }
    475 }
    476 
    477 static ElementConverter_t pickConverter(const Element *dst, const Element *src)
    478 {
    479     GLenum srcGLType = src->getComponent().getGLType();
    480     GLenum srcGLFmt = src->getComponent().getGLFormat();
    481     GLenum dstGLType = dst->getComponent().getGLType();
    482     GLenum dstGLFmt = dst->getComponent().getGLFormat();
    483 
    484     if (srcGLFmt == dstGLFmt && srcGLType == dstGLType) {
    485         switch(dst->getSizeBytes()) {
    486         case 4:
    487             return elementConverter_cpy_32;
    488         case 2:
    489             return elementConverter_cpy_16;
    490         case 1:
    491             return elementConverter_cpy_8;
    492         }
    493     }
    494 
    495     if (srcGLType == GL_UNSIGNED_BYTE &&
    496         srcGLFmt == GL_RGB &&
    497         dstGLType == GL_UNSIGNED_SHORT_5_6_5 &&
    498         dstGLType == GL_RGB) {
    499 
    500         return elementConverter_888_to_565;
    501     }
    502 
    503     if (srcGLType == GL_UNSIGNED_BYTE &&
    504         srcGLFmt == GL_RGBA &&
    505         dstGLType == GL_UNSIGNED_SHORT_5_6_5 &&
    506         dstGLType == GL_RGB) {
    507 
    508         return elementConverter_8888_to_565;
    509     }
    510 
    511     LOGE("pickConverter, unsuported combo, src %p,  dst %p", src, dst);
    512     return 0;
    513 }
    514 
    515 RsAllocation rsi_AllocationCreateBitmapRef(Context *rsc, RsType vtype,
    516                                            void *bmp, void *callbackData, RsBitmapCallback_t callback)
    517 {
    518     const Type * type = static_cast<const Type *>(vtype);
    519     Allocation * alloc = new Allocation(rsc, type, bmp, callbackData, callback);
    520     alloc->incUserRef();
    521     return alloc;
    522 }
    523 
    524 RsAllocation rsi_AllocationCreateFromBitmap(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src,  bool genMips, const void *data)
    525 {
    526     const Element *src = static_cast<const Element *>(_src);
    527     const Element *dst = static_cast<const Element *>(_dst);
    528 
    529     // Check for pow2 on pre es 2.0 versions.
    530     rsAssert(rsc->checkVersion2_0() || (!(w & (w-1)) && !(h & (h-1))));
    531 
    532     //LOGE("rsi_AllocationCreateFromBitmap %i %i %i %i %i", w, h, dstFmt, srcFmt, genMips);
    533     rsi_TypeBegin(rsc, _dst);
    534     rsi_TypeAdd(rsc, RS_DIMENSION_X, w);
    535     rsi_TypeAdd(rsc, RS_DIMENSION_Y, h);
    536     if (genMips) {
    537         rsi_TypeAdd(rsc, RS_DIMENSION_LOD, 1);
    538     }
    539     RsType type = rsi_TypeCreate(rsc);
    540 
    541     RsAllocation vTexAlloc = rsi_AllocationCreateTyped(rsc, type);
    542     Allocation *texAlloc = static_cast<Allocation *>(vTexAlloc);
    543     if (texAlloc == NULL) {
    544         LOGE("Memory allocation failure");
    545         return NULL;
    546     }
    547 
    548     ElementConverter_t cvt = pickConverter(dst, src);
    549     cvt(texAlloc->getPtr(), data, w * h);
    550 
    551     if (genMips) {
    552         Adapter2D adapt(rsc, texAlloc);
    553         Adapter2D adapt2(rsc, texAlloc);
    554         for(uint32_t lod=0; lod < (texAlloc->getType()->getLODCount() -1); lod++) {
    555             adapt.setLOD(lod);
    556             adapt2.setLOD(lod + 1);
    557             mip(adapt2, adapt);
    558         }
    559     }
    560 
    561     return texAlloc;
    562 }
    563 
    564 RsAllocation rsi_AllocationCreateFromBitmapBoxed(Context *rsc, uint32_t w, uint32_t h, RsElement _dst, RsElement _src, bool genMips, const void *data)
    565 {
    566     const Element *srcE = static_cast<const Element *>(_src);
    567     const Element *dstE = static_cast<const Element *>(_dst);
    568     uint32_t w2 = rsHigherPow2(w);
    569     uint32_t h2 = rsHigherPow2(h);
    570 
    571     if ((w2 == w) && (h2 == h)) {
    572         return rsi_AllocationCreateFromBitmap(rsc, w, h, _dst, _src, genMips, data);
    573     }
    574 
    575     uint32_t bpp = srcE->getSizeBytes();
    576     size_t size = w2 * h2 * bpp;
    577     uint8_t *tmp = static_cast<uint8_t *>(malloc(size));
    578     memset(tmp, 0, size);
    579 
    580     const uint8_t * src = static_cast<const uint8_t *>(data);
    581     for (uint32_t y = 0; y < h; y++) {
    582         uint8_t * ydst = &tmp[(y + ((h2 - h) >> 1)) * w2 * bpp];
    583         memcpy(&ydst[((w2 - w) >> 1) * bpp], src, w * bpp);
    584         src += w * bpp;
    585     }
    586 
    587     RsAllocation ret = rsi_AllocationCreateFromBitmap(rsc, w2, h2, _dst, _src, genMips, tmp);
    588     free(tmp);
    589     return ret;
    590 }
    591 
    592 void rsi_AllocationData(Context *rsc, RsAllocation va, const void *data, uint32_t sizeBytes)
    593 {
    594     Allocation *a = static_cast<Allocation *>(va);
    595     a->data(data, sizeBytes);
    596 }
    597 
    598 void rsi_Allocation1DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t count, const void *data, uint32_t sizeBytes)
    599 {
    600     Allocation *a = static_cast<Allocation *>(va);
    601     a->subData(xoff, count, data, sizeBytes);
    602 }
    603 
    604 void rsi_Allocation2DSubData(Context *rsc, RsAllocation va, uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, const void *data, uint32_t sizeBytes)
    605 {
    606     Allocation *a = static_cast<Allocation *>(va);
    607     a->subData(xoff, yoff, w, h, data, sizeBytes);
    608 }
    609 
    610 void rsi_AllocationRead(Context *rsc, RsAllocation va, void *data)
    611 {
    612     Allocation *a = static_cast<Allocation *>(va);
    613     a->read(data);
    614 }
    615 
    616 
    617 }
    618 }
    619