Allocation.cpp revision a662edd85843c2eb7078900b0279e38d6635795e
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#define LOG_TAG "libRS_cpp" 18 19#include <utils/Log.h> 20#include <malloc.h> 21 22#include "RenderScript.h" 23#include "Element.h" 24#include "Type.h" 25#include "Allocation.h" 26 27 28void * Allocation::getIDSafe() const { 29 //if (mAdaptedAllocation != NULL) { 30 //return mAdaptedAllocation.getID(); 31 //} 32 return getID(); 33} 34 35void Allocation::updateCacheInfo(const Type *t) { 36 mCurrentDimX = t->getX(); 37 mCurrentDimY = t->getY(); 38 mCurrentDimZ = t->getZ(); 39 mCurrentCount = mCurrentDimX; 40 if (mCurrentDimY > 1) { 41 mCurrentCount *= mCurrentDimY; 42 } 43 if (mCurrentDimZ > 1) { 44 mCurrentCount *= mCurrentDimZ; 45 } 46} 47 48Allocation::Allocation(void *id, RenderScript *rs, const Type *t, uint32_t usage) : BaseObj(id, rs) { 49 if ((usage & ~(RS_ALLOCATION_USAGE_SCRIPT | 50 RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE | 51 RS_ALLOCATION_USAGE_GRAPHICS_VERTEX | 52 RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS | 53 RS_ALLOCATION_USAGE_GRAPHICS_RENDER_TARGET | 54 RS_ALLOCATION_USAGE_IO_INPUT | 55 RS_ALLOCATION_USAGE_IO_OUTPUT)) != 0) { 56 ALOGE("Unknown usage specified."); 57 } 58 59 if ((usage & RS_ALLOCATION_USAGE_IO_INPUT) != 0) { 60 mWriteAllowed = false; 61 if ((usage & ~(RS_ALLOCATION_USAGE_IO_INPUT | 62 RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE | 63 RS_ALLOCATION_USAGE_SCRIPT)) != 0) { 64 ALOGE("Invalid usage combination."); 65 } 66 } 67 68 mType = t; 69 mUsage = usage; 70 71 if (t != NULL) { 72 updateCacheInfo(t); 73 } 74} 75 76void Allocation::validateIsInt32() { 77 RsDataType dt = mType->getElement()->getDataType(); 78 if ((dt == RS_TYPE_SIGNED_32) || (dt == RS_TYPE_UNSIGNED_32)) { 79 return; 80 } 81 ALOGE("32 bit integer source does not match allocation type %i", dt); 82} 83 84void Allocation::validateIsInt16() { 85 RsDataType dt = mType->getElement()->getDataType(); 86 if ((dt == RS_TYPE_SIGNED_16) || (dt == RS_TYPE_UNSIGNED_16)) { 87 return; 88 } 89 ALOGE("16 bit integer source does not match allocation type %i", dt); 90} 91 92void Allocation::validateIsInt8() { 93 RsDataType dt = mType->getElement()->getDataType(); 94 if ((dt == RS_TYPE_SIGNED_8) || (dt == RS_TYPE_UNSIGNED_8)) { 95 return; 96 } 97 ALOGE("8 bit integer source does not match allocation type %i", dt); 98} 99 100void Allocation::validateIsFloat32() { 101 RsDataType dt = mType->getElement()->getDataType(); 102 if (dt == RS_TYPE_FLOAT_32) { 103 return; 104 } 105 ALOGE("32 bit float source does not match allocation type %i", dt); 106} 107 108void Allocation::validateIsObject() { 109 RsDataType dt = mType->getElement()->getDataType(); 110 if ((dt == RS_TYPE_ELEMENT) || 111 (dt == RS_TYPE_TYPE) || 112 (dt == RS_TYPE_ALLOCATION) || 113 (dt == RS_TYPE_SAMPLER) || 114 (dt == RS_TYPE_SCRIPT) || 115 (dt == RS_TYPE_MESH) || 116 (dt == RS_TYPE_PROGRAM_FRAGMENT) || 117 (dt == RS_TYPE_PROGRAM_VERTEX) || 118 (dt == RS_TYPE_PROGRAM_RASTER) || 119 (dt == RS_TYPE_PROGRAM_STORE)) { 120 return; 121 } 122 ALOGE("Object source does not match allocation type %i", dt); 123} 124 125void Allocation::updateFromNative() { 126 BaseObj::updateFromNative(); 127 128 const void *typeID = rsaAllocationGetType(mRS->mContext, getID()); 129 if(typeID != NULL) { 130 const Type *old = mType; 131 Type *t = new Type((void *)typeID, mRS); 132 t->updateFromNative(); 133 updateCacheInfo(t); 134 mType = t; 135 delete old; 136 } 137} 138 139void Allocation::syncAll(RsAllocationUsageType srcLocation) { 140 switch (srcLocation) { 141 case RS_ALLOCATION_USAGE_SCRIPT: 142 case RS_ALLOCATION_USAGE_GRAPHICS_CONSTANTS: 143 case RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE: 144 case RS_ALLOCATION_USAGE_GRAPHICS_VERTEX: 145 break; 146 default: 147 ALOGE("Source must be exactly one usage type."); 148 } 149 rsAllocationSyncAll(mRS->mContext, getIDSafe(), srcLocation); 150} 151 152void Allocation::ioSendOutput() { 153 if ((mUsage & RS_ALLOCATION_USAGE_IO_OUTPUT) == 0) { 154 ALOGE("Can only send buffer if IO_OUTPUT usage specified."); 155 } 156 rsAllocationIoSend(mRS->mContext, getID()); 157} 158 159void Allocation::ioGetInput() { 160 if ((mUsage & RS_ALLOCATION_USAGE_IO_INPUT) == 0) { 161 ALOGE("Can only send buffer if IO_OUTPUT usage specified."); 162 } 163 rsAllocationIoReceive(mRS->mContext, getID()); 164} 165 166/* 167void copyFrom(BaseObj[] d) { 168 mRS.validate(); 169 validateIsObject(); 170 if (d.length != mCurrentCount) { 171 ALOGE("Array size mismatch, allocation sizeX = " + 172 mCurrentCount + ", array length = " + d.length); 173 } 174 int i[] = new int[d.length]; 175 for (int ct=0; ct < d.length; ct++) { 176 i[ct] = d[ct].getID(); 177 } 178 copy1DRangeFromUnchecked(0, mCurrentCount, i); 179} 180*/ 181 182 183/* 184void Allocation::setFromFieldPacker(int xoff, FieldPacker fp) { 185 mRS.validate(); 186 int eSize = mType.mElement.getSizeBytes(); 187 final byte[] data = fp.getData(); 188 189 int count = data.length / eSize; 190 if ((eSize * count) != data.length) { 191 ALOGE("Field packer length " + data.length + 192 " not divisible by element size " + eSize + "."); 193 } 194 copy1DRangeFromUnchecked(xoff, count, data); 195} 196 197void setFromFieldPacker(int xoff, int component_number, FieldPacker fp) { 198 mRS.validate(); 199 if (component_number >= mType.mElement.mElements.length) { 200 ALOGE("Component_number " + component_number + " out of range."); 201 } 202 if(xoff < 0) { 203 ALOGE("Offset must be >= 0."); 204 } 205 206 final byte[] data = fp.getData(); 207 int eSize = mType.mElement.mElements[component_number].getSizeBytes(); 208 eSize *= mType.mElement.mArraySizes[component_number]; 209 210 if (data.length != eSize) { 211 ALOGE("Field packer sizelength " + data.length + 212 " does not match component size " + eSize + "."); 213 } 214 215 mRS.nAllocationElementData1D(getIDSafe(), xoff, mSelectedLOD, 216 component_number, data, data.length); 217} 218*/ 219 220void Allocation::generateMipmaps() { 221 rsAllocationGenerateMipmaps(mRS->mContext, getID()); 222} 223 224void Allocation::copy1DRangeFromUnchecked(uint32_t off, size_t count, const void *data, size_t dataLen) { 225 if(count < 1) { 226 ALOGE("Count must be >= 1."); 227 return; 228 } 229 if((off + count) > mCurrentCount) { 230 ALOGE("Overflow, Available count %zu, got %zu at offset %zu.", mCurrentCount, count, off); 231 return; 232 } 233 if((count * mType->getElement()->getSizeBytes()) > dataLen) { 234 ALOGE("Array too small for allocation type."); 235 return; 236 } 237 238 rsAllocation1DData(mRS->mContext, getIDSafe(), off, mSelectedLOD, count, data, dataLen); 239} 240 241void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int32_t *d, size_t dataLen) { 242 validateIsInt32(); 243 copy1DRangeFromUnchecked(off, count, d, dataLen); 244} 245 246void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int16_t *d, size_t dataLen) { 247 validateIsInt16(); 248 copy1DRangeFromUnchecked(off, count, d, dataLen); 249} 250 251void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const int8_t *d, size_t dataLen) { 252 validateIsInt8(); 253 copy1DRangeFromUnchecked(off, count, d, dataLen); 254} 255 256void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const float *d, size_t dataLen) { 257 validateIsFloat32(); 258 copy1DRangeFromUnchecked(off, count, d, dataLen); 259} 260 261void Allocation::copy1DRangeFrom(uint32_t off, size_t count, const Allocation *data, uint32_t dataOff) { 262 rsAllocationCopy2DRange(mRS->mContext, getIDSafe(), off, 0, 263 mSelectedLOD, mSelectedFace, 264 count, 1, data->getIDSafe(), dataOff, 0, 265 data->mSelectedLOD, data->mSelectedFace); 266} 267 268void Allocation::validate2DRange(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h) { 269 if (mAdaptedAllocation != NULL) { 270 271 } else { 272 if (((xoff + w) > mCurrentDimX) || ((yoff + h) > mCurrentDimY)) { 273 ALOGE("Updated region larger than allocation."); 274 } 275 } 276} 277 278void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 279 const int8_t *data, size_t dataLen) { 280 validate2DRange(xoff, yoff, w, h); 281 rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, 282 w, h, data, dataLen); 283} 284 285void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 286 const int16_t *data, size_t dataLen) { 287 validate2DRange(xoff, yoff, w, h); 288 rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, 289 w, h, data, dataLen); 290} 291 292void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 293 const int32_t *data, size_t dataLen) { 294 validate2DRange(xoff, yoff, w, h); 295 rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, 296 w, h, data, dataLen); 297} 298 299void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 300 const float *data, size_t dataLen) { 301 validate2DRange(xoff, yoff, w, h); 302 rsAllocation2DData(mRS->mContext, getIDSafe(), xoff, yoff, mSelectedLOD, mSelectedFace, 303 w, h, data, dataLen); 304} 305 306void Allocation::copy2DRangeFrom(uint32_t xoff, uint32_t yoff, uint32_t w, uint32_t h, 307 const Allocation *data, size_t dataLen, 308 uint32_t dataXoff, uint32_t dataYoff) { 309 validate2DRange(xoff, yoff, w, h); 310 rsAllocationCopy2DRange(mRS->mContext, getIDSafe(), xoff, yoff, 311 mSelectedLOD, mSelectedFace, 312 w, h, data->getIDSafe(), dataXoff, dataYoff, 313 data->mSelectedLOD, data->mSelectedFace); 314} 315 316/* 317void copyTo(byte[] d) { 318 validateIsInt8(); 319 mRS.validate(); 320 mRS.nAllocationRead(getID(), d); 321} 322 323void copyTo(short[] d) { 324 validateIsInt16(); 325 mRS.validate(); 326 mRS.nAllocationRead(getID(), d); 327} 328 329void copyTo(int[] d) { 330 validateIsInt32(); 331 mRS.validate(); 332 mRS.nAllocationRead(getID(), d); 333} 334 335void copyTo(float[] d) { 336 validateIsFloat32(); 337 mRS.validate(); 338 mRS.nAllocationRead(getID(), d); 339} 340 341void resize(int dimX) { 342 if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) { 343 throw new RSInvalidStateException("Resize only support for 1D allocations at this time."); 344 } 345 mRS.nAllocationResize1D(getID(), dimX); 346 mRS.finish(); // Necessary because resize is fifoed and update is async. 347 348 int typeID = mRS.nAllocationGetType(getID()); 349 mType = new Type(typeID, mRS); 350 mType.updateFromNative(); 351 updateCacheInfo(mType); 352} 353 354void resize(int dimX, int dimY) { 355 if ((mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) { 356 throw new RSInvalidStateException( 357 "Resize only support for 2D allocations at this time."); 358 } 359 if (mType.getY() == 0) { 360 throw new RSInvalidStateException( 361 "Resize only support for 2D allocations at this time."); 362 } 363 mRS.nAllocationResize2D(getID(), dimX, dimY); 364 mRS.finish(); // Necessary because resize is fifoed and update is async. 365 366 int typeID = mRS.nAllocationGetType(getID()); 367 mType = new Type(typeID, mRS); 368 mType.updateFromNative(); 369 updateCacheInfo(mType); 370} 371*/ 372 373 374Allocation *Allocation::createTyped(RenderScript *rs, const Type *type, 375 RsAllocationMipmapControl mips, uint32_t usage) { 376 void *id = rsAllocationCreateTyped(rs->mContext, type->getID(), mips, usage, 0); 377 if (id == 0) { 378 ALOGE("Allocation creation failed."); 379 return NULL; 380 } 381 return new Allocation(id, rs, type, usage); 382} 383 384Allocation *Allocation::createTyped(RenderScript *rs, const Type *type, 385 RsAllocationMipmapControl mips, uint32_t usage, void *pointer) { 386 void *id = rsAllocationCreateTyped(rs->mContext, type->getID(), mips, usage, (uint32_t)pointer); 387 if (id == 0) { 388 ALOGE("Allocation creation failed."); 389 } 390 return new Allocation(id, rs, type, usage); 391} 392 393Allocation *Allocation::createTyped(RenderScript *rs, const Type *type, uint32_t usage) { 394 return createTyped(rs, type, RS_ALLOCATION_MIPMAP_NONE, usage); 395} 396 397Allocation *Allocation::createSized(RenderScript *rs, const Element *e, size_t count, uint32_t usage) { 398 Type::Builder b(rs, e); 399 b.setX(count); 400 const Type *t = b.create(); 401 402 void *id = rsAllocationCreateTyped(rs->mContext, t->getID(), RS_ALLOCATION_MIPMAP_NONE, usage, 0); 403 if (id == 0) { 404 ALOGE("Allocation creation failed."); 405 } 406 return new Allocation(id, rs, t, usage); 407} 408 409 410/* 411SurfaceTexture getSurfaceTexture() { 412 if ((mUsage & USAGE_GRAPHICS_SURFACE_TEXTURE_INPUT_OPAQUE) == 0) { 413 throw new RSInvalidStateException("Allocation is not a surface texture."); 414 } 415 416 int id = mRS.nAllocationGetSurfaceTextureID(getID()); 417 return new SurfaceTexture(id); 418 419} 420 421void setSurfaceTexture(SurfaceTexture sur) { 422 if ((mUsage & USAGE_IO_OUTPUT) == 0) { 423 throw new RSInvalidStateException("Allocation is not USAGE_IO_OUTPUT."); 424 } 425 426 mRS.validate(); 427 mRS.nAllocationSetSurfaceTexture(getID(), sur); 428} 429 430 431static Allocation createFromBitmapResource(RenderScript rs, 432 Resources res, 433 int id, 434 MipmapControl mips, 435 int usage) { 436 437 rs.validate(); 438 Bitmap b = BitmapFactory.decodeResource(res, id); 439 Allocation alloc = createFromBitmap(rs, b, mips, usage); 440 b.recycle(); 441 return alloc; 442} 443 444static Allocation createFromBitmapResource(RenderScript rs, 445 Resources res, 446 int id) { 447 return createFromBitmapResource(rs, res, id, 448 MipmapControl.MIPMAP_NONE, 449 USAGE_GRAPHICS_TEXTURE); 450} 451 452static Allocation createFromString(RenderScript rs, 453 String str, 454 int usage) { 455 rs.validate(); 456 byte[] allocArray = NULL; 457 try { 458 allocArray = str.getBytes("UTF-8"); 459 Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage); 460 alloc.copyFrom(allocArray); 461 return alloc; 462 } 463 catch (Exception e) { 464 throw new RSRuntimeException("Could not convert string to utf-8."); 465 } 466} 467*/ 468 469