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 #include "RenderScript.h"
     18 #include <rs.h>
     19 
     20 using namespace android;
     21 using namespace RSC;
     22 
     23 void * Allocation::getIDSafe() const {
     24     return getID();
     25 }
     26 
     27 void Allocation::updateCacheInfo(sp<const Type> t) {
     28     mCurrentDimX = t->getX();
     29     mCurrentDimY = t->getY();
     30     mCurrentDimZ = t->getZ();
     31     mCurrentCount = mCurrentDimX;
     32     if (mCurrentDimY > 1) {
     33         mCurrentCount *= mCurrentDimY;
     34     }
     35     if (mCurrentDimZ > 1) {
     36         mCurrentCount *= mCurrentDimZ;
     37     }
     38 }
     39 
     40 Allocation::Allocation(void *id, sp<RS> rs, sp<const Type> t, uint32_t usage) :
     41     BaseObj(id, rs), mSelectedY(0), mSelectedZ(0), mSelectedLOD(0),
     42     mSelectedFace(RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X) {
     43 
     44     if ((usage & ~(RS_ALLOCATION_USAGE_SCRIPT |
     45                    RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE |
     46                    RS_ALLOCATION_USAGE_GRAPHICS_VERTEX |
     47                    RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS |
     48                    RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET |
     49                    RS_ALLOCATION_USAGE_IO_INPUT |
     50                    RS_ALLOCATION_USAGE_IO_OUTPUT |
     51                    RS_ALLOCATION_USAGE_SHARED)) != 0) {
     52         ALOGE("Unknown usage specified.");
     53     }
     54 
     55     if ((usage & RS_ALLOCATION_USAGE_IO_INPUT) != 0) {
     56         mWriteAllowed = false;
     57         if ((usage & ~(RS_ALLOCATION_USAGE_IO_INPUT |
     58                        RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE |
     59                        RS_ALLOCATION_USAGE_SCRIPT)) != 0) {
     60             ALOGE("Invalid usage combination.");
     61         }
     62     }
     63 
     64     mType = t;
     65     mUsage = usage;
     66 
     67     if (t.get() != NULL) {
     68         updateCacheInfo(t);
     69     }
     70 }
     71 
     72 void Allocation::validateIsInt32() {
     73     RsDataType dt = mType->getElement()->getDataType();
     74     if ((dt == RS_TYPE_SIGNED_32) || (dt == RS_TYPE_UNSIGNED_32)) {
     75         return;
     76     }
     77     ALOGE("32 bit integer source does not match allocation type %i", dt);
     78 }
     79 
     80 void Allocation::validateIsInt16() {
     81     RsDataType dt = mType->getElement()->getDataType();
     82     if ((dt == RS_TYPE_SIGNED_16) || (dt == RS_TYPE_UNSIGNED_16)) {
     83         return;
     84     }
     85     ALOGE("16 bit integer source does not match allocation type %i", dt);
     86 }
     87 
     88 void Allocation::validateIsInt8() {
     89     RsDataType dt = mType->getElement()->getDataType();
     90     if ((dt == RS_TYPE_SIGNED_8) || (dt == RS_TYPE_UNSIGNED_8)) {
     91         return;
     92     }
     93     ALOGE("8 bit integer source does not match allocation type %i", dt);
     94 }
     95 
     96 void Allocation::validateIsFloat32() {
     97     RsDataType dt = mType->getElement()->getDataType();
     98     if (dt == RS_TYPE_FLOAT_32) {
     99         return;
    100     }
    101     ALOGE("32 bit float source does not match allocation type %i", dt);
    102 }
    103 
    104 void Allocation::validateIsObject() {
    105     RsDataType dt = mType->getElement()->getDataType();
    106     if ((dt == RS_TYPE_ELEMENT) ||
    107         (dt == RS_TYPE_TYPE) ||
    108         (dt == RS_TYPE_ALLOCATION) ||
    109         (dt == RS_TYPE_SAMPLER) ||
    110         (dt == RS_TYPE_SCRIPT) ||
    111         (dt == RS_TYPE_MESH) ||
    112         (dt == RS_TYPE_PROGRAM_FRAGMENT) ||
    113         (dt == RS_TYPE_PROGRAM_VERTEX) ||
    114         (dt == RS_TYPE_PROGRAM_RASTER) ||
    115         (dt == RS_TYPE_PROGRAM_STORE)) {
    116         return;
    117     }
    118     ALOGE("Object source does not match allocation type %i", dt);
    119 }
    120 
    121 void Allocation::updateFromNative() {
    122     BaseObj::updateFromNative();
    123 
    124     const void *typeID = rsaAllocationGetType(mRS->getContext(), getID());
    125     if(typeID != NULL) {
    126         sp<const Type> old = mType;
    127         sp<Type> t = new Type((void *)typeID, mRS);
    128         t->updateFromNative();
    129         updateCacheInfo(t);
    130         mType = t;
    131     }
    132 }
    133 
    134 void Allocation::syncAll(RsAllocationUsageType srcLocation) {
    135     switch (srcLocation) {
    136     case RS_ALLOCATION_USAGE_SCRIPT:
    137     case RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS:
    138     case RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE:
    139     case RS_ALLOCATION_USAGE_GRAPHICS_VERTEX:
    140         break;
    141     default:
    142         ALOGE("Source must be exactly one usage type.");
    143     }
    144     rsAllocationSyncAll(mRS->getContext(), getIDSafe(), srcLocation);
    145 }
    146 
    147 void Allocation::ioSendOutput() {
    148 #ifndef RS_COMPATIBILITY_LIB
    149     if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) {
    150         ALOGE("Can only send buffer if IO_OUTPUT usage specified.");
    151     }
    152     rsAllocationIoSend(mRS->getContext(), getID());
    153 #endif
    154 }
    155 
    156 void Allocation::ioGetInput() {
    157 #ifndef RS_COMPATIBILITY_LIB
    158     if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) {
    159         ALOGE("Can only send buffer if IO_OUTPUT usage specified.");
    160     }
    161     rsAllocationIoReceive(mRS->getContext(), getID());
    162 #endif
    163 }
    164 
    165 void Allocation::generateMipmaps() {
    166     rsAllocationGenerateMipmaps(mRS->getContext(), getID());
    167 }
    168 
    169 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const void *data) {
    170 
    171     if(count < 1) {
    172         ALOGE("Count must be >= 1.");
    173         return;
    174     }
    175     if((off + count) > mCurrentCount) {
    176         ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off);
    177         return;
    178     }
    179 
    180     rsAllocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD, count, data,
    181                        count * mType->getElement()->getSizeBytes());
    182 }
    183 
    184 void Allocation::copy1DRangeTo(uint32_t off, size_t count, void *data) {
    185     if(count < 1) {
    186         ALOGE("Count must be >= 1.");
    187         return;
    188     }
    189     if((off + count) > mCurrentCount) {
    190         ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off);
    191         return;
    192     }
    193 
    194     rsAllocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD, count, data,
    195                        count * mType->getElement()->getSizeBytes());
    196 }
    197 
    198 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, sp<const Allocation> data,
    199                                  uint32_t dataOff) {
    200 
    201     rsAllocationCopy2DRange(mRS->getContext(), getIDSafe(), off, 0,
    202                             mSelectedLOD, mSelectedFace,
    203                             count, 1, data->getIDSafe(), dataOff, 0,
    204                             data->mSelectedLOD, data->mSelectedFace);
    205 }
    206 
    207 void Allocation::copy1DFrom(const void* data) {
    208     copy1DRangeFrom(0, mCurrentCount, data);
    209 }
    210 
    211 void Allocation::copy1DTo(void* data) {
    212     copy1DRangeTo(0, mCurrentCount, data);
    213 }
    214 
    215 
    216 void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) {
    217     if (mAdaptedAllocation != NULL) {
    218 
    219     } else {
    220         if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
    221             ALOGE("Updated region larger than allocation.");
    222         }
    223     }
    224 }
    225 
    226 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    227                                  const void *data) {
    228     validate2DRange(xoff, yoff, w, h);
    229     rsAllocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
    230                        w, h, data, w * h * mType->getElement()->getSizeBytes(), w * mType->getElement()->getSizeBytes());
    231 }
    232 
    233 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    234                                  sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff) {
    235     validate2DRange(xoff, yoff, w, h);
    236     rsAllocationCopy2DRange(mRS->getContext(), getIDSafe(), xoff, yoff,
    237                             mSelectedLOD, mSelectedFace,
    238                             w, h, data->getIDSafe(), dataXoff, dataYoff,
    239                             data->mSelectedLOD, data->mSelectedFace);
    240 }
    241 
    242 void Allocation::copy2DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    243                                void* data) {
    244     validate2DRange(xoff, yoff, w, h);
    245     rsAllocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
    246                        w, h, data, w * h * mType->getElement()->getSizeBytes(), w * mType->getElement()->getSizeBytes());
    247 }
    248 
    249 void Allocation::copy2DStridedFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    250                                    const void *data, size_t stride) {
    251     validate2DRange(xoff, yoff, w, h);
    252     rsAllocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
    253                        w, h, data, w * h * mType->getElement()->getSizeBytes(), stride);
    254 }
    255 
    256 void Allocation::copy2DStridedFrom(const void* data, size_t stride) {
    257     copy2DStridedFrom(0, 0, mCurrentDimX, mCurrentDimY, data, stride);
    258 }
    259 
    260 void Allocation::copy2DStridedTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    261                                  void *data, size_t stride) {
    262     validate2DRange(xoff, yoff, w, h);
    263     rsAllocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace,
    264                        w, h, data, w * h * mType->getElement()->getSizeBytes(), stride);
    265 }
    266 
    267 void Allocation::copy2DStridedTo(void* data, size_t stride) {
    268     copy2DStridedTo(0, 0, mCurrentDimX, mCurrentDimY, data, stride);
    269 }
    270 
    271 
    272 /*
    273 void resize(int dimX) {
    274     if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
    275         throw new RSInvalidStateException("Resize only support for 1D allocations at this time.");
    276     }
    277     mRS.nAllocationResize1D(getID(), dimX);
    278     mRS.finish();  // Necessary because resize is fifoed and update is async.
    279 
    280     int typeID = mRS.nAllocationGetType(getID());
    281     mType = new Type(typeID, mRS);
    282     mType.updateFromNative();
    283     updateCacheInfo(mType);
    284 }
    285 
    286 void resize(int dimX, int dimY) {
    287     if ((mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) {
    288         throw new RSInvalidStateException(
    289             "Resize only support for 2D allocations at this time.");
    290     }
    291     if (mType.getY() == 0) {
    292         throw new RSInvalidStateException(
    293             "Resize only support for 2D allocations at this time.");
    294     }
    295     mRS.nAllocationResize2D(getID(), dimX, dimY);
    296     mRS.finish();  // Necessary because resize is fifoed and update is async.
    297 
    298     int typeID = mRS.nAllocationGetType(getID());
    299     mType = new Type(typeID, mRS);
    300     mType.updateFromNative();
    301     updateCacheInfo(mType);
    302 }
    303 */
    304 
    305 
    306 android::sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
    307                                                 RsAllocationMipmapControl mips, uint32_t usage) {
    308     void *id = rsAllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, 0);
    309     if (id == 0) {
    310         ALOGE("Allocation creation failed.");
    311         return NULL;
    312     }
    313     return new Allocation(id, rs, type, usage);
    314 }
    315 
    316 android::sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
    317                                                 RsAllocationMipmapControl mips, uint32_t usage,
    318                                                 void *pointer) {
    319     void *id = rsAllocationCreateTyped(rs->getContext(), type->getID(), mips, usage,
    320                                        (uintptr_t)pointer);
    321     if (id == 0) {
    322         ALOGE("Allocation creation failed.");
    323     }
    324     return new Allocation(id, rs, type, usage);
    325 }
    326 
    327 android::sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
    328                                                 uint32_t usage) {
    329     return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage);
    330 }
    331 
    332 android::sp<Allocation> Allocation::createSized(sp<RS> rs, sp<const Element> e,
    333                                                 size_t count, uint32_t usage) {
    334     Type::Builder b(rs, e);
    335     b.setX(count);
    336     sp<const Type> t = b.create();
    337 
    338     return createTyped(rs, t, usage);
    339 }
    340 
    341 android::sp<Allocation> Allocation::createSized2D(sp<RS> rs, sp<const Element> e,
    342                                                   size_t x, size_t y, uint32_t usage) {
    343     Type::Builder b(rs, e);
    344     b.setX(x);
    345     b.setY(y);
    346     sp<const Type> t = b.create();
    347 
    348     return createTyped(rs, t, usage);
    349 }
    350