Allocation.java revision 4ef6650bd05a39a09958ea1db92f120ea4949cb1
1/* 2 * Copyright (C) 2008 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 17package android.renderscript; 18 19import java.io.IOException; 20import java.io.InputStream; 21 22import android.content.res.Resources; 23import android.content.res.AssetManager; 24import android.graphics.Bitmap; 25import android.graphics.BitmapFactory; 26import android.util.Log; 27import android.util.TypedValue; 28 29/** 30 * @hide 31 * 32 **/ 33public class Allocation extends BaseObj { 34 Type mType; 35 Bitmap mBitmap; 36 int mUsage; 37 38 public static final int USAGE_SCRIPT = 0x0001; 39 public static final int USAGE_GRAPHICS_TEXTURE = 0x0002; 40 public static final int USAGE_GRAPHICS_VERTEX = 0x0004; 41 public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008; 42 43 private static final int USAGE_ALL = 0x000F; 44 45 46 public enum CubemapLayout { 47 VERTICAL_FACE_LIST (0), 48 HORIZONTAL_FACE_LIST (1), 49 VERTICAL_CROSS (2), 50 HORIZONTAL_CROSS (3); 51 52 int mID; 53 CubemapLayout(int id) { 54 mID = id; 55 } 56 } 57 58 public enum MipmapControl { 59 MIPMAP_NONE(0), 60 MIPMAP_FULL(1), 61 MIPMAP_ON_SYNC_TO_TEXTURE(2); 62 63 int mID; 64 MipmapControl(int id) { 65 mID = id; 66 } 67 } 68 69 Allocation(int id, RenderScript rs, Type t, int usage) { 70 super(id, rs); 71 if (usage > USAGE_ALL) { 72 throw new RSIllegalArgumentException("Unknown usage specified."); 73 } 74 mType = t; 75 } 76 77 @Override 78 void updateFromNative() { 79 super.updateFromNative(); 80 int typeID = mRS.nAllocationGetType(getID()); 81 if(typeID != 0) { 82 mType = new Type(typeID, mRS); 83 mType.updateFromNative(); 84 } 85 } 86 87 public Type getType() { 88 return mType; 89 } 90 91 public void syncAll(int srcLocation) { 92 switch (srcLocation) { 93 case USAGE_SCRIPT: 94 case USAGE_GRAPHICS_CONSTANTS: 95 case USAGE_GRAPHICS_TEXTURE: 96 case USAGE_GRAPHICS_VERTEX: 97 break; 98 default: 99 throw new RSIllegalArgumentException("Source must be exactly one usage type."); 100 } 101 mRS.validate(); 102 mRS.nAllocationSyncAll(getID(), srcLocation); 103 } 104 105 public void uploadToTexture(int baseMipLevel) { 106 mRS.validate(); 107 mRS.nAllocationUploadToTexture(getID(), false, baseMipLevel); 108 } 109 110 public void uploadToTexture(boolean genMips, int baseMipLevel) { 111 mRS.validate(); 112 mRS.nAllocationUploadToTexture(getID(), genMips, baseMipLevel); 113 } 114 115 public void uploadToBufferObject() { 116 mRS.validate(); 117 mRS.nAllocationUploadToBufferObject(getID()); 118 } 119 120 121 public void copyFrom(BaseObj[] d) { 122 mRS.validate(); 123 if (d.length != mType.getCount()) { 124 throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " + 125 mType.getCount() + ", array length = " + d.length); 126 } 127 int i[] = new int[d.length]; 128 for (int ct=0; ct < d.length; ct++) { 129 i[ct] = d[ct].getID(); 130 } 131 subData1D(0, mType.getCount(), i); 132 } 133 134 private void validateBitmap(Bitmap b) { 135 mRS.validate(); 136 if(mType.getX() != b.getWidth() || 137 mType.getY() != b.getHeight()) { 138 throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch"); 139 } 140 } 141 142 public void copyFrom(int[] d) { 143 mRS.validate(); 144 subData1D(0, mType.getCount(), d); 145 } 146 public void copyFrom(short[] d) { 147 mRS.validate(); 148 subData1D(0, mType.getCount(), d); 149 } 150 public void copyFrom(byte[] d) { 151 mRS.validate(); 152 subData1D(0, mType.getCount(), d); 153 } 154 public void copyFrom(float[] d) { 155 mRS.validate(); 156 subData1D(0, mType.getCount(), d); 157 } 158 public void copyFrom(Bitmap b) { 159 validateBitmap(b); 160 mRS.nAllocationCopyFromBitmap(getID(), b); 161 } 162 163 public void copyTo(Bitmap b) { 164 validateBitmap(b); 165 mRS.nAllocationCopyToBitmap(getID(), b); 166 } 167 168 169 public void subData(int xoff, FieldPacker fp) { 170 int eSize = mType.mElement.getSizeBytes(); 171 final byte[] data = fp.getData(); 172 173 int count = data.length / eSize; 174 if ((eSize * count) != data.length) { 175 throw new RSIllegalArgumentException("Field packer length " + data.length + 176 " not divisible by element size " + eSize + "."); 177 } 178 data1DChecks(xoff, count, data.length, data.length); 179 mRS.nAllocationSubData1D(getID(), xoff, count, data, data.length); 180 } 181 182 183 public void subElementData(int xoff, int component_number, FieldPacker fp) { 184 if (component_number >= mType.mElement.mElements.length) { 185 throw new RSIllegalArgumentException("Component_number " + component_number + " out of range."); 186 } 187 if(xoff < 0) { 188 throw new RSIllegalArgumentException("Offset must be >= 0."); 189 } 190 191 final byte[] data = fp.getData(); 192 int eSize = mType.mElement.mElements[component_number].getSizeBytes(); 193 194 if (data.length != eSize) { 195 throw new RSIllegalArgumentException("Field packer sizelength " + data.length + 196 " does not match component size " + eSize + "."); 197 } 198 199 mRS.nAllocationSubElementData1D(getID(), xoff, component_number, data, data.length); 200 } 201 202 private void data1DChecks(int off, int count, int len, int dataSize) { 203 mRS.validate(); 204 if(off < 0) { 205 throw new RSIllegalArgumentException("Offset must be >= 0."); 206 } 207 if(count < 1) { 208 throw new RSIllegalArgumentException("Count must be >= 1."); 209 } 210 if((off + count) > mType.getCount()) { 211 throw new RSIllegalArgumentException("Overflow, Available count " + mType.getCount() + 212 ", got " + count + " at offset " + off + "."); 213 } 214 if((len) < dataSize) { 215 throw new RSIllegalArgumentException("Array too small for allocation type."); 216 } 217 } 218 219 public void subData1D(int off, int count, int[] d) { 220 int dataSize = mType.mElement.getSizeBytes() * count; 221 data1DChecks(off, count, d.length * 4, dataSize); 222 mRS.nAllocationSubData1D(getID(), off, count, d, dataSize); 223 } 224 public void subData1D(int off, int count, short[] d) { 225 int dataSize = mType.mElement.getSizeBytes() * count; 226 data1DChecks(off, count, d.length * 2, dataSize); 227 mRS.nAllocationSubData1D(getID(), off, count, d, dataSize); 228 } 229 public void subData1D(int off, int count, byte[] d) { 230 int dataSize = mType.mElement.getSizeBytes() * count; 231 data1DChecks(off, count, d.length, dataSize); 232 mRS.nAllocationSubData1D(getID(), off, count, d, dataSize); 233 } 234 public void subData1D(int off, int count, float[] d) { 235 int dataSize = mType.mElement.getSizeBytes() * count; 236 data1DChecks(off, count, d.length * 4, dataSize); 237 mRS.nAllocationSubData1D(getID(), off, count, d, dataSize); 238 } 239 240 241 public void subData2D(int xoff, int yoff, int w, int h, int[] d) { 242 mRS.validate(); 243 mRS.nAllocationSubData2D(getID(), xoff, yoff, w, h, d, d.length * 4); 244 } 245 246 public void subData2D(int xoff, int yoff, int w, int h, float[] d) { 247 mRS.validate(); 248 mRS.nAllocationSubData2D(getID(), xoff, yoff, w, h, d, d.length * 4); 249 } 250 251 public void readData(int[] d) { 252 mRS.validate(); 253 mRS.nAllocationRead(getID(), d); 254 } 255 256 public void readData(float[] d) { 257 mRS.validate(); 258 mRS.nAllocationRead(getID(), d); 259 } 260 261 public synchronized void resize(int dimX) { 262 if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) { 263 throw new RSInvalidStateException("Resize only support for 1D allocations at this time."); 264 } 265 mRS.nAllocationResize1D(getID(), dimX); 266 mRS.finish(); // Necessary because resize is fifoed and update is async. 267 268 int typeID = mRS.nAllocationGetType(getID()); 269 mType = new Type(typeID, mRS); 270 mType.updateFromNative(); 271 } 272 273 /* 274 public void resize(int dimX, int dimY) { 275 if ((mType.getZ() > 0) || mType.getFaces() || mType.getLOD()) { 276 throw new RSIllegalStateException("Resize only support for 2D allocations at this time."); 277 } 278 if (mType.getY() == 0) { 279 throw new RSIllegalStateException("Resize only support for 2D allocations at this time."); 280 } 281 mRS.nAllocationResize2D(getID(), dimX, dimY); 282 } 283 */ 284 285 /* 286 public class Adapter1D extends BaseObj { 287 Adapter1D(int id, RenderScript rs) { 288 super(id, rs); 289 } 290 291 public void setConstraint(Dimension dim, int value) { 292 mRS.validate(); 293 mRS.nAdapter1DSetConstraint(getID(), dim.mID, value); 294 } 295 296 public void data(int[] d) { 297 mRS.validate(); 298 mRS.nAdapter1DData(getID(), d); 299 } 300 301 public void data(float[] d) { 302 mRS.validate(); 303 mRS.nAdapter1DData(getID(), d); 304 } 305 306 public void subData(int off, int count, int[] d) { 307 mRS.validate(); 308 mRS.nAdapter1DSubData(getID(), off, count, d); 309 } 310 311 public void subData(int off, int count, float[] d) { 312 mRS.validate(); 313 mRS.nAdapter1DSubData(getID(), off, count, d); 314 } 315 } 316 317 public Adapter1D createAdapter1D() { 318 mRS.validate(); 319 int id = mRS.nAdapter1DCreate(); 320 if(id == 0) { 321 throw new RSRuntimeException("Adapter creation failed."); 322 } 323 mRS.nAdapter1DBindAllocation(id, getID()); 324 return new Adapter1D(id, mRS); 325 } 326 */ 327 328 329 public class Adapter2D extends BaseObj { 330 Adapter2D(int id, RenderScript rs) { 331 super(id, rs); 332 } 333 334 public void setConstraint(Dimension dim, int value) { 335 mRS.validate(); 336 mRS.nAdapter2DSetConstraint(getID(), dim.mID, value); 337 } 338 339 public void data(int[] d) { 340 mRS.validate(); 341 mRS.nAdapter2DData(getID(), d); 342 } 343 344 public void data(float[] d) { 345 mRS.validate(); 346 mRS.nAdapter2DData(getID(), d); 347 } 348 349 public void subData(int xoff, int yoff, int w, int h, int[] d) { 350 mRS.validate(); 351 mRS.nAdapter2DSubData(getID(), xoff, yoff, w, h, d); 352 } 353 354 public void subData(int xoff, int yoff, int w, int h, float[] d) { 355 mRS.validate(); 356 mRS.nAdapter2DSubData(getID(), xoff, yoff, w, h, d); 357 } 358 } 359 360 public Adapter2D createAdapter2D() { 361 mRS.validate(); 362 int id = mRS.nAdapter2DCreate(); 363 if(id == 0) { 364 throw new RSRuntimeException("allocation failed."); 365 } 366 mRS.nAdapter2DBindAllocation(id, getID()); 367 if(id == 0) { 368 throw new RSRuntimeException("Adapter creation failed."); 369 } 370 return new Adapter2D(id, mRS); 371 } 372 373 374 // creation 375 376 private static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options(); 377 static { 378 mBitmapOptions.inScaled = false; 379 } 380 381 static public Allocation createTyped(RenderScript rs, Type type, int usage) { 382 rs.validate(); 383 if (type.getID() == 0) { 384 throw new RSInvalidStateException("Bad Type"); 385 } 386 int id = rs.nAllocationCreateTyped(type.getID(), usage); 387 if (id == 0) { 388 throw new RSRuntimeException("Allocation creation failed."); 389 } 390 return new Allocation(id, rs, type, usage); 391 } 392 393 static public Allocation createTyped(RenderScript rs, Type type) { 394 return createTyped(rs, type, USAGE_ALL); 395 } 396 397 static public Allocation createSized(RenderScript rs, Element e, 398 int count, int usage) { 399 rs.validate(); 400 Type.Builder b = new Type.Builder(rs, e); 401 b.setX(count); 402 Type t = b.create(); 403 404 int id = rs.nAllocationCreateTyped(t.getID(), usage); 405 if (id == 0) { 406 throw new RSRuntimeException("Allocation creation failed."); 407 } 408 return new Allocation(id, rs, t, usage); 409 } 410 411 static public Allocation createSized(RenderScript rs, Element e, int count) { 412 return createSized(rs, e, count, USAGE_ALL); 413 } 414 415 static private Element elementFromBitmap(RenderScript rs, Bitmap b) { 416 final Bitmap.Config bc = b.getConfig(); 417 if (bc == Bitmap.Config.ALPHA_8) { 418 return Element.A_8(rs); 419 } 420 if (bc == Bitmap.Config.ARGB_4444) { 421 return Element.RGBA_4444(rs); 422 } 423 if (bc == Bitmap.Config.ARGB_8888) { 424 return Element.RGBA_8888(rs); 425 } 426 if (bc == Bitmap.Config.RGB_565) { 427 return Element.RGB_565(rs); 428 } 429 throw new RSInvalidStateException("Bad bitmap type: " + bc); 430 } 431 432 static private Type typeFromBitmap(RenderScript rs, Bitmap b, 433 MipmapControl mip) { 434 Element e = elementFromBitmap(rs, b); 435 Type.Builder tb = new Type.Builder(rs, e); 436 tb.setX(b.getWidth()); 437 tb.setY(b.getHeight()); 438 tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL); 439 return tb.create(); 440 } 441 442 static public Allocation createFromBitmap(RenderScript rs, Bitmap b, 443 MipmapControl mips, 444 int usage) { 445 rs.validate(); 446 Type t = typeFromBitmap(rs, b, mips); 447 448 int id = rs.nAllocationCreateFromBitmap(t.getID(), mips.mID, b, usage); 449 if (id == 0) { 450 throw new RSRuntimeException("Load failed."); 451 } 452 return new Allocation(id, rs, t, usage); 453 } 454 455 static public Allocation createFromBitmap(RenderScript rs, Bitmap b, 456 Element dstFmt, boolean genMips) { 457 MipmapControl mc = MipmapControl.MIPMAP_NONE; 458 if (genMips) { 459 mc = MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE; 460 } 461 return createFromBitmap(rs, b, mc, USAGE_ALL); 462 } 463 464 static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b, 465 MipmapControl mips, 466 CubemapLayout layout, 467 int usage) { 468 rs.validate(); 469 470 int height = b.getHeight(); 471 int width = b.getWidth(); 472 473 if (layout != CubemapLayout.VERTICAL_FACE_LIST) { 474 throw new RSIllegalArgumentException("Only vertical face list supported"); 475 } 476 if (height % 6 != 0) { 477 throw new RSIllegalArgumentException("Cubemap height must be multiple of 6"); 478 } 479 if (height / 6 != width) { 480 throw new RSIllegalArgumentException("Only square cobe map faces supported"); 481 } 482 boolean isPow2 = (width & (width - 1)) == 0; 483 if (!isPow2) { 484 throw new RSIllegalArgumentException("Only power of 2 cube faces supported"); 485 } 486 487 Element e = elementFromBitmap(rs, b); 488 Type.Builder tb = new Type.Builder(rs, e); 489 tb.setX(width); 490 tb.setY(width); 491 tb.setFaces(true); 492 tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL); 493 Type t = tb.create(); 494 495 int id = rs.nAllocationCubeCreateFromBitmap(t.getID(), mips.mID, b, usage); 496 if(id == 0) { 497 throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e); 498 } 499 return new Allocation(id, rs, t, usage); 500 } 501 502 static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b, 503 Element dstFmt, 504 boolean genMips, 505 CubemapLayout layout) { 506 MipmapControl mc = MipmapControl.MIPMAP_NONE; 507 if (genMips) { 508 mc = MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE; 509 } 510 return createCubemapFromBitmap(rs, b, mc, layout, USAGE_ALL); 511 } 512 513 static public Allocation createFromBitmapResource(RenderScript rs, 514 Resources res, 515 int id, 516 MipmapControl mips, 517 int usage) { 518 519 rs.validate(); 520 Bitmap b = BitmapFactory.decodeResource(res, id); 521 Allocation alloc = createFromBitmap(rs, b, mips, usage); 522 b.recycle(); 523 return alloc; 524 } 525 526 static public Allocation createFromBitmapResource(RenderScript rs, 527 Resources res, 528 int id, 529 Element dstFmt, 530 boolean genMips) { 531 MipmapControl mc = MipmapControl.MIPMAP_NONE; 532 if (genMips) { 533 mc = MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE; 534 } 535 return createFromBitmapResource(rs, res, id, mc, USAGE_ALL); 536 } 537 538 static public Allocation createFromString(RenderScript rs, 539 String str, 540 int usage) { 541 rs.validate(); 542 byte[] allocArray = null; 543 try { 544 allocArray = str.getBytes("UTF-8"); 545 Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage); 546 alloc.copyFrom(allocArray); 547 return alloc; 548 } 549 catch (Exception e) { 550 throw new RSRuntimeException("Could not convert string to utf-8."); 551 } 552 } 553} 554 555 556