Home | History | Annotate | Download | only in cpp
      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 "RenderScript.h"
     18 #include "rsCppInternal.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 != NULL) {
     68         updateCacheInfo(t);
     69     }
     70 
     71 }
     72 
     73 
     74 
     75 void Allocation::validateIsInt32() {
     76     RsDataType dt = mType->getElement()->getDataType();
     77     if ((dt == RS_TYPE_SIGNED_32) || (dt == RS_TYPE_UNSIGNED_32)) {
     78         return;
     79     }
     80     ALOGE("32 bit integer source does not match allocation type %i", dt);
     81 }
     82 
     83 void Allocation::validateIsInt16() {
     84     RsDataType dt = mType->getElement()->getDataType();
     85     if ((dt == RS_TYPE_SIGNED_16) || (dt == RS_TYPE_UNSIGNED_16)) {
     86         return;
     87     }
     88     ALOGE("16 bit integer source does not match allocation type %i", dt);
     89 }
     90 
     91 void Allocation::validateIsInt8() {
     92     RsDataType dt = mType->getElement()->getDataType();
     93     if ((dt == RS_TYPE_SIGNED_8) || (dt == RS_TYPE_UNSIGNED_8)) {
     94         return;
     95     }
     96     ALOGE("8 bit integer source does not match allocation type %i", dt);
     97 }
     98 
     99 void Allocation::validateIsFloat32() {
    100     RsDataType dt = mType->getElement()->getDataType();
    101     if (dt == RS_TYPE_FLOAT_32) {
    102         return;
    103     }
    104     ALOGE("32 bit float source does not match allocation type %i", dt);
    105 }
    106 
    107 void Allocation::validateIsObject() {
    108     RsDataType dt = mType->getElement()->getDataType();
    109     if ((dt == RS_TYPE_ELEMENT) ||
    110         (dt == RS_TYPE_TYPE) ||
    111         (dt == RS_TYPE_ALLOCATION) ||
    112         (dt == RS_TYPE_SAMPLER) ||
    113         (dt == RS_TYPE_SCRIPT) ||
    114         (dt == RS_TYPE_MESH) ||
    115         (dt == RS_TYPE_PROGRAM_FRAGMENT) ||
    116         (dt == RS_TYPE_PROGRAM_VERTEX) ||
    117         (dt == RS_TYPE_PROGRAM_RASTER) ||
    118         (dt == RS_TYPE_PROGRAM_STORE)) {
    119         return;
    120     }
    121     ALOGE("Object source does not match allocation type %i", dt);
    122 }
    123 
    124 void Allocation::updateFromNative() {
    125     BaseObj::updateFromNative();
    126 
    127     const void *typeID = RS::dispatch->AllocationGetType(mRS->getContext(), getID());
    128     if(typeID != NULL) {
    129         sp<const Type> old = mType;
    130         sp<Type> t = new Type((void *)typeID, mRS);
    131         t->updateFromNative();
    132         updateCacheInfo(t);
    133         mType = t;
    134     }
    135 }
    136 
    137 void Allocation::syncAll(RsAllocationUsageType srcLocation) {
    138     switch (srcLocation) {
    139     case RS_ALLOCATION_USAGE_SCRIPT:
    140     case RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS:
    141     case RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE:
    142     case RS_ALLOCATION_USAGE_GRAPHICS_VERTEX:
    143     case RS_ALLOCATION_USAGE_SHARED:
    144         break;
    145     default:
    146         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Source must be exactly one usage type.");
    147         return;
    148     }
    149     tryDispatch(mRS, RS::dispatch->AllocationSyncAll(mRS->getContext(), getIDSafe(), srcLocation));
    150 }
    151 
    152 void Allocation::ioSendOutput() {
    153 #ifndef RS_COMPATIBILITY_LIB
    154     if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) {
    155         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only send buffer if IO_OUTPUT usage specified.");
    156         return;
    157     }
    158     tryDispatch(mRS, RS::dispatch->AllocationIoSend(mRS->getContext(), getID()));
    159 #endif
    160 }
    161 
    162 void Allocation::ioGetInput() {
    163 #ifndef RS_COMPATIBILITY_LIB
    164     if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) {
    165         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only send buffer if IO_OUTPUT usage specified.");
    166         return;
    167     }
    168     tryDispatch(mRS, RS::dispatch->AllocationIoReceive(mRS->getContext(), getID()));
    169 #endif
    170 }
    171 
    172 void Allocation::generateMipmaps() {
    173     tryDispatch(mRS, RS::dispatch->AllocationGenerateMipmaps(mRS->getContext(), getID()));
    174 }
    175 
    176 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const void *data) {
    177 
    178     if(count < 1) {
    179         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1.");
    180         return;
    181     }
    182     if((off + count) > mCurrentCount) {
    183         ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off);
    184         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified");
    185         return;
    186     }
    187 
    188     tryDispatch(mRS, RS::dispatch->Allocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD,
    189                                                     count, data, count * mType->getElement()->getSizeBytes()));
    190 }
    191 
    192 void Allocation::copy1DRangeTo(uint32_t off, size_t count, void *data) {
    193     if(count < 1) {
    194         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1.");
    195         return;
    196     }
    197     if((off + count) > mCurrentCount) {
    198         ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off);
    199         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified");
    200         return;
    201     }
    202 
    203     tryDispatch(mRS, RS::dispatch->Allocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD,
    204                                                     count, data, count * mType->getElement()->getSizeBytes()));
    205 }
    206 
    207 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, sp<const Allocation> data,
    208                                  uint32_t dataOff) {
    209 
    210     tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), off, 0,
    211                                                          mSelectedLOD, mSelectedFace,
    212                                                          count, 1, data->getIDSafe(), dataOff, 0,
    213                                                          data->mSelectedLOD, data->mSelectedFace));
    214 }
    215 
    216 void Allocation::copy1DFrom(const void* data) {
    217     copy1DRangeFrom(0, mCurrentCount, data);
    218 }
    219 
    220 void Allocation::copy1DTo(void* data) {
    221     copy1DRangeTo(0, mCurrentCount, data);
    222 }
    223 
    224 
    225 void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) {
    226     if (mAdaptedAllocation != NULL) {
    227 
    228     } else {
    229         if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
    230             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation.");
    231         }
    232     }
    233 }
    234 
    235 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    236                                  const void *data) {
    237     validate2DRange(xoff, yoff, w, h);
    238     tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff,
    239                                                     yoff, mSelectedLOD, mSelectedFace,
    240                                                     w, h, data, w * h * mType->getElement()->getSizeBytes(),
    241                                                     w * mType->getElement()->getSizeBytes()));
    242 }
    243 
    244 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    245                                  sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff) {
    246     validate2DRange(xoff, yoff, w, h);
    247     tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), xoff, yoff,
    248                                                          mSelectedLOD, mSelectedFace,
    249                                                          w, h, data->getIDSafe(), dataXoff, dataYoff,
    250                                                          data->mSelectedLOD, data->mSelectedFace));
    251 }
    252 
    253 void Allocation::copy2DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    254                                void* data) {
    255     validate2DRange(xoff, yoff, w, h);
    256     tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff,
    257                                                     mSelectedLOD, mSelectedFace, w, h, data,
    258                                                     w * h * mType->getElement()->getSizeBytes(),
    259                                                     w * mType->getElement()->getSizeBytes()));
    260 }
    261 
    262 void Allocation::copy2DStridedFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    263                                    const void *data, size_t stride) {
    264     validate2DRange(xoff, yoff, w, h);
    265     tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff,
    266                                                     mSelectedLOD, mSelectedFace, w, h, data,
    267                                                     w * h * mType->getElement()->getSizeBytes(), stride));
    268 }
    269 
    270 void Allocation::copy2DStridedFrom(const void* data, size_t stride) {
    271     copy2DStridedFrom(0, 0, mCurrentDimX, mCurrentDimY, data, stride);
    272 }
    273 
    274 void Allocation::copy2DStridedTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    275                                  void *data, size_t stride) {
    276     validate2DRange(xoff, yoff, w, h);
    277     tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff,
    278                                                     mSelectedLOD, mSelectedFace, w, h, data,
    279                                                     w * h * mType->getElement()->getSizeBytes(), stride));
    280 }
    281 
    282 void Allocation::copy2DStridedTo(void* data, size_t stride) {
    283     copy2DStridedTo(0, 0, mCurrentDimX, mCurrentDimY, data, stride);
    284 }
    285 
    286 void Allocation::validate3DRange(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w,
    287                                  uint32_t h, uint32_t d) {
    288     if (mAdaptedAllocation != NULL) {
    289 
    290     } else {
    291         if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) {
    292             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation.");
    293         }
    294     }
    295 }
    296 
    297 void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w,
    298                                  uint32_t h, uint32_t d, const void* data) {
    299     validate3DRange(xoff, yoff, zoff, w, h, d);
    300     tryDispatch(mRS, RS::dispatch->Allocation3DData(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
    301                                                     mSelectedLOD, w, h, d, data,
    302                                                     w * h * d * mType->getElement()->getSizeBytes(),
    303                                                     w * mType->getElement()->getSizeBytes()));
    304 }
    305 
    306 void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, uint32_t h, uint32_t d,
    307                                  sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff, uint32_t dataZoff) {
    308     validate3DRange(xoff, yoff, zoff, dataXoff, dataYoff, dataZoff);
    309     tryDispatch(mRS, RS::dispatch->AllocationCopy3DRange(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
    310                                                          mSelectedLOD, w, h, d, data->getIDSafe(),
    311                                                          dataXoff, dataYoff, dataZoff, data->mSelectedLOD));
    312 }
    313 
    314 
    315 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
    316                                     RsAllocationMipmapControl mips, uint32_t usage) {
    317     void *id = 0;
    318     if (rs->getError() == RS_SUCCESS) {
    319         id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, 0);
    320     }
    321     if (id == 0) {
    322         rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed");
    323         return NULL;
    324     }
    325     return new Allocation(id, rs, type, usage);
    326 }
    327 
    328 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
    329                                     RsAllocationMipmapControl mips, uint32_t usage,
    330                                     void *pointer) {
    331     void *id = 0;
    332     if (rs->getError() == RS_SUCCESS) {
    333         id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mips, usage,
    334                                                  (uintptr_t)pointer);
    335     }
    336     if (id == 0) {
    337         rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed");
    338         return NULL;
    339     }
    340     return new Allocation(id, rs, type, usage);
    341 }
    342 
    343 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
    344                                     uint32_t usage) {
    345     return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage);
    346 }
    347 
    348 sp<Allocation> Allocation::createSized(sp<RS> rs, sp<const Element> e,
    349                                     size_t count, uint32_t usage) {
    350     Type::Builder b(rs, e);
    351     b.setX(count);
    352     sp<const Type> t = b.create();
    353 
    354     return createTyped(rs, t, usage);
    355 }
    356 
    357 sp<Allocation> Allocation::createSized2D(sp<RS> rs, sp<const Element> e,
    358                                       size_t x, size_t y, uint32_t usage) {
    359     Type::Builder b(rs, e);
    360     b.setX(x);
    361     b.setY(y);
    362     sp<const Type> t = b.create();
    363 
    364     return createTyped(rs, t, usage);
    365 }
    366