Allocation.cpp revision 94280f817b502caf0b4e40cbcbe300f5178b7473
1/* 2 * Copyright (C) 2013 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 "rsCppInternal.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 != nullptr) { 68 updateCacheInfo(t); 69 } 70 71} 72 73 74 75void Allocation::validateIsInt32() { 76 RsDataType dt = mType->getElement()->getDataType(); 77 if ((dt == RS_TYPE_SIGNED_32) || (dt == RS_TYPE_UNSIGNED_32)) { 78 return; 79 } 80 ALOGE("32 bit integer source does not match allocation type %i", dt); 81} 82 83void Allocation::validateIsInt16() { 84 RsDataType dt = mType->getElement()->getDataType(); 85 if ((dt == RS_TYPE_SIGNED_16) || (dt == RS_TYPE_UNSIGNED_16)) { 86 return; 87 } 88 ALOGE("16 bit integer source does not match allocation type %i", dt); 89} 90 91void Allocation::validateIsInt8() { 92 RsDataType dt = mType->getElement()->getDataType(); 93 if ((dt == RS_TYPE_SIGNED_8) || (dt == RS_TYPE_UNSIGNED_8)) { 94 return; 95 } 96 ALOGE("8 bit integer source does not match allocation type %i", dt); 97} 98 99void Allocation::validateIsFloat32() { 100 RsDataType dt = mType->getElement()->getDataType(); 101 if (dt == RS_TYPE_FLOAT_32) { 102 return; 103 } 104 ALOGE("32 bit float source does not match allocation type %i", dt); 105} 106 107void Allocation::validateIsObject() { 108 RsDataType dt = mType->getElement()->getDataType(); 109 if ((dt == RS_TYPE_ELEMENT) || 110 (dt == RS_TYPE_TYPE) || 111 (dt == RS_TYPE_ALLOCATION) || 112 (dt == RS_TYPE_SAMPLER) || 113 (dt == RS_TYPE_SCRIPT) || 114 (dt == RS_TYPE_MESH) || 115 (dt == RS_TYPE_PROGRAM_FRAGMENT) || 116 (dt == RS_TYPE_PROGRAM_VERTEX) || 117 (dt == RS_TYPE_PROGRAM_RASTER) || 118 (dt == RS_TYPE_PROGRAM_STORE)) { 119 return; 120 } 121 ALOGE("Object source does not match allocation type %i", dt); 122} 123 124void Allocation::updateFromNative() { 125 BaseObj::updateFromNative(); 126 127 const void *typeID = RS::dispatch->AllocationGetType(mRS->getContext(), getID()); 128 if(typeID != nullptr) { 129 sp<const Type> old = mType; 130 sp<Type> t = new Type((void *)typeID, mRS); 131 t->updateFromNative(); 132 updateCacheInfo(t); 133 mType = t; 134 } 135} 136 137void Allocation::syncAll(RsAllocationUsageType srcLocation) { 138 switch (srcLocation) { 139 case RS_ALLOCATION_USAGE_SCRIPT: 140 case RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS: 141 case RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE: 142 case RS_ALLOCATION_USAGE_GRAPHICS_VERTEX: 143 case RS_ALLOCATION_USAGE_SHARED: 144 break; 145 default: 146 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Source must be exactly one usage type."); 147 return; 148 } 149 tryDispatch(mRS, RS::dispatch->AllocationSyncAll(mRS->getContext(), getIDSafe(), srcLocation)); 150} 151 152void Allocation::ioSendOutput() { 153#ifndef RS_COMPATIBILITY_LIB 154 if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) { 155 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only send buffer if IO_OUTPUT usage specified."); 156 return; 157 } 158 tryDispatch(mRS, RS::dispatch->AllocationIoSend(mRS->getContext(), getID())); 159#endif 160} 161 162void Allocation::ioGetInput() { 163#ifndef RS_COMPATIBILITY_LIB 164 if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) { 165 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Can only send buffer if IO_OUTPUT usage specified."); 166 return; 167 } 168 tryDispatch(mRS, RS::dispatch->AllocationIoReceive(mRS->getContext(), getID())); 169#endif 170} 171 172void * Allocation::getPointer(size_t *stride) { 173 void *p = nullptr; 174 if (!(mUsage & RS_ALLOCATION_USAGE_SHARED)) { 175 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Allocation does not support USAGE_SHARED."); 176 return nullptr; 177 } 178 179 // FIXME: decide if lack of getPointer should cause compat mode 180 if (RS::dispatch->AllocationGetPointer == nullptr) { 181 mRS->throwError(RS_ERROR_RUNTIME_ERROR, "Can't use getPointer on older APIs"); 182 return nullptr; 183 } 184 185 p = RS::dispatch->AllocationGetPointer(mRS->getContext(), getIDSafe(), 0, 186 RS_ALLOCATION_CUBEMAP_FACE_POSITIVE_X, 0, 0, stride, sizeof(size_t)); 187 if (mRS->getError() != RS_SUCCESS) { 188 mRS->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation lock failed"); 189 p = nullptr; 190 } 191 return p; 192} 193 194void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const void *data) { 195 196 if(count < 1) { 197 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1."); 198 return; 199 } 200 if((off + count) > mCurrentCount) { 201 ALOGE("Overflow, Available count %u, got %zu at offset %u.", mCurrentCount, count, off); 202 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified"); 203 return; 204 } 205 206 tryDispatch(mRS, RS::dispatch->Allocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD, 207 count, data, count * mType->getElement()->getSizeBytes())); 208} 209 210void Allocation::copy1DRangeTo(uint32_t off, size_t count, void *data) { 211 if(count < 1) { 212 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1."); 213 return; 214 } 215 if((off + count) > mCurrentCount) { 216 ALOGE("Overflow, Available count %u, got %zu at offset %u.", mCurrentCount, count, off); 217 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified"); 218 return; 219 } 220 221 tryDispatch(mRS, RS::dispatch->Allocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD, 222 count, data, count * mType->getElement()->getSizeBytes())); 223} 224 225void Allocation::copy1DRangeFrom(uint32_t off, size_t count, sp<const Allocation> data, 226 uint32_t dataOff) { 227 228 tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), off, 0, 229 mSelectedLOD, mSelectedFace, 230 count, 1, data->getIDSafe(), dataOff, 0, 231 data->mSelectedLOD, data->mSelectedFace)); 232} 233 234void Allocation::copy1DFrom(const void* data) { 235 copy1DRangeFrom(0, mCurrentCount, data); 236} 237 238void Allocation::copy1DTo(void* data) { 239 copy1DRangeTo(0, mCurrentCount, data); 240} 241 242 243void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) { 244 if (mAdaptedAllocation != nullptr) { 245 246 } else { 247 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) { 248 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation."); 249 } 250 } 251} 252 253void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 254 const void *data) { 255 validate2DRange(xoff, yoff, w, h); 256 tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, 257 yoff, mSelectedLOD, mSelectedFace, 258 w, h, data, w * h * mType->getElement()->getSizeBytes(), 259 w * mType->getElement()->getSizeBytes())); 260} 261 262void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 263 sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff) { 264 validate2DRange(xoff, yoff, w, h); 265 tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), xoff, yoff, 266 mSelectedLOD, mSelectedFace, 267 w, h, data->getIDSafe(), dataXoff, dataYoff, 268 data->mSelectedLOD, data->mSelectedFace)); 269} 270 271void Allocation::copy2DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 272 void* data) { 273 validate2DRange(xoff, yoff, w, h); 274 tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, 275 mSelectedLOD, mSelectedFace, w, h, data, 276 w * h * mType->getElement()->getSizeBytes(), 277 w * mType->getElement()->getSizeBytes())); 278} 279 280void Allocation::copy2DStridedFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 281 const void *data, size_t stride) { 282 validate2DRange(xoff, yoff, w, h); 283 tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, 284 mSelectedLOD, mSelectedFace, w, h, data, 285 w * h * mType->getElement()->getSizeBytes(), stride)); 286} 287 288void Allocation::copy2DStridedFrom(const void* data, size_t stride) { 289 copy2DStridedFrom(0, 0, mCurrentDimX, mCurrentDimY, data, stride); 290} 291 292void Allocation::copy2DStridedTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 293 void *data, size_t stride) { 294 validate2DRange(xoff, yoff, w, h); 295 tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, 296 mSelectedLOD, mSelectedFace, w, h, data, 297 w * h * mType->getElement()->getSizeBytes(), stride)); 298} 299 300void Allocation::copy2DStridedTo(void* data, size_t stride) { 301 copy2DStridedTo(0, 0, mCurrentDimX, mCurrentDimY, data, stride); 302} 303 304void Allocation::validate3DRange(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, 305 uint32_t h, uint32_t d) { 306 if (mAdaptedAllocation != nullptr) { 307 308 } else { 309 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) { 310 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation."); 311 } 312 } 313} 314 315void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, 316 uint32_t h, uint32_t d, const void* data) { 317 validate3DRange(xoff, yoff, zoff, w, h, d); 318 tryDispatch(mRS, RS::dispatch->Allocation3DData(mRS->getContext(), getIDSafe(), xoff, yoff, zoff, 319 mSelectedLOD, w, h, d, data, 320 w * h * d * mType->getElement()->getSizeBytes(), 321 w * mType->getElement()->getSizeBytes())); 322} 323 324void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, uint32_t h, uint32_t d, 325 sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff, uint32_t dataZoff) { 326 validate3DRange(xoff, yoff, zoff, dataXoff, dataYoff, dataZoff); 327 tryDispatch(mRS, RS::dispatch->AllocationCopy3DRange(mRS->getContext(), getIDSafe(), xoff, yoff, zoff, 328 mSelectedLOD, w, h, d, data->getIDSafe(), 329 dataXoff, dataYoff, dataZoff, data->mSelectedLOD)); 330} 331 332 333sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 334 RsAllocationMipmapControl mipmaps, uint32_t usage) { 335 void *id = 0; 336 if (rs->getError() == RS_SUCCESS) { 337 id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mipmaps, usage, 0); 338 } 339 if (id == 0) { 340 rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed"); 341 return nullptr; 342 } 343 return new Allocation(id, rs, type, usage); 344} 345 346sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 347 RsAllocationMipmapControl mipmaps, uint32_t usage, 348 void *pointer) { 349 void *id = 0; 350 if (rs->getError() == RS_SUCCESS) { 351 id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mipmaps, usage, 352 (uintptr_t)pointer); 353 } 354 if (id == 0) { 355 rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed"); 356 return nullptr; 357 } 358 return new Allocation(id, rs, type, usage); 359} 360 361sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 362 uint32_t usage) { 363 return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage); 364} 365 366sp<Allocation> Allocation::createSized(sp<RS> rs, sp<const Element> e, 367 size_t count, uint32_t usage) { 368 Type::Builder b(rs, e); 369 b.setX(count); 370 sp<const Type> t = b.create(); 371 372 return createTyped(rs, t, usage); 373} 374 375sp<Allocation> Allocation::createSized2D(sp<RS> rs, sp<const Element> e, 376 size_t x, size_t y, uint32_t usage) { 377 Type::Builder b(rs, e); 378 b.setX(x); 379 b.setY(y); 380 sp<const Type> t = b.create(); 381 382 return createTyped(rs, t, usage); 383} 384