Allocation.cpp revision a4cbc2b0cf0f6fbdb21e84a3e17585eda1885e3e
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::copy1DRangeFrom(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::copy1DRangeTo(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, 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::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) { 208 if (mAdaptedAllocation != NULL) { 209 210 } else { 211 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) { 212 ALOGE("Updated region larger than allocation."); 213 } 214 } 215} 216 217void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 218 const void *data, size_t dataLen) { 219 validate2DRange(xoff, yoff, w, h); 220 rsAllocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, 221 w, h, data, dataLen); 222} 223 224void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 225 sp<const Allocation> data, size_t dataLen, 226 uint32_t dataXoff, uint32_t dataYoff) { 227 validate2DRange(xoff, yoff, w, h); 228 rsAllocationCopy2DRange(mRS->getContext(), getIDSafe(), xoff, yoff, 229 mSelectedLOD, mSelectedFace, 230 w, h, data->getIDSafe(), dataXoff, dataYoff, 231 data->mSelectedLOD, data->mSelectedFace); 232} 233 234/* 235void resize(int dimX) { 236 if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) { 237 throw new RSInvalidStateException("Resize only support for 1D allocations at this time."); 238 } 239 mRS.nAllocationResize1D(getID(), dimX); 240 mRS.finish(); // Necessary because resize is fifoed and update is async. 241 242 int typeID = mRS.nAllocationGetType(getID()); 243 mType = new Type(typeID, mRS); 244 mType.updateFromNative(); 245 updateCacheInfo(mType); 246} 247 248void resize(int dimX, int dimY) { 249 if ((mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) { 250 throw new RSInvalidStateException( 251 "Resize only support for 2D allocations at this time."); 252 } 253 if (mType.getY() == 0) { 254 throw new RSInvalidStateException( 255 "Resize only support for 2D allocations at this time."); 256 } 257 mRS.nAllocationResize2D(getID(), dimX, dimY); 258 mRS.finish(); // Necessary because resize is fifoed and update is async. 259 260 int typeID = mRS.nAllocationGetType(getID()); 261 mType = new Type(typeID, mRS); 262 mType.updateFromNative(); 263 updateCacheInfo(mType); 264} 265*/ 266 267 268android::sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 269 RsAllocationMipmapControl mips, uint32_t usage) { 270 void *id = rsAllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, 0); 271 if (id == 0) { 272 ALOGE("Allocation creation failed."); 273 return NULL; 274 } 275 return new Allocation(id, rs, type, usage); 276} 277 278android::sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 279 RsAllocationMipmapControl mips, uint32_t usage, 280 void *pointer) { 281 void *id = rsAllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, 282 (uint32_t)pointer); 283 if (id == 0) { 284 ALOGE("Allocation creation failed."); 285 } 286 return new Allocation(id, rs, type, usage); 287} 288 289android::sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 290 uint32_t usage) { 291 return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage); 292} 293 294android::sp<Allocation> Allocation::createSized(sp<RS> rs, sp<const Element> e, 295 size_t count, uint32_t usage) { 296 Type::Builder b(rs, e); 297 b.setX(count); 298 sp<const Type> t = b.create(); 299 300 return createTyped(rs, t, usage); 301} 302 303android::sp<Allocation> Allocation::createSized2D(sp<RS> rs, sp<const Element> e, 304 size_t x, size_t y, uint32_t usage) { 305 Type::Builder b(rs, e); 306 b.setX(x); 307 b.setY(y); 308 sp<const Type> t = b.create(); 309 310 return createTyped(rs, t, usage); 311} 312