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