Allocation.cpp revision 509ea5c832a865bc9083d53f1f058377a689bab3
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::copy1DRangeToUnchecked(uint32_t off, size_t count, void *data, size_t dataLen) { 182 if(count < 1) { 183 ALOGE("Count must be >= 1."); 184 return; 185 } 186 if((off + count) > mCurrentCount) { 187 ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off); 188 return; 189 } 190 if((count * mType->getElement()->getSizeBytes()) > dataLen) { 191 ALOGE("Array too small for allocation type."); 192 return; 193 } 194 rsAllocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD, count, data, dataLen); 195} 196 197void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int32_t *d, size_t dataLen) { 198 validateIsInt32(); 199 copy1DRangeFromUnchecked(off, count, d, dataLen); 200} 201 202void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int16_t *d, size_t dataLen) { 203 validateIsInt16(); 204 copy1DRangeFromUnchecked(off, count, d, dataLen); 205} 206 207void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int8_t *d, size_t dataLen) { 208 validateIsInt8(); 209 copy1DRangeFromUnchecked(off, count, d, dataLen); 210} 211 212void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const float *d, size_t dataLen) { 213 validateIsFloat32(); 214 copy1DRangeFromUnchecked(off, count, d, dataLen); 215} 216 217void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const Allocation *data, 218 uint32_t dataOff) { 219 220 rsAllocationCopy2DRange(mRS->getContext(), getIDSafe(), off, 0, 221 mSelectedLOD, mSelectedFace, 222 count, 1, data->getIDSafe(), dataOff, 0, 223 data->mSelectedLOD, data->mSelectedFace); 224} 225 226void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) { 227 if (mAdaptedAllocation != NULL) { 228 229 } else { 230 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) { 231 ALOGE("Updated region larger than allocation."); 232 } 233 } 234} 235 236void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 237 const int8_t *data, size_t dataLen) { 238 validate2DRange(xoff, yoff, w, h); 239 rsAllocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, 240 w, h, data, dataLen); 241} 242 243void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 244 const int16_t *data, size_t dataLen) { 245 validate2DRange(xoff, yoff, w, h); 246 rsAllocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, 247 w, h, data, dataLen); 248} 249 250void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 251 const int32_t *data, size_t dataLen) { 252 validate2DRange(xoff, yoff, w, h); 253 rsAllocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, 254 w, h, data, dataLen); 255} 256 257void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 258 const float *data, size_t dataLen) { 259 validate2DRange(xoff, yoff, w, h); 260 rsAllocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, 261 w, h, data, dataLen); 262} 263 264void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 265 const Allocation *data, size_t dataLen, 266 uint32_t dataXoff, uint32_t dataYoff) { 267 validate2DRange(xoff, yoff, w, h); 268 rsAllocationCopy2DRange(mRS->getContext(), getIDSafe(), xoff, yoff, 269 mSelectedLOD, mSelectedFace, 270 w, h, data->getIDSafe(), dataXoff, dataYoff, 271 data->mSelectedLOD, data->mSelectedFace); 272} 273 274/* 275void resize(int dimX) { 276 if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) { 277 throw new RSInvalidStateException("Resize only support for 1D allocations at this time."); 278 } 279 mRS.nAllocationResize1D(getID(), dimX); 280 mRS.finish(); // Necessary because resize is fifoed and update is async. 281 282 int typeID = mRS.nAllocationGetType(getID()); 283 mType = new Type(typeID, mRS); 284 mType.updateFromNative(); 285 updateCacheInfo(mType); 286} 287 288void resize(int dimX, int dimY) { 289 if ((mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) { 290 throw new RSInvalidStateException( 291 "Resize only support for 2D allocations at this time."); 292 } 293 if (mType.getY() == 0) { 294 throw new RSInvalidStateException( 295 "Resize only support for 2D allocations at this time."); 296 } 297 mRS.nAllocationResize2D(getID(), dimX, dimY); 298 mRS.finish(); // Necessary because resize is fifoed and update is async. 299 300 int typeID = mRS.nAllocationGetType(getID()); 301 mType = new Type(typeID, mRS); 302 mType.updateFromNative(); 303 updateCacheInfo(mType); 304} 305*/ 306 307 308android::sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 309 RsAllocationMipmapControl mips, uint32_t usage) { 310 void *id = rsAllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, 0); 311 if (id == 0) { 312 ALOGE("Allocation creation failed."); 313 return NULL; 314 } 315 return new Allocation(id, rs, type, usage); 316} 317 318android::sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 319 RsAllocationMipmapControl mips, uint32_t usage, void *pointer) { 320 void *id = rsAllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, (uint32_t)pointer); 321 if (id == 0) { 322 ALOGE("Allocation creation failed."); 323 } 324 return new Allocation(id, rs, type, usage); 325} 326 327android::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 332android::sp<Allocation> Allocation::createSized(sp<RS> rs, sp<const Element> e, 333 size_t count, uint32_t usage) { 334 335 Type::Builder b(rs, e); 336 b.setX(count); 337 sp<const Type> t = b.create(); 338 339 void *id = rsAllocationCreateTyped(rs->getContext(), t->getID(), 340 RS_ALLOCATION_MIPMAP_NONE, usage, 0); 341 if (id == 0) { 342 ALOGE("Allocation creation failed."); 343 } 344 return new Allocation(id, rs, t, usage); 345} 346