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