Allocation.cpp revision b206acefa7ef03e02d3e8e161f8a1493329246b3
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 if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) { 149 ALOGE("Can only send buffer if IO_OUTPUT usage specified."); 150 } 151 rsAllocationIoSend(mRS->getContext(), getID()); 152} 153 154void Allocation::ioGetInput() { 155 if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) { 156 ALOGE("Can only send buffer if IO_OUTPUT usage specified."); 157 } 158 rsAllocationIoReceive(mRS->getContext(), getID()); 159} 160 161void Allocation::generateMipmaps() { 162 rsAllocationGenerateMipmaps(mRS->getContext(), getID()); 163} 164 165void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const void *data) { 166 167 if(count < 1) { 168 ALOGE("Count must be >= 1."); 169 return; 170 } 171 if((off + count) > mCurrentCount) { 172 ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off); 173 return; 174 } 175 176 rsAllocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD, count, data, 177 count * mType->getElement()->getSizeBytes()); 178} 179 180void Allocation::copy1DRangeTo(uint32_t off, size_t count, void *data) { 181 if(count < 1) { 182 ALOGE("Count must be >= 1."); 183 return; 184 } 185 if((off + count) > mCurrentCount) { 186 ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off); 187 return; 188 } 189 190 rsAllocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD, count, data, 191 count * mType->getElement()->getSizeBytes()); 192} 193 194void Allocation::copy1DRangeFrom(uint32_t off, size_t count, sp<const Allocation> data, 195 uint32_t dataOff) { 196 197 rsAllocationCopy2DRange(mRS->getContext(), getIDSafe(), off, 0, 198 mSelectedLOD, mSelectedFace, 199 count, 1, data->getIDSafe(), dataOff, 0, 200 data->mSelectedLOD, data->mSelectedFace); 201} 202 203void Allocation::copy1DFrom(const void* data) { 204 copy1DRangeFrom(0, mCurrentCount, data); 205} 206 207void Allocation::copy1DTo(void* data) { 208 copy1DRangeTo(0, mCurrentCount, data); 209} 210 211 212void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) { 213 if (mAdaptedAllocation != NULL) { 214 215 } else { 216 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) { 217 ALOGE("Updated region larger than allocation."); 218 } 219 } 220} 221 222void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 223 const void *data) { 224 validate2DRange(xoff, yoff, w, h); 225 rsAllocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, 226 w, h, data, w * h * mType->getElement()->getSizeBytes(), w * mType->getElement()->getSizeBytes()); 227} 228 229void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 230 sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff) { 231 validate2DRange(xoff, yoff, w, h); 232 rsAllocationCopy2DRange(mRS->getContext(), getIDSafe(), xoff, yoff, 233 mSelectedLOD, mSelectedFace, 234 w, h, data->getIDSafe(), dataXoff, dataYoff, 235 data->mSelectedLOD, data->mSelectedFace); 236} 237 238void Allocation::copy2DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 239 void* data) { 240 validate2DRange(xoff, yoff, w, h); 241 rsAllocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, 242 w, h, data, w * h * mType->getElement()->getSizeBytes(), w * mType->getElement()->getSizeBytes()); 243} 244 245void Allocation::copy2DStridedFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 246 const void *data, size_t stride) { 247 validate2DRange(xoff, yoff, w, h); 248 rsAllocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, 249 w, h, data, w * h * mType->getElement()->getSizeBytes(), stride); 250} 251 252void Allocation::copy2DStridedFrom(const void* data, size_t stride) { 253 copy2DStridedFrom(0, 0, mCurrentDimX, mCurrentDimY, data, stride); 254} 255 256void Allocation::copy2DStridedTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 257 void *data, size_t stride) { 258 validate2DRange(xoff, yoff, w, h); 259 rsAllocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, 260 w, h, data, w * h * mType->getElement()->getSizeBytes(), stride); 261} 262 263void Allocation::copy2DStridedTo(void* data, size_t stride) { 264 copy2DStridedTo(0, 0, mCurrentDimX, mCurrentDimY, data, stride); 265} 266 267 268/* 269void resize(int dimX) { 270 if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) { 271 throw new RSInvalidStateException("Resize only support for 1D allocations at this time."); 272 } 273 mRS.nAllocationResize1D(getID(), dimX); 274 mRS.finish(); // Necessary because resize is fifoed and update is async. 275 276 int typeID = mRS.nAllocationGetType(getID()); 277 mType = new Type(typeID, mRS); 278 mType.updateFromNative(); 279 updateCacheInfo(mType); 280} 281 282void resize(int dimX, int dimY) { 283 if ((mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) { 284 throw new RSInvalidStateException( 285 "Resize only support for 2D allocations at this time."); 286 } 287 if (mType.getY() == 0) { 288 throw new RSInvalidStateException( 289 "Resize only support for 2D allocations at this time."); 290 } 291 mRS.nAllocationResize2D(getID(), dimX, dimY); 292 mRS.finish(); // Necessary because resize is fifoed and update is async. 293 294 int typeID = mRS.nAllocationGetType(getID()); 295 mType = new Type(typeID, mRS); 296 mType.updateFromNative(); 297 updateCacheInfo(mType); 298} 299*/ 300 301 302android::sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 303 RsAllocationMipmapControl mips, uint32_t usage) { 304 void *id = rsAllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, 0); 305 if (id == 0) { 306 ALOGE("Allocation creation failed."); 307 return NULL; 308 } 309 return new Allocation(id, rs, type, usage); 310} 311 312android::sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 313 RsAllocationMipmapControl mips, uint32_t usage, 314 void *pointer) { 315 void *id = rsAllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, 316 (uint32_t)pointer); 317 if (id == 0) { 318 ALOGE("Allocation creation failed."); 319 } 320 return new Allocation(id, rs, type, usage); 321} 322 323android::sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 324 uint32_t usage) { 325 return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage); 326} 327 328android::sp<Allocation> Allocation::createSized(sp<RS> rs, sp<const Element> e, 329 size_t count, uint32_t usage) { 330 Type::Builder b(rs, e); 331 b.setX(count); 332 sp<const Type> t = b.create(); 333 334 return createTyped(rs, t, usage); 335} 336 337android::sp<Allocation> Allocation::createSized2D(sp<RS> rs, sp<const Element> e, 338 size_t x, size_t y, uint32_t usage) { 339 Type::Builder b(rs, e); 340 b.setX(x); 341 b.setY(y); 342 sp<const Type> t = b.create(); 343 344 return createTyped(rs, t, usage); 345} 346