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