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