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