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