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 20 using namespace android; 21 using namespace RSC; 22 23 void * Allocation::getIDSafe() const { 24 return getID(); 25 } 26 27 void 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 40 Allocation::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 != NULL) { 68 updateCacheInfo(t); 69 } 70 71 } 72 73 74 75 void 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 83 void 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 91 void 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 99 void 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 107 void 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 124 void Allocation::updateFromNative() { 125 BaseObj::updateFromNative(); 126 127 const void *typeID = RS::dispatch->AllocationGetType(mRS->getContext(), getID()); 128 if(typeID != NULL) { 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 137 void 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 152 void 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 162 void 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 172 void Allocation::generateMipmaps() { 173 tryDispatch(mRS, RS::dispatch->AllocationGenerateMipmaps(mRS->getContext(), getID())); 174 } 175 176 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const void *data) { 177 178 if(count < 1) { 179 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1."); 180 return; 181 } 182 if((off + count) > mCurrentCount) { 183 ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off); 184 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified"); 185 return; 186 } 187 188 tryDispatch(mRS, RS::dispatch->Allocation1DData(mRS->getContext(), getIDSafe(), off, mSelectedLOD, 189 count, data, count * mType->getElement()->getSizeBytes())); 190 } 191 192 void Allocation::copy1DRangeTo(uint32_t off, size_t count, void *data) { 193 if(count < 1) { 194 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Count must be >= 1."); 195 return; 196 } 197 if((off + count) > mCurrentCount) { 198 ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off); 199 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Invalid copy specified"); 200 return; 201 } 202 203 tryDispatch(mRS, RS::dispatch->Allocation1DRead(mRS->getContext(), getIDSafe(), off, mSelectedLOD, 204 count, data, count * mType->getElement()->getSizeBytes())); 205 } 206 207 void Allocation::copy1DRangeFrom(uint32_t off, size_t count, sp<const Allocation> data, 208 uint32_t dataOff) { 209 210 tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), off, 0, 211 mSelectedLOD, mSelectedFace, 212 count, 1, data->getIDSafe(), dataOff, 0, 213 data->mSelectedLOD, data->mSelectedFace)); 214 } 215 216 void Allocation::copy1DFrom(const void* data) { 217 copy1DRangeFrom(0, mCurrentCount, data); 218 } 219 220 void Allocation::copy1DTo(void* data) { 221 copy1DRangeTo(0, mCurrentCount, data); 222 } 223 224 225 void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) { 226 if (mAdaptedAllocation != NULL) { 227 228 } else { 229 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) { 230 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation."); 231 } 232 } 233 } 234 235 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 236 const void *data) { 237 validate2DRange(xoff, yoff, w, h); 238 tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, 239 yoff, mSelectedLOD, mSelectedFace, 240 w, h, data, w * h * mType->getElement()->getSizeBytes(), 241 w * mType->getElement()->getSizeBytes())); 242 } 243 244 void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 245 sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff) { 246 validate2DRange(xoff, yoff, w, h); 247 tryDispatch(mRS, RS::dispatch->AllocationCopy2DRange(mRS->getContext(), getIDSafe(), xoff, yoff, 248 mSelectedLOD, mSelectedFace, 249 w, h, data->getIDSafe(), dataXoff, dataYoff, 250 data->mSelectedLOD, data->mSelectedFace)); 251 } 252 253 void Allocation::copy2DRangeTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 254 void* data) { 255 validate2DRange(xoff, yoff, w, h); 256 tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, 257 mSelectedLOD, mSelectedFace, w, h, data, 258 w * h * mType->getElement()->getSizeBytes(), 259 w * mType->getElement()->getSizeBytes())); 260 } 261 262 void Allocation::copy2DStridedFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 263 const void *data, size_t stride) { 264 validate2DRange(xoff, yoff, w, h); 265 tryDispatch(mRS, RS::dispatch->Allocation2DData(mRS->getContext(), getIDSafe(), xoff, yoff, 266 mSelectedLOD, mSelectedFace, w, h, data, 267 w * h * mType->getElement()->getSizeBytes(), stride)); 268 } 269 270 void Allocation::copy2DStridedFrom(const void* data, size_t stride) { 271 copy2DStridedFrom(0, 0, mCurrentDimX, mCurrentDimY, data, stride); 272 } 273 274 void Allocation::copy2DStridedTo(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 275 void *data, size_t stride) { 276 validate2DRange(xoff, yoff, w, h); 277 tryDispatch(mRS, RS::dispatch->Allocation2DRead(mRS->getContext(), getIDSafe(), xoff, yoff, 278 mSelectedLOD, mSelectedFace, w, h, data, 279 w * h * mType->getElement()->getSizeBytes(), stride)); 280 } 281 282 void Allocation::copy2DStridedTo(void* data, size_t stride) { 283 copy2DStridedTo(0, 0, mCurrentDimX, mCurrentDimY, data, stride); 284 } 285 286 void Allocation::validate3DRange(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, 287 uint32_t h, uint32_t d) { 288 if (mAdaptedAllocation != NULL) { 289 290 } else { 291 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY) || ((zoff + d) > mCurrentDimZ)) { 292 mRS->throwError(RS_ERROR_INVALID_PARAMETER, "Updated region larger than allocation."); 293 } 294 } 295 } 296 297 void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, 298 uint32_t h, uint32_t d, const void* data) { 299 validate3DRange(xoff, yoff, zoff, w, h, d); 300 tryDispatch(mRS, RS::dispatch->Allocation3DData(mRS->getContext(), getIDSafe(), xoff, yoff, zoff, 301 mSelectedLOD, w, h, d, data, 302 w * h * d * mType->getElement()->getSizeBytes(), 303 w * mType->getElement()->getSizeBytes())); 304 } 305 306 void Allocation::copy3DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t zoff, uint32_t w, uint32_t h, uint32_t d, 307 sp<const Allocation> data, uint32_t dataXoff, uint32_t dataYoff, uint32_t dataZoff) { 308 validate3DRange(xoff, yoff, zoff, dataXoff, dataYoff, dataZoff); 309 tryDispatch(mRS, RS::dispatch->AllocationCopy3DRange(mRS->getContext(), getIDSafe(), xoff, yoff, zoff, 310 mSelectedLOD, w, h, d, data->getIDSafe(), 311 dataXoff, dataYoff, dataZoff, data->mSelectedLOD)); 312 } 313 314 315 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 316 RsAllocationMipmapControl mips, uint32_t usage) { 317 void *id = 0; 318 if (rs->getError() == RS_SUCCESS) { 319 id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, 0); 320 } 321 if (id == 0) { 322 rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed"); 323 return NULL; 324 } 325 return new Allocation(id, rs, type, usage); 326 } 327 328 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 329 RsAllocationMipmapControl mips, uint32_t usage, 330 void *pointer) { 331 void *id = 0; 332 if (rs->getError() == RS_SUCCESS) { 333 id = RS::dispatch->AllocationCreateTyped(rs->getContext(), type->getID(), mips, usage, 334 (uintptr_t)pointer); 335 } 336 if (id == 0) { 337 rs->throwError(RS_ERROR_RUNTIME_ERROR, "Allocation creation failed"); 338 return NULL; 339 } 340 return new Allocation(id, rs, type, usage); 341 } 342 343 sp<Allocation> Allocation::createTyped(sp<RS> rs, sp<const Type> type, 344 uint32_t usage) { 345 return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage); 346 } 347 348 sp<Allocation> Allocation::createSized(sp<RS> rs, sp<const Element> e, 349 size_t count, uint32_t usage) { 350 Type::Builder b(rs, e); 351 b.setX(count); 352 sp<const Type> t = b.create(); 353 354 return createTyped(rs, t, usage); 355 } 356 357 sp<Allocation> Allocation::createSized2D(sp<RS> rs, sp<const Element> e, 358 size_t x, size_t y, uint32_t usage) { 359 Type::Builder b(rs, e); 360 b.setX(x); 361 b.setY(y); 362 sp<const Type> t = b.create(); 363 364 return createTyped(rs, t, usage); 365 } 366