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::getPointer(size_t *stride) {
    173     void *p = NULL;
    174     if (!(mUsage & RS_ALLOCATION_USAGE_SHARED)) {
    175         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Allocation does not support USAGE_SHARED.");
    176         return NULL;
    177     }
    178 
    179     // FIXME: decide if lack of getPointer should cause compat mode
    180     if (RS::dispatch->AllocationGetPointer == NULL) {
    181         mRS->throwError(RS_ERROR_RUNTIME_ERROR, "Can't use getPointer on older APIs");
    182         return NULL;
    183     }
    184 
    185     p = RS::dispatch->AllocationGetPointer(mRS->getContext(), getIDSafe(), 0,
    186                                            RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, 0, 0, stride);
    187     if (mRS->getError() != RS_SUCCESS) {
    188         mRS->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation lock failed");
    189         p = NULL;
    190     }
    191     return p;
    192 }
    193 
    194 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const void *data) {
    195 
    196     if(count < 1) {
    197         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1.");
    198         return;
    199     }
    200     if((off + count) > mCurrentCount) {
    201         ALOGE("Overflow, Available count %u, got %zu at offset %u.", mCurrentCount, count, off);
    202         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified");
    203         return;
    204     }
    205 
    206     tryDispatch(mRS, RS::dispatch->Allocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD,
    207                                                     count, data, count * mType->getElement()->getSizeBytes()));
    208 }
    209 
    210 void Allocation::copy1DRangeTo(uint32_t off, size_t count, void *data) {
    211     if(count < 1) {
    212         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1.");
    213         return;
    214     }
    215     if((off + count) > mCurrentCount) {
    216         ALOGE("Overflow, Available count %u, got %zu at offset %u.", mCurrentCount, count, off);
    217         mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified");
    218         return;
    219     }
    220 
    221     tryDispatch(mRS, RS::dispatch->Allocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD,
    222                                                     count, data, count * mType->getElement()->getSizeBytes()));
    223 }
    224 
    225 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, sp<const Allocation> data,
    226                                  uint32_t dataOff) {
    227 
    228     tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), off, 0,
    229                                                          mSelectedLOD, mSelectedFace,
    230                                                          count, 1, data->getIDSafe(), dataOff, 0,
    231                                                          data->mSelectedLOD, data->mSelectedFace));
    232 }
    233 
    234 void Allocation::copy1DFrom(const void* data) {
    235     copy1DRangeFrom(0, mCurrentCount, data);
    236 }
    237 
    238 void Allocation::copy1DTo(void* data) {
    239     copy1DRangeTo(0, mCurrentCount, data);
    240 }
    241 
    242 
    243 void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) {
    244     if (mAdaptedAllocation != NULL) {
    245 
    246     } else {
    247         if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) {
    248             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation.");
    249         }
    250     }
    251 }
    252 
    253 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    254                                  const void *data) {
    255     validate2DRange(xoff, yoff, w, h);
    256     tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff,
    257                                                     yoff, mSelectedLOD, mSelectedFace,
    258                                                     w, h, data, w * h * mType->getElement()->getSizeBytes(),
    259                                                     w * mType->getElement()->getSizeBytes()));
    260 }
    261 
    262 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    263                                  sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff) {
    264     validate2DRange(xoff, yoff, w, h);
    265     tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), xoff, yoff,
    266                                                          mSelectedLOD, mSelectedFace,
    267                                                          w, h, data->getIDSafe(), dataXoff, dataYoff,
    268                                                          data->mSelectedLOD, data->mSelectedFace));
    269 }
    270 
    271 void Allocation::copy2DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    272                                void* data) {
    273     validate2DRange(xoff, yoff, w, h);
    274     tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff,
    275                                                     mSelectedLOD, mSelectedFace, w, h, data,
    276                                                     w * h * mType->getElement()->getSizeBytes(),
    277                                                     w * mType->getElement()->getSizeBytes()));
    278 }
    279 
    280 void Allocation::copy2DStridedFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    281                                    const void *data, size_t stride) {
    282     validate2DRange(xoff, yoff, w, h);
    283     tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff,
    284                                                     mSelectedLOD, mSelectedFace, w, h, data,
    285                                                     w * h * mType->getElement()->getSizeBytes(), stride));
    286 }
    287 
    288 void Allocation::copy2DStridedFrom(const void* data, size_t stride) {
    289     copy2DStridedFrom(0, 0, mCurrentDimX, mCurrentDimY, data, stride);
    290 }
    291 
    292 void Allocation::copy2DStridedTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h,
    293                                  void *data, size_t stride) {
    294     validate2DRange(xoff, yoff, w, h);
    295     tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff,
    296                                                     mSelectedLOD, mSelectedFace, w, h, data,
    297                                                     w * h * mType->getElement()->getSizeBytes(), stride));
    298 }
    299 
    300 void Allocation::copy2DStridedTo(void* data, size_t stride) {
    301     copy2DStridedTo(0, 0, mCurrentDimX, mCurrentDimY, data, stride);
    302 }
    303 
    304 void Allocation::validate3DRange(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w,
    305                                  uint32_t h, uint32_t d) {
    306     if (mAdaptedAllocation != NULL) {
    307 
    308     } else {
    309         if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) {
    310             mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation.");
    311         }
    312     }
    313 }
    314 
    315 void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w,
    316                                  uint32_t h, uint32_t d, const void* data) {
    317     validate3DRange(xoff, yoff, zoff, w, h, d);
    318     tryDispatch(mRS, RS::dispatch->Allocation3DData(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
    319                                                     mSelectedLOD, w, h, d, data,
    320                                                     w * h * d * mType->getElement()->getSizeBytes(),
    321                                                     w * mType->getElement()->getSizeBytes()));
    322 }
    323 
    324 void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, uint32_t h, uint32_t d,
    325                                  sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff, uint32_t dataZoff) {
    326     validate3DRange(xoff, yoff, zoff, dataXoff, dataYoff, dataZoff);
    327     tryDispatch(mRS, RS::dispatch->AllocationCopy3DRange(mRS->getContext(), getIDSafe(), xoff, yoff, zoff,
    328                                                          mSelectedLOD, w, h, d, data->getIDSafe(),
    329                                                          dataXoff, dataYoff, dataZoff, data->mSelectedLOD));
    330 }
    331 
    332 
    333 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
    334                                     RsAllocationMipmapControl mipmaps, uint32_t usage) {
    335     void *id = 0;
    336     if (rs->getError() == RS_SUCCESS) {
    337         id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mipmaps, usage, 0);
    338     }
    339     if (id == 0) {
    340         rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed");
    341         return NULL;
    342     }
    343     return new Allocation(id, rs, type, usage);
    344 }
    345 
    346 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
    347                                     RsAllocationMipmapControl mipmaps, uint32_t usage,
    348                                     void *pointer) {
    349     void *id = 0;
    350     if (rs->getError() == RS_SUCCESS) {
    351         id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mipmaps, usage,
    352                                                  (uintptr_t)pointer);
    353     }
    354     if (id == 0) {
    355         rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed");
    356         return NULL;
    357     }
    358     return new Allocation(id, rs, type, usage);
    359 }
    360 
    361 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type,
    362                                     uint32_t usage) {
    363     return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage);
    364 }
    365 
    366 sp<Allocation> Allocation::createSized(sp<RS> rs, sp<const Element> e,
    367                                     size_t count, uint32_t usage) {
    368     Type::Builder b(rs, e);
    369     b.setX(count);
    370     sp<const Type> t = b.create();
    371 
    372     return createTyped(rs, t, usage);
    373 }
    374 
    375 sp<Allocation> Allocation::createSized2D(sp<RS> rs, sp<const Element> e,
    376                                       size_t x, size_t y, uint32_t usage) {
    377     Type::Builder b(rs, e);
    378     b.setX(x);
    379     b.setY(y);
    380     sp<const Type> t = b.create();
    381 
    382     return createTyped(rs, t, usage);
    383 }
    384