Home | History | Annotate | Download | only in cpp
      1 /*
      2  * Copyright (C) 2012 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 #define LOG_TAG "libRS_cpp"
     18 
     19 #include <utils/Log.h>
     20 #include <malloc.h>
     21 
     22 #include "RenderScript.h"
     23 #include "Element.h"
     24 #include "Type.h"
     25 #include "Allocation.h"
     26 
     27 using namespace android;
     28 using namespace renderscriptCpp;
     29 
     30 void * Allocation::getIDSafe() const {
     31     //if (mAdaptedAllocation != NULL) {
     32         //return mAdaptedAllocation.getID();
     33     //}
     34     return getID();
     35 }
     36 
     37 void Allocation::updateCacheInfo(sp<const Type> t) {
     38     mCurrentDimX = t->getX();
     39     mCurrentDimY = t->getY();
     40     mCurrentDimZ = t->getZ();
     41     mCurrentCount = mCurrentDimX;
     42     if (mCurrentDimY > 1) {
     43         mCurrentCount *= mCurrentDimY;
     44     }
     45     if (mCurrentDimZ > 1) {
     46         mCurrentCount *= mCurrentDimZ;
     47     }
     48 }
     49 
     50 Allocation::Allocation(void *id, RenderScript *rs, sp<const Type> t, uint32_t usage) :
     51         BaseObj(id, rs) {
     52 
     53     if ((usage & ~(RS_ALLOCATION_USAGE_SCRIPT |
     54                    RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE |
     55                    RS_ALLOCATION_USAGE_GRAPHICS_VERTEX |
     56                    RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS |
     57                    RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET |
     58                    RS_ALLOCATION_USAGE_IO_INPUT |
     59                    RS_ALLOCATION_USAGE_IO_OUTPUT)) != 0) {
     60         ALOGE("Unknown usage specified.");
     61     }
     62 
     63     if ((usage & RS_ALLOCATION_USAGE_IO_INPUT) != 0) {
     64         mWriteAllowed = false;
     65         if ((usage & ~(RS_ALLOCATION_USAGE_IO_INPUT |
     66                        RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE |
     67                        RS_ALLOCATION_USAGE_SCRIPT)) != 0) {
     68             ALOGE("Invalid usage combination.");
     69         }
     70     }
     71 
     72     mType = t;
     73     mUsage = usage;
     74 
     75     if (t.get() != NULL) {
     76         updateCacheInfo(t);
     77     }
     78 }
     79 
     80 void Allocation::validateIsInt32() {
     81     RsDataType dt = mType->getElement()->getDataType();
     82     if ((dt == RS_TYPE_SIGNED_32) || (dt == RS_TYPE_UNSIGNED_32)) {
     83         return;
     84     }
     85     ALOGE("32 bit integer source does not match allocation type %i", dt);
     86 }
     87 
     88 void Allocation::validateIsInt16() {
     89     RsDataType dt = mType->getElement()->getDataType();
     90     if ((dt == RS_TYPE_SIGNED_16) || (dt == RS_TYPE_UNSIGNED_16)) {
     91         return;
     92     }
     93     ALOGE("16 bit integer source does not match allocation type %i", dt);
     94 }
     95 
     96 void Allocation::validateIsInt8() {
     97     RsDataType dt = mType->getElement()->getDataType();
     98     if ((dt == RS_TYPE_SIGNED_8) || (dt == RS_TYPE_UNSIGNED_8)) {
     99         return;
    100     }
    101     ALOGE("8 bit integer source does not match allocation type %i", dt);
    102 }
    103 
    104 void Allocation::validateIsFloat32() {
    105     RsDataType dt = mType->getElement()->getDataType();
    106     if (dt == RS_TYPE_FLOAT_32) {
    107         return;
    108     }
    109     ALOGE("32 bit float source does not match allocation type %i", dt);
    110 }
    111 
    112 void Allocation::validateIsObject() {
    113     RsDataType dt = mType->getElement()->getDataType();
    114     if ((dt == RS_TYPE_ELEMENT) ||
    115         (dt == RS_TYPE_TYPE) ||
    116         (dt == RS_TYPE_ALLOCATION) ||
    117         (dt == RS_TYPE_SAMPLER) ||
    118         (dt == RS_TYPE_SCRIPT) ||
    119         (dt == RS_TYPE_MESH) ||
    120         (dt == RS_TYPE_PROGRAM_FRAGMENT) ||
    121         (dt == RS_TYPE_PROGRAM_VERTEX) ||
    122         (dt == RS_TYPE_PROGRAM_RASTER) ||
    123         (dt == RS_TYPE_PROGRAM_STORE)) {
    124         return;
    125     }
    126     ALOGE("Object source does not match allocation type %i", dt);
    127 }
    128 
    129 void Allocation::updateFromNative() {
    130     BaseObj::updateFromNative();
    131 
    132     const void *typeID = rsaAllocationGetType(mRS->mContext, getID());
    133     if(typeID != NULL) {
    134         sp<const Type> old = mType;
    135         sp<Type> t = new Type((void *)typeID, mRS);
    136         t->updateFromNative();
    137         updateCacheInfo(t);
    138         mType = t;
    139     }
    140 }
    141 
    142 void Allocation::syncAll(RsAllocationUsageType srcLocation) {
    143     switch (srcLocation) {
    144     case RS_ALLOCATION_USAGE_SCRIPT:
    145     case RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS:
    146     case RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE:
    147     case RS_ALLOCATION_USAGE_GRAPHICS_VERTEX:
    148         break;
    149     default:
    150         ALOGE("Source must be exactly one usage type.");
    151     }
    152     rsAllocationSyncAll(mRS->mContext, getIDSafe(), srcLocation);
    153 }
    154 
    155 void Allocation::ioSendOutput() {
    156     if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) {
    157         ALOGE("Can only send buffer if IO_OUTPUT usage specified.");
    158     }
    159     rsAllocationIoSend(mRS->mContext, getID());
    160 }
    161 
    162 void Allocation::ioGetInput() {
    163     if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) {
    164         ALOGE("Can only send buffer if IO_OUTPUT usage specified.");
    165     }
    166     rsAllocationIoReceive(mRS->mContext, getID());
    167 }
    168 
    169 /*
    170 void copyFrom(BaseObj[] d) {
    171     mRS.validate();
    172     validateIsObject();
    173     if (d.length != mCurrentCount) {
    174         ALOGE("Array size mismatch, allocation sizeX = " +
    175                                              mCurrentCount + ", array length = " + d.length);
    176     }
    177     int i[] = new int[d.length];
    178     for (int ct=0; ct < d.length; ct++) {
    179         i[ct] = d[ct].getID();
    180     }
    181     copy1DRangeFromUnchecked(0, mCurrentCount, i);
    182 }
    183 */
    184 
    185 
    186 /*
    187 void Allocation::setFromFieldPacker(int xoff, FieldPacker fp) {
    188     mRS.validate();
    189     int eSize = mType.mElement.getSizeBytes();
    190     final byte[] data = fp.getData();
    191 
    192     int count = data.length / eSize;
    193     if ((eSize * count) != data.length) {
    194         ALOGE("Field packer length " + data.length +
    195                                            " not divisible by element size " + eSize + ".");
    196     }
    197     copy1DRangeFromUnchecked(xoff, count, data);
    198 }
    199 
    200 void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) {
    201     mRS.validate();
    202     if (component_number >= mType.mElement.mElements.length) {
    203         ALOGE("Component_number " + component_number + " out of range.");
    204     }
    205     if(xoff < 0) {
    206         ALOGE("Offset must be >= 0.");
    207     }
    208 
    209     final byte[] data = fp.getData();
    210     int eSize = mType.mElement.mElements[component_number].getSizeBytes();
    211     eSize *= mType.mElement.mArraySizes[component_number];
    212 
    213     if (data.length != eSize) {
    214         ALOGE("Field packer sizelength " + data.length +
    215                                            " does not match component size " + eSize + ".");
    216     }
    217 
    218     mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD,
    219                                  component_number, data, data.length);
    220 }
    221 */
    222 
    223 void Allocation::generateMipmaps() {
    224     rsAllocationGenerateMipmaps(mRS->mContext, getID());
    225 }
    226 
    227 void Allocation::copy1DRangeFromUnchecked(uint32_t off, size_t count, const void *data,
    228         size_t dataLen) {
    229 
    230     if(count < 1) {
    231         ALOGE("Count must be >= 1.");
    232         return;
    233     }
    234     if((off + count) > mCurrentCount) {
    235         ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off);
    236         return;
    237     }
    238     if((count * mType->getElement()->getSizeBytes()) > dataLen) {
    239         ALOGE("Array too small for allocation type.");
    240         return;
    241     }
    242 
    243     rsAllocation1DData(mRS->mContext, getIDSafe(), off, mSelectedLOD, count, data, dataLen);
    244 }
    245 
    246 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int32_t *d, size_t dataLen) {
    247     validateIsInt32();
    248     copy1DRangeFromUnchecked(off, count, d, dataLen);
    249 }
    250 
    251 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int16_t *d, size_t dataLen) {
    252     validateIsInt16();
    253     copy1DRangeFromUnchecked(off, count, d, dataLen);
    254 }
    255 
    256 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int8_t *d, size_t dataLen) {
    257     validateIsInt8();
    258     copy1DRangeFromUnchecked(off, count, d, dataLen);
    259 }
    260 
    261 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const float *d, size_t dataLen) {
    262     validateIsFloat32();
    263     copy1DRangeFromUnchecked(off, count, d, dataLen);
    264 }
    265 
    266 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const Allocation *data,
    267         uint32_t dataOff) {
    268 
    269     rsAllocationCopy2DRange(mRS->mContext, getIDSafe(), off, 0,
    270                             mSelectedLOD, mSelectedFace,
    271                             count, 1, data->getIDSafe(), dataOff, 0,
    272                             data->mSelectedLOD, data->mSelectedFace);
    273 }
    274 
    275 void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) {
    276     if (mAdaptedAllocation != NULL) {
    277 
    278     } else {
    279         if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
    280             ALOGE("Updated region larger than allocation.");
    281         }
    282     }
    283 }
    284 
    285 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    286                                  const int8_t *data, size_t dataLen) {
    287     validate2DRange(xoff, yoff, w, h);
    288     rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
    289                        w, h, data, dataLen);
    290 }
    291 
    292 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    293                                  const int16_t *data, size_t dataLen) {
    294     validate2DRange(xoff, yoff, w, h);
    295     rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
    296                        w, h, data, dataLen);
    297 }
    298 
    299 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    300                                  const int32_t *data, size_t dataLen) {
    301     validate2DRange(xoff, yoff, w, h);
    302     rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
    303                        w, h, data, dataLen);
    304 }
    305 
    306 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    307                                  const float *data, size_t dataLen) {
    308     validate2DRange(xoff, yoff, w, h);
    309     rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
    310                        w, h, data, dataLen);
    311 }
    312 
    313 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    314                                  const Allocation *data, size_t dataLen,
    315                                  uint32_t dataXoff, uint32_t dataYoff) {
    316     validate2DRange(xoff, yoff, w, h);
    317     rsAllocationCopy2DRange(mRS->mContext, getIDSafe(), xoff, yoff,
    318                             mSelectedLOD, mSelectedFace,
    319                             w, h, data->getIDSafe(), dataXoff, dataYoff,
    320                             data->mSelectedLOD, data->mSelectedFace);
    321 }
    322 
    323 /*
    324 void copyTo(byte[] d) {
    325     validateIsInt8();
    326     mRS.validate();
    327     mRS.nAllocationRead(getID(), d);
    328 }
    329 
    330 void copyTo(short[] d) {
    331     validateIsInt16();
    332     mRS.validate();
    333     mRS.nAllocationRead(getID(), d);
    334 }
    335 
    336 void copyTo(int[] d) {
    337     validateIsInt32();
    338     mRS.validate();
    339     mRS.nAllocationRead(getID(), d);
    340 }
    341 
    342 void copyTo(float[] d) {
    343     validateIsFloat32();
    344     mRS.validate();
    345     mRS.nAllocationRead(getID(), d);
    346 }
    347 
    348 void resize(int dimX) {
    349     if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
    350         throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
    351     }
    352     mRS.nAllocationResize1D(getID(), dimX);
    353     mRS.finish();  // Necessary because resize is fifoed and update is async.
    354 
    355     int typeID = mRS.nAllocationGetType(getID());
    356     mType = new Type(typeID, mRS);
    357     mType.updateFromNative();
    358     updateCacheInfo(mType);
    359 }
    360 
    361 void resize(int dimX, int dimY) {
    362     if ((mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
    363         throw new RSInvalidStateException(
    364             "Resize only support for 2D allocations at this time.");
    365     }
    366     if (mType.getY() == 0) {
    367         throw new RSInvalidStateException(
    368             "Resize only support for 2D allocations at this time.");
    369     }
    370     mRS.nAllocationResize2D(getID(), dimX, dimY);
    371     mRS.finish();  // Necessary because resize is fifoed and update is async.
    372 
    373     int typeID = mRS.nAllocationGetType(getID());
    374     mType = new Type(typeID, mRS);
    375     mType.updateFromNative();
    376     updateCacheInfo(mType);
    377 }
    378 */
    379 
    380 
    381 android::sp<Allocation> Allocation::createTyped(RenderScript *rs, sp<const Type> type,
    382                         RsAllocationMipmapControl mips, uint32_t usage) {
    383     void *id = rsAllocationCreateTyped(rs->mContext, type->getID(), mips, usage, 0);
    384     if (id == 0) {
    385         ALOGE("Allocation creation failed.");
    386         return NULL;
    387     }
    388     return new Allocation(id, rs, type, usage);
    389 }
    390 
    391 android::sp<Allocation> Allocation::createTyped(RenderScript *rs, sp<const Type> type,
    392                                     RsAllocationMipmapControl mips, uint32_t usage, void *pointer) {
    393     void *id = rsAllocationCreateTyped(rs->mContext, type->getID(), mips, usage, (uint32_t)pointer);
    394     if (id == 0) {
    395         ALOGE("Allocation creation failed.");
    396     }
    397     return new Allocation(id, rs, type, usage);
    398 }
    399 
    400 android::sp<Allocation> Allocation::createTyped(RenderScript *rs, sp<const Type> type,
    401         uint32_t usage) {
    402     return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage);
    403 }
    404 
    405 android::sp<Allocation> Allocation::createSized(RenderScript *rs, sp<const Element> e,
    406         size_t count, uint32_t usage) {
    407 
    408     Type::Builder b(rs, e);
    409     b.setX(count);
    410     sp<const Type> t = b.create();
    411 
    412     void *id = rsAllocationCreateTyped(rs->mContext, t->getID(),
    413         RS_ALLOCATION_MIPMAP_NONE, usage, 0);
    414     if (id == 0) {
    415         ALOGE("Allocation creation failed.");
    416     }
    417     return new Allocation(id, rs, t, usage);
    418 }
    419 
    420 
    421 /*
    422 SurfaceTexture getSurfaceTexture() {
    423     if ((mUsage & USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE) == 0) {
    424         throw new RSInvalidStateException("Allocation is not a surface texture.");
    425     }
    426 
    427     int id = mRS.nAllocationGetSurfaceTextureID(getID());
    428     return new SurfaceTexture(id);
    429 
    430 }
    431 
    432 void setSurfaceTexture(SurfaceTexture sur) {
    433     if ((mUsage & USAGE_IO_OUTPUT) == 0) {
    434         throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT.");
    435     }
    436 
    437     mRS.validate();
    438     mRS.nAllocationSetSurfaceTexture(getID(), sur);
    439 }
    440 
    441 
    442 static Allocation createFromBitmapResource(RenderScript rs,
    443                                                   Resources res,
    444                                                   int id,
    445                                                   MipmapControl mips,
    446                                                   int usage) {
    447 
    448     rs.validate();
    449     Bitmap b = BitmapFactory.decodeResource(res, id);
    450     Allocation alloc = createFromBitmap(rs, b, mips, usage);
    451     b.recycle();
    452     return alloc;
    453 }
    454 
    455 static Allocation createFromBitmapResource(RenderScript rs,
    456                                                   Resources res,
    457                                                   int id) {
    458     return createFromBitmapResource(rs, res, id,
    459                                     MipmapControl.MIPMAP_NONE,
    460                                     USAGE_GRAPHICS_TEXTURE);
    461 }
    462 
    463 static Allocation createFromString(RenderScript rs,
    464                                           String str,
    465                                           int usage) {
    466     rs.validate();
    467     byte[] allocArray = NULL;
    468     try {
    469         allocArray = str.getBytes("UTF-8");
    470         Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage);
    471         alloc.copyFrom(allocArray);
    472         return alloc;
    473     }
    474     catch (Exception e) {
    475         throw new RSRuntimeException("Could not convert string to utf-8.");
    476     }
    477 }
    478 */
    479 
    480