diff options
Diffstat (limited to 'graphics/java/android/renderscript/Allocation.java')
-rw-r--r-- | graphics/java/android/renderscript/Allocation.java | 924 |
1 files changed, 709 insertions, 215 deletions
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java index b27c7f502e96..b15121a23c11 100644 --- a/graphics/java/android/renderscript/Allocation.java +++ b/graphics/java/android/renderscript/Allocation.java @@ -18,7 +18,6 @@ package android.renderscript; import java.io.IOException; import java.io.InputStream; - import android.content.res.Resources; import android.content.res.AssetManager; import android.graphics.Bitmap; @@ -27,243 +26,549 @@ import android.util.Log; import android.util.TypedValue; /** - * @hide + * Memory allocation class for renderscript. An allocation combines a Type with + * memory to provide storage for user data and objects. + * + * Allocations may exist in one or more memory spaces. Currently those are + * Script: accessable by RS scripts. + * Graphics Texture: accessable as a graphics texture. + * Graphics Vertex: accessable as graphical vertex data. + * Graphics Constants: Accessable as constants in user shaders + * + * By default java side updates are always applied to the script accessable + * memory. If this is not present they are then applied to the various HW + * memory types. A syncAll call is necessary after the script data is update to + * keep the other memory spaces in sync. * **/ public class Allocation extends BaseObj { Type mType; Bitmap mBitmap; + int mUsage; + + /** + * The usage of the allocation. These signal to renderscript + * where to place the allocation in memory. + * + * SCRIPT The allocation will be bound to and accessed by + * scripts. + */ + public static final int USAGE_SCRIPT = 0x0001; + + /** + * GRAPHICS_TEXTURE The allcation will be used as a texture + * source by one or more graphcics programs. + * + */ + public static final int USAGE_GRAPHICS_TEXTURE = 0x0002; + + /** + * GRAPHICS_VERTEX The allocation will be used as a graphics + * mesh. + * + */ + public static final int USAGE_GRAPHICS_VERTEX = 0x0004; + + + /** + * GRAPHICS_CONSTANTS The allocation will be used as the source + * of shader constants by one or more programs. + * + */ + public static final int USAGE_GRAPHICS_CONSTANTS = 0x0008; + + + /** + * Controls mipmap behavior when using the bitmap creation and + * update functions. + */ + public enum MipmapControl { + /** + * No mipmaps will be generated and the type generated from the + * incoming bitmap will not contain additional LODs. + */ + MIPMAP_NONE(0), + + /** + * A Full mipmap chain will be created in script memory. The + * type of the allocation will contain a full mipmap chain. On + * upload to graphics the full chain will be transfered. + */ + MIPMAP_FULL(1), + + /** + * The type of the allocation will be the same as MIPMAP_NONE. + * It will not contain mipmaps. On upload to graphics the + * graphics copy of the allocation data will contain a full + * mipmap chain generated from the top level in script memory. + */ + MIPMAP_ON_SYNC_TO_TEXTURE(2); + + int mID; + MipmapControl(int id) { + mID = id; + } + } - Allocation(int id, RenderScript rs, Type t) { - super(rs); - mID = id; + Allocation(int id, RenderScript rs, Type t, int usage) { + super(id, rs); + if ((usage & ~(USAGE_SCRIPT | + USAGE_GRAPHICS_TEXTURE | + USAGE_GRAPHICS_VERTEX | + USAGE_GRAPHICS_CONSTANTS)) != 0) { + throw new RSIllegalArgumentException("Unknown usage specified."); + } mType = t; } + @Override + void updateFromNative() { + super.updateFromNative(); + int typeID = mRS.nAllocationGetType(getID()); + if(typeID != 0) { + mType = new Type(typeID, mRS); + mType.updateFromNative(); + } + } + public Type getType() { return mType; } - public void uploadToTexture(int baseMipLevel) { + public void syncAll(int srcLocation) { + switch (srcLocation) { + case USAGE_SCRIPT: + case USAGE_GRAPHICS_CONSTANTS: + case USAGE_GRAPHICS_TEXTURE: + case USAGE_GRAPHICS_VERTEX: + break; + default: + throw new RSIllegalArgumentException("Source must be exactly one usage type."); + } mRS.validate(); - mRS.nAllocationUploadToTexture(mID, false, baseMipLevel); + mRS.nAllocationSyncAll(getID(), srcLocation); } - public void uploadToTexture(boolean genMips, int baseMipLevel) { + public void copyFrom(BaseObj[] d) { mRS.validate(); - mRS.nAllocationUploadToTexture(mID, genMips, baseMipLevel); + if (d.length != mType.getCount()) { + throw new RSIllegalArgumentException("Array size mismatch, allocation sizeX = " + + mType.getCount() + ", array length = " + d.length); + } + int i[] = new int[d.length]; + for (int ct=0; ct < d.length; ct++) { + i[ct] = d[ct].getID(); + } + copy1DRangeFrom(0, mType.getCount(), i); + } + + private void validateBitmapFormat(Bitmap b) { + Bitmap.Config bc = b.getConfig(); + switch (bc) { + case ALPHA_8: + if (mType.getElement().mKind != Element.DataKind.PIXEL_A) { + throw new RSIllegalArgumentException("Allocation kind is " + + mType.getElement().mKind + ", type " + + mType.getElement().mType + + " of " + mType.getElement().getSizeBytes() + + " bytes, passed bitmap was " + bc); + } + break; + case ARGB_8888: + if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) || + (mType.getElement().getSizeBytes() != 4)) { + throw new RSIllegalArgumentException("Allocation kind is " + + mType.getElement().mKind + ", type " + + mType.getElement().mType + + " of " + mType.getElement().getSizeBytes() + + " bytes, passed bitmap was " + bc); + } + break; + case RGB_565: + if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGB) || + (mType.getElement().getSizeBytes() != 2)) { + throw new RSIllegalArgumentException("Allocation kind is " + + mType.getElement().mKind + ", type " + + mType.getElement().mType + + " of " + mType.getElement().getSizeBytes() + + " bytes, passed bitmap was " + bc); + } + break; + case ARGB_4444: + if ((mType.getElement().mKind != Element.DataKind.PIXEL_RGBA) || + (mType.getElement().getSizeBytes() != 2)) { + throw new RSIllegalArgumentException("Allocation kind is " + + mType.getElement().mKind + ", type " + + mType.getElement().mType + + " of " + mType.getElement().getSizeBytes() + + " bytes, passed bitmap was " + bc); + } + break; + + } } - public void uploadToBufferObject() { - mRS.validate(); - mRS.nAllocationUploadToBufferObject(mID); + private void validateBitmapSize(Bitmap b) { + if(mType.getX() != b.getWidth() || + mType.getY() != b.getHeight()) { + throw new RSIllegalArgumentException("Cannot update allocation from bitmap, sizes mismatch"); + } } - public void data(int[] d) { + public void copyFrom(int[] d) { mRS.validate(); - subData1D(0, mType.getElementCount(), d); + copy1DRangeFrom(0, mType.getCount(), d); } - public void data(short[] d) { + public void copyFrom(short[] d) { mRS.validate(); - subData1D(0, mType.getElementCount(), d); + copy1DRangeFrom(0, mType.getCount(), d); } - public void data(byte[] d) { + public void copyFrom(byte[] d) { mRS.validate(); - subData1D(0, mType.getElementCount(), d); + copy1DRangeFrom(0, mType.getCount(), d); } - public void data(float[] d) { + public void copyFrom(float[] d) { mRS.validate(); - subData1D(0, mType.getElementCount(), d); + copy1DRangeFrom(0, mType.getCount(), d); + } + public void copyFrom(Bitmap b) { + mRS.validate(); + validateBitmapSize(b); + validateBitmapFormat(b); + mRS.nAllocationCopyFromBitmap(getID(), b); + } + + /** + * @hide + * + * This is only intended to be used by auto-generate code reflected from the + * renderscript script files. + * + * @param xoff + * @param fp + */ + public void setOneElement(int xoff, FieldPacker fp) { + int eSize = mType.mElement.getSizeBytes(); + final byte[] data = fp.getData(); + + int count = data.length / eSize; + if ((eSize * count) != data.length) { + throw new RSIllegalArgumentException("Field packer length " + data.length + + " not divisible by element size " + eSize + "."); + } + data1DChecks(xoff, count, data.length, data.length); + mRS.nAllocationData1D(getID(), xoff, 0, count, data, data.length); + } + + + /** + * @hide + * + * This is only intended to be used by auto-generate code reflected from the + * renderscript script files. + * + * @param xoff + * @param component_number + * @param fp + */ + public void setOneComponent(int xoff, int component_number, FieldPacker fp) { + if (component_number >= mType.mElement.mElements.length) { + throw new RSIllegalArgumentException("Component_number " + component_number + " out of range."); + } + if(xoff < 0) { + throw new RSIllegalArgumentException("Offset must be >= 0."); + } + + final byte[] data = fp.getData(); + int eSize = mType.mElement.mElements[component_number].getSizeBytes(); + + if (data.length != eSize) { + throw new RSIllegalArgumentException("Field packer sizelength " + data.length + + " does not match component size " + eSize + "."); + } + + mRS.nAllocationElementData1D(getID(), xoff, 0, component_number, data, data.length); } private void data1DChecks(int off, int count, int len, int dataSize) { mRS.validate(); - if((off < 0) || (count < 1) || ((off + count) > mType.getElementCount())) { - throw new IllegalArgumentException("Offset or Count out of bounds."); + if(off < 0) { + throw new RSIllegalArgumentException("Offset must be >= 0."); + } + if(count < 1) { + throw new RSIllegalArgumentException("Count must be >= 1."); + } + if((off + count) > mType.getCount()) { + throw new RSIllegalArgumentException("Overflow, Available count " + mType.getCount() + + ", got " + count + " at offset " + off + "."); } if((len) < dataSize) { - throw new IllegalArgumentException("Array too small for allocation type."); + throw new RSIllegalArgumentException("Array too small for allocation type."); } } - public void subData1D(int off, int count, int[] d) { + /** + * Generate a mipmap chain. Requires the type of the allocation + * include mipmaps. + * + * This function will generate a complete set of mipmaps from + * the top level lod and place them into the script memoryspace. + * + * If the allocation is also using other memory spaces a + * followup sync will be required. + */ + public void generateMipmaps() { + mRS.nAllocationGenerateMipmaps(getID()); + } + + public void copy1DRangeFrom(int off, int count, int[] d) { int dataSize = mType.mElement.getSizeBytes() * count; data1DChecks(off, count, d.length * 4, dataSize); - mRS.nAllocationSubData1D(mID, off, count, d, dataSize); + mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); } - public void subData1D(int off, int count, short[] d) { + public void copy1DRangeFrom(int off, int count, short[] d) { int dataSize = mType.mElement.getSizeBytes() * count; data1DChecks(off, count, d.length * 2, dataSize); - mRS.nAllocationSubData1D(mID, off, count, d, dataSize); + mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); } - public void subData1D(int off, int count, byte[] d) { + public void copy1DRangeFrom(int off, int count, byte[] d) { int dataSize = mType.mElement.getSizeBytes() * count; data1DChecks(off, count, d.length, dataSize); - mRS.nAllocationSubData1D(mID, off, count, d, dataSize); + mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); } - public void subData1D(int off, int count, float[] d) { + public void copy1DRangeFrom(int off, int count, float[] d) { int dataSize = mType.mElement.getSizeBytes() * count; data1DChecks(off, count, d.length * 4, dataSize); - mRS.nAllocationSubData1D(mID, off, count, d, dataSize); + mRS.nAllocationData1D(getID(), off, 0, count, d, dataSize); } - - - public void subData2D(int xoff, int yoff, int w, int h, int[] d) { - mRS.validate(); - mRS.nAllocationSubData2D(mID, xoff, yoff, w, h, d, d.length * 4); + private void validate2DRange(int xoff, int yoff, int w, int h) { + if (xoff < 0 || yoff < 0) { + throw new RSIllegalArgumentException("Offset cannot be negative."); + } + if (h < 0 || w < 0) { + throw new RSIllegalArgumentException("Height or width cannot be negative."); + } + if ((xoff + w) > mType.mDimX || + (yoff + h) > mType.mDimY) { + throw new RSIllegalArgumentException("Updated region larger than allocation."); + } } - public void subData2D(int xoff, int yoff, int w, int h, float[] d) { + /** + * Copy a rectanglular region from the array into the + * allocation. The incoming array is assumed to be tightly + * packed. + * + * @param xoff X offset of the region to update + * @param yoff Y offset of the region to update + * @param w Width of the incoming region to update + * @param h Height of the incoming region to update + * @param data to be placed into the allocation + */ + public void copy2DRangeFrom(int xoff, int yoff, int w, int h, byte[] data) { mRS.validate(); - mRS.nAllocationSubData2D(mID, xoff, yoff, w, h, d, d.length * 4); + validate2DRange(xoff, yoff, w, h); + mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length); } - public void readData(int[] d) { + public void copy2DRangeFrom(int xoff, int yoff, int w, int h, short[] data) { mRS.validate(); - mRS.nAllocationRead(mID, d); + validate2DRange(xoff, yoff, w, h); + mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 2); } - public void readData(float[] d) { + public void copy2DRangeFrom(int xoff, int yoff, int w, int h, int[] data) { mRS.validate(); - mRS.nAllocationRead(mID, d); + validate2DRange(xoff, yoff, w, h); + mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4); } - public void data(Object o) { + public void copy2DRangeFrom(int xoff, int yoff, int w, int h, float[] data) { + mRS.validate(); + validate2DRange(xoff, yoff, w, h); + mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, w, h, data, data.length * 4); + } + + /** + * Copy a bitmap into an allocation. The height and width of + * the update will use the height and width of the incoming + * bitmap. + * + * @param xoff X offset of the region to update + * @param yoff Y offset of the region to update + * @param data the bitmap to be copied + */ + public void copy2DRangeFrom(int xoff, int yoff, Bitmap data) { mRS.validate(); - mRS.nAllocationSubDataFromObject(mID, mType, 0, o); + validateBitmapFormat(data); + validate2DRange(xoff, yoff, data.getWidth(), data.getHeight()); + mRS.nAllocationData2D(getID(), xoff, yoff, 0, 0, data); } - public void read(Object o) { + + public void copyTo(Bitmap b) { mRS.validate(); - mRS.nAllocationSubReadFromObject(mID, mType, 0, o); + validateBitmapFormat(b); + validateBitmapSize(b); + mRS.nAllocationCopyToBitmap(getID(), b); } - public void subData(int offset, Object o) { + public void copyTo(byte[] d) { mRS.validate(); - mRS.nAllocationSubDataFromObject(mID, mType, offset, o); + mRS.nAllocationRead(getID(), d); } - public class Adapter1D extends BaseObj { - Adapter1D(int id, RenderScript rs) { - super(rs); - mID = id; - } - - public void setConstraint(Dimension dim, int value) { - mRS.validate(); - mRS.nAdapter1DSetConstraint(mID, dim.mID, value); - } - - public void data(int[] d) { - mRS.validate(); - mRS.nAdapter1DData(mID, d); - } - - public void data(float[] d) { - mRS.validate(); - mRS.nAdapter1DData(mID, d); - } - - public void subData(int off, int count, int[] d) { - mRS.validate(); - mRS.nAdapter1DSubData(mID, off, count, d); - } - - public void subData(int off, int count, float[] d) { - mRS.validate(); - mRS.nAdapter1DSubData(mID, off, count, d); - } + public void copyTo(short[] d) { + mRS.validate(); + mRS.nAllocationRead(getID(), d); } - public Adapter1D createAdapter1D() { + public void copyTo(int[] d) { mRS.validate(); - int id = mRS.nAdapter1DCreate(); - if(id == 0) { - throw new IllegalStateException("allocation failed."); - } - mRS.nAdapter1DBindAllocation(id, mID); - return new Adapter1D(id, mRS); + mRS.nAllocationRead(getID(), d); } - - public class Adapter2D extends BaseObj { - Adapter2D(int id, RenderScript rs) { - super(rs); - mID = id; - } - - public void setConstraint(Dimension dim, int value) { - mRS.validate(); - mRS.nAdapter2DSetConstraint(mID, dim.mID, value); - } - - public void data(int[] d) { - mRS.validate(); - mRS.nAdapter2DData(mID, d); + public void copyTo(float[] d) { + mRS.validate(); + mRS.nAllocationRead(getID(), d); + } + + /** + * Resize a 1D allocation. The contents of the allocation are + * preserved. If new elements are allocated objects are created + * with null contents and the new region is otherwise undefined. + * + * If the new region is smaller the references of any objects + * outside the new region will be released. + * + * A new type will be created with the new dimension. + * + * @param dimX The new size of the allocation. + */ + public synchronized void resize(int dimX) { + if ((mType.getY() > 0)|| (mType.getZ() > 0) || mType.hasFaces() || mType.hasMipmaps()) { + throw new RSInvalidStateException("Resize only support for 1D allocations at this time."); } + mRS.nAllocationResize1D(getID(), dimX); + mRS.finish(); // Necessary because resize is fifoed and update is async. - public void data(float[] d) { - mRS.validate(); - mRS.nAdapter2DData(mID, d); - } + int typeID = mRS.nAllocationGetType(getID()); + mType = new Type(typeID, mRS); + mType.updateFromNative(); + } - public void subData(int xoff, int yoff, int w, int h, int[] d) { - mRS.validate(); - mRS.nAdapter2DSubData(mID, xoff, yoff, w, h, d); + /* + public void resize(int dimX, int dimY) { + if ((mType.getZ() > 0) || mType.getFaces() || mType.getLOD()) { + throw new RSIllegalStateException("Resize only support for 2D allocations at this time."); } - - public void subData(int xoff, int yoff, int w, int h, float[] d) { - mRS.validate(); - mRS.nAdapter2DSubData(mID, xoff, yoff, w, h, d); + if (mType.getY() == 0) { + throw new RSIllegalStateException("Resize only support for 2D allocations at this time."); } + mRS.nAllocationResize2D(getID(), dimX, dimY); } + */ - public Adapter2D createAdapter2D() { - mRS.validate(); - int id = mRS.nAdapter2DCreate(); - if(id == 0) { - throw new IllegalStateException("allocation failed."); - } - mRS.nAdapter2DBindAllocation(id, mID); - return new Adapter2D(id, mRS); - } // creation - private static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options(); + static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options(); static { mBitmapOptions.inScaled = false; } - static public Allocation createTyped(RenderScript rs, Type type) - throws IllegalArgumentException { - + /** + * + * @param type renderscript type describing data layout + * @param mips specifies desired mipmap behaviour for the + * allocation + * @param usage bit field specifying how the allocation is + * utilized + */ + static public Allocation createTyped(RenderScript rs, Type type, MipmapControl mips, int usage) { rs.validate(); - if(type.mID == 0) { - throw new IllegalStateException("Bad Type"); + if (type.getID() == 0) { + throw new RSInvalidStateException("Bad Type"); } - int id = rs.nAllocationCreateTyped(type.mID); - return new Allocation(id, rs, type); - } - - static public Allocation createSized(RenderScript rs, Element e, int count) - throws IllegalArgumentException { - + int id = rs.nAllocationCreateTyped(type.getID(), mips.mID, usage); + if (id == 0) { + throw new RSRuntimeException("Allocation creation failed."); + } + return new Allocation(id, rs, type, usage); + } + + /** + * Creates a renderscript allocation with the size specified by + * the type and no mipmaps generated by default + * + * @param rs + * @param type renderscript type describing data layout + * @param usage bit field specifying how the allocation is + * utilized + * + * @return allocation + */ + static public Allocation createTyped(RenderScript rs, Type type, int usage) { + return createTyped(rs, type, MipmapControl.MIPMAP_NONE, usage); + } + + /** + * Creates a renderscript allocation for use by the script with + * the size specified by the type and no mipmaps generated by + * default + * + * @param rs + * @param type renderscript type describing data layout + * + * @return allocation + */ + static public Allocation createTyped(RenderScript rs, Type type) { + return createTyped(rs, type, MipmapControl.MIPMAP_NONE, USAGE_SCRIPT); + } + + /** + * Creates a renderscript allocation with a specified number of + * given elements + * + * @param rs + * @param e describes what each element of an allocation is + * @param count specifies the number of element in the allocation + * @param usage bit field specifying how the allocation is + * utilized + * + * @return allocation + */ + static public Allocation createSized(RenderScript rs, Element e, + int count, int usage) { rs.validate(); Type.Builder b = new Type.Builder(rs, e); - b.add(Dimension.X, count); + b.setX(count); Type t = b.create(); - int id = rs.nAllocationCreateTyped(t.mID); - if(id == 0) { - throw new IllegalStateException("Bad element."); + int id = rs.nAllocationCreateTyped(t.getID(), MipmapControl.MIPMAP_NONE.mID, usage); + if (id == 0) { + throw new RSRuntimeException("Allocation creation failed."); } - return new Allocation(id, rs, t); + return new Allocation(id, rs, t, usage); + } + + /** + * Creates a renderscript allocation with a specified number of + * given elements + * + * @param rs + * @param e describes what each element of an allocation is + * @param count specifies the number of element in the allocation + * + * @return allocation + */ + static public Allocation createSized(RenderScript rs, Element e, int count) { + return createSized(rs, e, count, USAGE_SCRIPT); } - static private Element elementFromBitmap(RenderScript rs, Bitmap b) { + static Element elementFromBitmap(RenderScript rs, Bitmap b) { final Bitmap.Config bc = b.getConfig(); if (bc == Bitmap.Config.ALPHA_8) { return Element.A_8(rs); @@ -277,105 +582,294 @@ public class Allocation extends BaseObj { if (bc == Bitmap.Config.RGB_565) { return Element.RGB_565(rs); } - throw new IllegalStateException("Bad bitmap type."); + throw new RSInvalidStateException("Bad bitmap type: " + bc); } - static private Type typeFromBitmap(RenderScript rs, Bitmap b) { + static Type typeFromBitmap(RenderScript rs, Bitmap b, + MipmapControl mip) { Element e = elementFromBitmap(rs, b); Type.Builder tb = new Type.Builder(rs, e); - tb.add(Dimension.X, b.getWidth()); - tb.add(Dimension.Y, b.getHeight()); + tb.setX(b.getWidth()); + tb.setY(b.getHeight()); + tb.setMipmaps(mip == MipmapControl.MIPMAP_FULL); return tb.create(); } - static public Allocation createFromBitmap(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips) - throws IllegalArgumentException { - + /** + * Creates a renderscript allocation from a bitmap + * + * @param rs + * @param b bitmap source for the allocation data + * @param mips specifies desired mipmap behaviour for the + * allocation + * @param usage bit field specifying how the allocation is + * utilized + * + * @return renderscript allocation containing bitmap data + * + */ + static public Allocation createFromBitmap(RenderScript rs, Bitmap b, + MipmapControl mips, + int usage) { rs.validate(); - Type t = typeFromBitmap(rs, b); + Type t = typeFromBitmap(rs, b, mips); - int id = rs.nAllocationCreateFromBitmap(dstFmt.mID, genMips, b); - if(id == 0) { - throw new IllegalStateException("Load failed."); + int id = rs.nAllocationCreateFromBitmap(t.getID(), mips.mID, b, usage); + if (id == 0) { + throw new RSRuntimeException("Load failed."); } - return new Allocation(id, rs, t); - } - - static public Allocation createBitmapRef(RenderScript rs, Bitmap b) - throws IllegalArgumentException { - + return new Allocation(id, rs, t, usage); + } + + /** + * Creates a non-mipmapped renderscript allocation to use as a + * graphics texture + * + * @param rs + * @param b bitmap source for the allocation data + * + * @return renderscript allocation containing bitmap data + * + */ + static public Allocation createFromBitmap(RenderScript rs, Bitmap b) { + return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, + USAGE_GRAPHICS_TEXTURE); + } + + /** + * Creates a cubemap allocation from a bitmap containing the + * horizontal list of cube faces. Each individual face must be + * the same size and power of 2 + * + * @param rs + * @param b bitmap with cubemap faces layed out in the following + * format: right, left, top, bottom, front, back + * @param mips specifies desired mipmap behaviour for the cubemap + * @param usage bit field specifying how the cubemap is utilized + * + * @return allocation containing cubemap data + * + */ + static public Allocation createCubemapFromBitmap(RenderScript rs, Bitmap b, + MipmapControl mips, + int usage) { rs.validate(); - Type t = typeFromBitmap(rs, b); - int id = rs.nAllocationCreateBitmapRef(t.getID(), b); - if(id == 0) { - throw new IllegalStateException("Load failed."); - } + int height = b.getHeight(); + int width = b.getWidth(); - Allocation a = new Allocation(id, rs, t); - a.mBitmap = b; - return a; - } + if (width % 6 != 0) { + throw new RSIllegalArgumentException("Cubemap height must be multiple of 6"); + } + if (width / 6 != height) { + throw new RSIllegalArgumentException("Only square cube map faces supported"); + } + boolean isPow2 = (height & (height - 1)) == 0; + if (!isPow2) { + throw new RSIllegalArgumentException("Only power of 2 cube faces supported"); + } - static Allocation createFromBitmapBoxed(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips) - throws IllegalArgumentException { + Element e = elementFromBitmap(rs, b); + Type.Builder tb = new Type.Builder(rs, e); + tb.setX(height); + tb.setY(height); + tb.setFaces(true); + tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL); + Type t = tb.create(); - rs.validate(); - int id = rs.nAllocationCreateFromBitmapBoxed(dstFmt.mID, genMips, b); + int id = rs.nAllocationCubeCreateFromBitmap(t.getID(), mips.mID, b, usage); if(id == 0) { - throw new IllegalStateException("Load failed."); + throw new RSRuntimeException("Load failed for bitmap " + b + " element " + e); + } + return new Allocation(id, rs, t, usage); + } + + /** + * Creates a non-mipmapped cubemap allocation for use as a + * graphics texture from a bitmap containing the horizontal list + * of cube faces. Each individual face must be the same size and + * power of 2 + * + * @param rs + * @param b bitmap with cubemap faces layed out in the following + * format: right, left, top, bottom, front, back + * + * @return allocation containing cubemap data + * + */ + static public Allocation createCubemapFromBitmap(RenderScript rs, + Bitmap b) { + return createCubemapFromBitmap(rs, b, MipmapControl.MIPMAP_NONE, + USAGE_GRAPHICS_TEXTURE); + } + + /** + * Creates a cubemap allocation from 6 bitmaps containing + * the cube faces. All the faces must be the same size and + * power of 2 + * + * @param rs + * @param xpos cubemap face in the positive x direction + * @param xneg cubemap face in the negative x direction + * @param ypos cubemap face in the positive y direction + * @param yneg cubemap face in the negative y direction + * @param zpos cubemap face in the positive z direction + * @param zneg cubemap face in the negative z direction + * @param mips specifies desired mipmap behaviour for the cubemap + * @param usage bit field specifying how the cubemap is utilized + * + * @return allocation containing cubemap data + * + */ + static public Allocation createCubemapFromCubeFaces(RenderScript rs, + Bitmap xpos, + Bitmap xneg, + Bitmap ypos, + Bitmap yneg, + Bitmap zpos, + Bitmap zneg, + MipmapControl mips, + int usage) { + int height = xpos.getHeight(); + if (xpos.getWidth() != height || + xneg.getWidth() != height || xneg.getHeight() != height || + ypos.getWidth() != height || ypos.getHeight() != height || + yneg.getWidth() != height || yneg.getHeight() != height || + zpos.getWidth() != height || zpos.getHeight() != height || + zneg.getWidth() != height || zneg.getHeight() != height) { + throw new RSIllegalArgumentException("Only square cube map faces supported"); + } + boolean isPow2 = (height & (height - 1)) == 0; + if (!isPow2) { + throw new RSIllegalArgumentException("Only power of 2 cube faces supported"); } - return new Allocation(id, rs, null); - } - static public Allocation createFromBitmapResource(RenderScript rs, Resources res, int id, Element dstFmt, boolean genMips) - throws IllegalArgumentException { + Element e = elementFromBitmap(rs, xpos); + Type.Builder tb = new Type.Builder(rs, e); + tb.setX(height); + tb.setY(height); + tb.setFaces(true); + tb.setMipmaps(mips == MipmapControl.MIPMAP_FULL); + Type t = tb.create(); + Allocation cubemap = Allocation.createTyped(rs, t, mips, usage); + + AllocationAdapter adapter = AllocationAdapter.create2D(rs, cubemap); + adapter.setFace(Type.CubemapFace.POSITVE_X); + adapter.copyFrom(xpos); + adapter.setFace(Type.CubemapFace.NEGATIVE_X); + adapter.copyFrom(xneg); + adapter.setFace(Type.CubemapFace.POSITVE_Y); + adapter.copyFrom(ypos); + adapter.setFace(Type.CubemapFace.NEGATIVE_Y); + adapter.copyFrom(yneg); + adapter.setFace(Type.CubemapFace.POSITVE_Z); + adapter.copyFrom(zpos); + adapter.setFace(Type.CubemapFace.NEGATIVE_Z); + adapter.copyFrom(zneg); + + return cubemap; + } + + /** + * Creates a non-mipmapped cubemap allocation for use as a + * graphics texture from 6 bitmaps containing + * the cube faces. All the faces must be the same size and + * power of 2 + * + * @param rs + * @param xpos cubemap face in the positive x direction + * @param xneg cubemap face in the negative x direction + * @param ypos cubemap face in the positive y direction + * @param yneg cubemap face in the negative y direction + * @param zpos cubemap face in the positive z direction + * @param zneg cubemap face in the negative z direction + * + * @return allocation containing cubemap data + * + */ + static public Allocation createCubemapFromCubeFaces(RenderScript rs, + Bitmap xpos, + Bitmap xneg, + Bitmap ypos, + Bitmap yneg, + Bitmap zpos, + Bitmap zneg) { + return createCubemapFromCubeFaces(rs, xpos, xneg, ypos, yneg, + zpos, zneg, MipmapControl.MIPMAP_NONE, + USAGE_GRAPHICS_TEXTURE); + } + + /** + * Creates a renderscript allocation from the bitmap referenced + * by resource id + * + * @param rs + * @param res application resources + * @param id resource id to load the data from + * @param mips specifies desired mipmap behaviour for the + * allocation + * @param usage bit field specifying how the allocation is + * utilized + * + * @return renderscript allocation containing resource data + * + */ + static public Allocation createFromBitmapResource(RenderScript rs, + Resources res, + int id, + MipmapControl mips, + int usage) { rs.validate(); - InputStream is = null; + Bitmap b = BitmapFactory.decodeResource(res, id); + Allocation alloc = createFromBitmap(rs, b, mips, usage); + b.recycle(); + return alloc; + } + + /** + * Creates a non-mipmapped renderscript allocation to use as a + * graphics texture from the bitmap referenced by resource id + * + * @param rs + * @param res application resources + * @param id resource id to load the data from + * + * @return renderscript allocation containing resource data + * + */ + static public Allocation createFromBitmapResource(RenderScript rs, + Resources res, + int id) { + return createFromBitmapResource(rs, res, id, + MipmapControl.MIPMAP_NONE, + USAGE_GRAPHICS_TEXTURE); + } + + /** + * Creates a renderscript allocation containing string data + * encoded in UTF-8 format + * + * @param rs + * @param str string to create the allocation from + * @param usage bit field specifying how the allocaiton is + * utilized + * + */ + static public Allocation createFromString(RenderScript rs, + String str, + int usage) { + rs.validate(); + byte[] allocArray = null; try { - final TypedValue value = new TypedValue(); - is = res.openRawResource(id, value); - - int asset = ((AssetManager.AssetInputStream) is).getAssetInt(); - int allocationId = rs.nAllocationCreateFromAssetStream(dstFmt.mID, genMips, - asset); - - if(allocationId == 0) { - throw new IllegalStateException("Load failed."); - } - return new Allocation(allocationId, rs, null); - } catch (Exception e) { - // Ignore - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - // Ignore - } - } + allocArray = str.getBytes("UTF-8"); + Allocation alloc = Allocation.createSized(rs, Element.U8(rs), allocArray.length, usage); + alloc.copyFrom(allocArray); + return alloc; } - - return null; - } - - static public Allocation createFromBitmapResourceBoxed(RenderScript rs, Resources res, int id, Element dstFmt, boolean genMips) - throws IllegalArgumentException { - - mBitmapOptions.inPreferredConfig = null; - if (dstFmt == rs.mElement_RGBA_8888) { - mBitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888; - } else if (dstFmt == rs.mElement_RGB_888) { - mBitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_8888; - } else if (dstFmt == rs.mElement_RGBA_4444) { - mBitmapOptions.inPreferredConfig = Bitmap.Config.ARGB_4444; - } else if (dstFmt == rs.mElement_RGB_565) { - mBitmapOptions.inPreferredConfig = Bitmap.Config.RGB_565; + catch (Exception e) { + throw new RSRuntimeException("Could not convert string to utf-8."); } - - Bitmap b = BitmapFactory.decodeResource(res, id, mBitmapOptions); - return createFromBitmapBoxed(rs, b, dstFmt, genMips); } } |