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