From 9db3d07b9620b4269ab33f78604a36327e536ce1 Mon Sep 17 00:00:00 2001 From: Jean-Baptiste Queru Date: Thu, 12 Nov 2009 18:45:53 -0800 Subject: eclair snapshot --- graphics/java/android/graphics/Bitmap.java | 35 +- graphics/java/android/graphics/BitmapFactory.java | 43 +- graphics/java/android/graphics/BlurMaskFilter.java | 14 +- graphics/java/android/graphics/Color.java | 196 +++++++- graphics/java/android/graphics/DashPathEffect.java | 6 +- graphics/java/android/graphics/Paint.java | 126 +++++- graphics/java/android/graphics/PixelFormat.java | 13 + .../java/android/graphics/TableMaskFilter.java | 46 ++ graphics/java/android/graphics/Typeface.java | 12 + .../graphics/drawable/AnimatedRotateDrawable.java | 22 +- .../graphics/drawable/AnimationDrawable.java | 18 +- .../android/graphics/drawable/BitmapDrawable.java | 83 +++- .../android/graphics/drawable/ClipDrawable.java | 23 +- .../android/graphics/drawable/ColorDrawable.java | 5 + .../java/android/graphics/drawable/Drawable.java | 34 +- .../graphics/drawable/DrawableContainer.java | 38 +- .../graphics/drawable/GradientDrawable.java | 14 + .../android/graphics/drawable/InsetDrawable.java | 23 +- .../android/graphics/drawable/LayerDrawable.java | 27 +- .../graphics/drawable/LevelListDrawable.java | 17 +- .../graphics/drawable/NinePatchDrawable.java | 95 ++-- .../android/graphics/drawable/RotateDrawable.java | 21 +- .../android/graphics/drawable/ScaleDrawable.java | 23 +- .../android/graphics/drawable/ShapeDrawable.java | 5 + .../graphics/drawable/StateListDrawable.java | 31 +- .../graphics/drawable/TransitionDrawable.java | 25 +- graphics/java/android/renderscript/Allocation.java | 276 ++++++++++++ graphics/java/android/renderscript/BaseObj.java | 84 ++++ graphics/java/android/renderscript/Dimension.java | 35 ++ graphics/java/android/renderscript/Element.java | 494 +++++++++++++++++++++ graphics/java/android/renderscript/Light.java | 73 +++ graphics/java/android/renderscript/Matrix.java | 192 ++++++++ graphics/java/android/renderscript/Primitive.java | 37 ++ .../java/android/renderscript/ProgramFragment.java | 158 +++++++ .../java/android/renderscript/ProgramRaster.java | 110 +++++ .../java/android/renderscript/ProgramStore.java | 173 ++++++++ .../java/android/renderscript/ProgramVertex.java | 185 ++++++++ .../java/android/renderscript/RSSurfaceView.java | 167 +++++++ .../java/android/renderscript/RenderScript.java | 366 +++++++++++++++ graphics/java/android/renderscript/Sampler.java | 108 +++++ graphics/java/android/renderscript/Script.java | 144 ++++++ graphics/java/android/renderscript/ScriptC.java | 161 +++++++ graphics/java/android/renderscript/SimpleMesh.java | 351 +++++++++++++++ graphics/java/android/renderscript/Type.java | 225 ++++++++++ 44 files changed, 4159 insertions(+), 175 deletions(-) create mode 100644 graphics/java/android/graphics/TableMaskFilter.java create mode 100644 graphics/java/android/renderscript/Allocation.java create mode 100644 graphics/java/android/renderscript/BaseObj.java create mode 100644 graphics/java/android/renderscript/Dimension.java create mode 100644 graphics/java/android/renderscript/Element.java create mode 100644 graphics/java/android/renderscript/Light.java create mode 100644 graphics/java/android/renderscript/Matrix.java create mode 100644 graphics/java/android/renderscript/Primitive.java create mode 100644 graphics/java/android/renderscript/ProgramFragment.java create mode 100644 graphics/java/android/renderscript/ProgramRaster.java create mode 100644 graphics/java/android/renderscript/ProgramStore.java create mode 100644 graphics/java/android/renderscript/ProgramVertex.java create mode 100644 graphics/java/android/renderscript/RSSurfaceView.java create mode 100644 graphics/java/android/renderscript/RenderScript.java create mode 100644 graphics/java/android/renderscript/Sampler.java create mode 100644 graphics/java/android/renderscript/Script.java create mode 100644 graphics/java/android/renderscript/ScriptC.java create mode 100644 graphics/java/android/renderscript/SimpleMesh.java create mode 100644 graphics/java/android/renderscript/Type.java (limited to 'graphics/java') diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index eef1096..5aa88b0 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -77,7 +77,8 @@ public final class Bitmap implements Parcelable { This can be called from JNI code. */ - private Bitmap(int nativeBitmap, boolean isMutable, byte[] ninePatchChunk) { + private Bitmap(int nativeBitmap, boolean isMutable, byte[] ninePatchChunk, + int density) { if (nativeBitmap == 0) { throw new RuntimeException("internal error: native bitmap is 0"); } @@ -86,6 +87,9 @@ public final class Bitmap implements Parcelable { mNativeBitmap = nativeBitmap; mIsMutable = isMutable; mNinePatchChunk = ninePatchChunk; + if (density >= 0) { + mDensity = density; + } } /** @@ -680,12 +684,35 @@ public final class Bitmap implements Parcelable { return Config.nativeToConfig(nativeConfig(mNativeBitmap)); } - /** Returns true if the bitmap's pixels support levels of alpha */ + /** Returns true if the bitmap's config supports per-pixel alpha, and + * if the pixels may contain non-opaque alpha values. For some configs, + * this is always false (e.g. RGB_565), since they do not support per-pixel + * alpha. However, for configs that do, the bitmap may be flagged to be + * known that all of its pixels are opaque. In this case hasAlpha() will + * also return false. If a config such as ARGB_8888 is not so flagged, + * it will return true by default. + */ public final boolean hasAlpha() { return nativeHasAlpha(mNativeBitmap); } /** + * Tell the bitmap if all of the pixels are known to be opaque (false) + * or if some of the pixels may contain non-opaque alpha values (true). + * Note, for some configs (e.g. RGB_565) this call is ignore, since it does + * not support per-pixel alpha values. + * + * This is meant as a drawing hint, as in some cases a bitmap that is known + * to be opaque can take a faster drawing case than one that may have + * non-opaque per-pixel alpha values. + * + * @hide + */ + public void setHasAlpha(boolean hasAlpha) { + nativeSetHasAlpha(mNativeBitmap, hasAlpha); + } + + /** * Fills the bitmap's pixels with the specified {@link Color}. * * @throws IllegalStateException if the bitmap is not mutable. @@ -892,7 +919,7 @@ public final class Bitmap implements Parcelable { */ public void writeToParcel(Parcel p, int flags) { checkRecycled("Can't parcel a recycled bitmap"); - if (!nativeWriteToParcel(mNativeBitmap, mIsMutable, p)) { + if (!nativeWriteToParcel(mNativeBitmap, mIsMutable, mDensity, p)) { throw new RuntimeException("native writeToParcel failed"); } } @@ -1006,6 +1033,7 @@ public final class Bitmap implements Parcelable { // returns true on success private static native boolean nativeWriteToParcel(int nativeBitmap, boolean isMutable, + int density, Parcel p); // returns a new bitmap built from the native bitmap's alpha, and the paint private static native Bitmap nativeExtractAlpha(int nativeBitmap, @@ -1013,6 +1041,7 @@ public final class Bitmap implements Parcelable { int[] offsetXY); private static native void nativePrepareToDraw(int nativeBitmap); + private static native void nativeSetHasAlpha(int nBitmap, boolean hasAlpha); /* package */ final int ni() { return mNativeBitmap; diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java index c8bed24..f60a7be 100644 --- a/graphics/java/android/graphics/BitmapFactory.java +++ b/graphics/java/android/graphics/BitmapFactory.java @@ -18,6 +18,7 @@ package android.graphics; import android.content.res.AssetManager; import android.content.res.Resources; +import android.os.MemoryFile; import android.util.DisplayMetrics; import android.util.TypedValue; @@ -72,7 +73,7 @@ public class BitmapFactory { public Bitmap.Config inPreferredConfig; /** - * If dither is true, the decoder will atttempt to dither the decoded + * If dither is true, the decoder will attempt to dither the decoded * image. */ public boolean inDither; @@ -336,19 +337,26 @@ public class BitmapFactory { */ public static Bitmap decodeResource(Resources res, int id, Options opts) { Bitmap bm = null; - + InputStream is = null; + try { final TypedValue value = new TypedValue(); - final InputStream is = res.openRawResource(id, value); + is = res.openRawResource(id, value); bm = decodeResourceStream(res, value, is, null, opts); - is.close(); - } catch (java.io.IOException e) { + } catch (Exception e) { /* do nothing. If the exception happened on open, bm will be null. If it happened on close, bm is still valid. */ + } finally { + try { + if (is != null) is.close(); + } catch (IOException e) { + // Ignore + } } + return bm; } @@ -451,6 +459,10 @@ public class BitmapFactory { bm = nativeDecodeStream(is, tempStorage, outPadding, opts); } + return finishDecode(bm, outPadding, opts); + } + + private static Bitmap finishDecode(Bitmap bm, Rect outPadding, Options opts) { if (bm == null || opts == null) { return bm; } @@ -486,7 +498,7 @@ public class BitmapFactory { return bm; } - + /** * Decode an input stream into a bitmap. If the input stream is null, or * cannot be used to decode a bitmap, the function returns null. @@ -506,7 +518,7 @@ public class BitmapFactory { /** * Decode a bitmap from the file descriptor. If the bitmap cannot be decoded * return null. The position within the descriptor will not be changed when - * this returns, so the descriptor can be used again as is. + * this returns, so the descriptor can be used again as-is. * * @param fd The file descriptor containing the bitmap data to decode * @param outPadding If not null, return the padding rect for the bitmap if @@ -518,7 +530,20 @@ public class BitmapFactory { * @return the decoded bitmap, or null */ public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) { - return nativeDecodeFileDescriptor(fd, outPadding, opts); + try { + if (MemoryFile.isMemoryFile(fd)) { + int mappedlength = MemoryFile.getMappedSize(fd); + MemoryFile file = new MemoryFile(fd, mappedlength, "r"); + InputStream is = file.getInputStream(); + Bitmap bm = decodeStream(is, outPadding, opts); + return finishDecode(bm, outPadding, opts); + } + } catch (IOException ex) { + // invalid filedescriptor, no need to call nativeDecodeFileDescriptor() + return null; + } + Bitmap bm = nativeDecodeFileDescriptor(fd, outPadding, opts); + return finishDecode(bm, outPadding, opts); } /** @@ -530,7 +555,7 @@ public class BitmapFactory { * @return the decoded bitmap, or null */ public static Bitmap decodeFileDescriptor(FileDescriptor fd) { - return nativeDecodeFileDescriptor(fd, null, null); + return decodeFileDescriptor(fd, null, null); } private static native Bitmap nativeDecodeStream(InputStream is, byte[] storage, diff --git a/graphics/java/android/graphics/BlurMaskFilter.java b/graphics/java/android/graphics/BlurMaskFilter.java index dbf57ac..5eafe76 100644 --- a/graphics/java/android/graphics/BlurMaskFilter.java +++ b/graphics/java/android/graphics/BlurMaskFilter.java @@ -16,13 +16,19 @@ package android.graphics; +/** + * This takes a mask, and blurs its edge by the specified radius. Whether or + * or not to include the original mask, and whether the blur goes outside, + * inside, or straddles, the original mask's border, is controlled by the + * Blur enum. + */ public class BlurMaskFilter extends MaskFilter { public enum Blur { - NORMAL(0), //!< fuzzy inside and outside - SOLID(1), //!< solid inside, fuzzy outside - OUTER(2), //!< nothing inside, fuzzy outside - INNER(3); //!< fuzzy inside, nothing outside + NORMAL(0), //!< blur inside and outside of the original border + SOLID(1), //!< include the original mask, blur outside + OUTER(2), //!< just blur outside the original border + INNER(3); //!< just blur inside the original border Blur(int value) { native_int = value; diff --git a/graphics/java/android/graphics/Color.java b/graphics/java/android/graphics/Color.java index 3fc391c..5cefaa3 100644 --- a/graphics/java/android/graphics/Color.java +++ b/graphics/java/android/graphics/Color.java @@ -16,6 +16,8 @@ package android.graphics; +import android.util.MathUtils; + import java.util.HashMap; import java.util.Locale; @@ -105,6 +107,92 @@ public class Color { } /** + * Returns the hue component of a color int. + * + * @return A value between 0.0f and 1.0f + * + * @hide Pending API council + */ + public static float hue(int color) { + int r = (color >> 16) & 0xFF; + int g = (color >> 8) & 0xFF; + int b = color & 0xFF; + + int V = Math.max(b, Math.max(r, g)); + int temp = Math.min(b, Math.min(r, g)); + + float H; + + if (V == temp) { + H = 0; + } else { + final float vtemp = (float) (V - temp); + final float cr = (V - r) / vtemp; + final float cg = (V - g) / vtemp; + final float cb = (V - b) / vtemp; + + if (r == V) { + H = cb - cg; + } else if (g == V) { + H = 2 + cr - cb; + } else { + H = 4 + cg - cr; + } + + H /= 6.f; + if (H < 0) { + H++; + } + } + + return H; + } + + /** + * Returns the saturation component of a color int. + * + * @return A value between 0.0f and 1.0f + * + * @hide Pending API council + */ + public static float saturation(int color) { + int r = (color >> 16) & 0xFF; + int g = (color >> 8) & 0xFF; + int b = color & 0xFF; + + + int V = Math.max(b, Math.max(r, g)); + int temp = Math.min(b, Math.min(r, g)); + + float S; + + if (V == temp) { + S = 0; + } else { + S = (V - temp) / (float) V; + } + + return S; + } + + /** + * Returns the brightness component of a color int. + * + * @return A value between 0.0f and 1.0f + * + * @hide Pending API council + */ + public static float brightness(int color) { + int r = (color >> 16) & 0xFF; + int g = (color >> 8) & 0xFF; + int b = color & 0xFF; + + int V = Math.max(b, Math.max(r, g)); + + return (V / 255.f); + } + + /** * Parse the color string, and return the corresponding color-int. * If the string cannot be parsed, throws an IllegalArgumentException * exception. Supported formats are: @@ -134,6 +222,87 @@ public class Color { } /** + * Convert HSB components to an ARGB color. Alpha set to 0xFF. + * hsv[0] is Hue [0 .. 1) + * hsv[1] is Saturation [0...1] + * hsv[2] is Value [0...1] + * If hsv values are out of range, they are pinned. + * @param hsb 3 element array which holds the input HSB components. + * @return the resulting argb color + * + * @hide Pending API council + */ + public static int HSBtoColor(float[] hsb) { + return HSBtoColor(hsb[0], hsb[1], hsb[2]); + } + + /** + * Convert HSB components to an ARGB color. Alpha set to 0xFF. + * hsv[0] is Hue [0 .. 1) + * hsv[1] is Saturation [0...1] + * hsv[2] is Value [0...1] + * If hsv values are out of range, they are pinned. + * @param h Hue component + * @param s Saturation component + * @param b Brightness component + * @return the resulting argb color + * + * @hide Pending API council + */ + public static int HSBtoColor(float h, float s, float b) { + h = MathUtils.constrain(h, 0.0f, 1.0f); + s = MathUtils.constrain(s, 0.0f, 1.0f); + b = MathUtils.constrain(b, 0.0f, 1.0f); + + float red = 0.0f; + float green = 0.0f; + float blue = 0.0f; + + final float hf = (h - (int) h) * 6.0f; + final int ihf = (int) hf; + final float f = hf - ihf; + final float pv = b * (1.0f - s); + final float qv = b * (1.0f - s * f); + final float tv = b * (1.0f - s * (1.0f - f)); + + switch (ihf) { + case 0: // Red is the dominant color + red = b; + green = tv; + blue = pv; + break; + case 1: // Green is the dominant color + red = qv; + green = b; + blue = pv; + break; + case 2: + red = pv; + green = b; + blue = tv; + break; + case 3: // Blue is the dominant color + red = pv; + green = qv; + blue = b; + break; + case 4: + red = tv; + green = pv; + blue = b; + break; + case 5: // Red is the dominant color + red = b; + green = pv; + blue = qv; + break; + } + + return 0xFF000000 | (((int) (red * 255.0f)) << 16) | + (((int) (green * 255.0f)) << 8) | ((int) (blue * 255.0f)); + } + + /** * Convert RGB components to HSV. * hsv[0] is Hue [0 .. 360) * hsv[1] is Saturation [0...1] @@ -193,25 +362,24 @@ public class Color { return nativeHSVToColor(alpha, hsv); } - private static native void nativeRGBToHSV(int red, int greed, int blue, - float hsv[]); + private static native void nativeRGBToHSV(int red, int greed, int blue, float hsv[]); private static native int nativeHSVToColor(int alpha, float hsv[]); private static final HashMap sColorNameMap; static { - sColorNameMap = new HashMap(); - sColorNameMap.put("black", Integer.valueOf(BLACK)); - sColorNameMap.put("darkgray", Integer.valueOf(DKGRAY)); - sColorNameMap.put("gray", Integer.valueOf(GRAY)); - sColorNameMap.put("lightgray", Integer.valueOf(LTGRAY)); - sColorNameMap.put("white", Integer.valueOf(WHITE)); - sColorNameMap.put("red", Integer.valueOf(RED)); - sColorNameMap.put("green", Integer.valueOf(GREEN)); - sColorNameMap.put("blue", Integer.valueOf(BLUE)); - sColorNameMap.put("yellow", Integer.valueOf(YELLOW)); - sColorNameMap.put("cyan", Integer.valueOf(CYAN)); - sColorNameMap.put("magenta", Integer.valueOf(MAGENTA)); + sColorNameMap = new HashMap(); + sColorNameMap.put("black", BLACK); + sColorNameMap.put("darkgray", DKGRAY); + sColorNameMap.put("gray", GRAY); + sColorNameMap.put("lightgray", LTGRAY); + sColorNameMap.put("white", WHITE); + sColorNameMap.put("red", RED); + sColorNameMap.put("green", GREEN); + sColorNameMap.put("blue", BLUE); + sColorNameMap.put("yellow", YELLOW); + sColorNameMap.put("cyan", CYAN); + sColorNameMap.put("magenta", MAGENTA); } } diff --git a/graphics/java/android/graphics/DashPathEffect.java b/graphics/java/android/graphics/DashPathEffect.java index 3deca4a..4f16dc4 100644 --- a/graphics/java/android/graphics/DashPathEffect.java +++ b/graphics/java/android/graphics/DashPathEffect.java @@ -23,13 +23,13 @@ public class DashPathEffect extends PathEffect { * the even indices specifying the "on" intervals, and the odd indices * specifying the "off" intervals. phase is an offset into the intervals * array (mod the sum of all of the intervals). The intervals array - * controlls the width of the dashes. The paint's strokeWidth controlls the - * height of the dashes. + * controls the length of the dashes. The paint's strokeWidth controls the + * thickness of the dashes. * Note: this patheffect only affects drawing with the paint's style is set * to STROKE or STROKE_AND_FILL. It is ignored if the drawing is done with * style == FILL. * @param intervals array of ON and OFF distances - * @param phase offset before the first ON interval is drawn + * @param phase offset into the intervals array */ public DashPathEffect(float intervals[], float phase) { if (intervals.length < 2) { diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java index 862e827..3e3f87b 100644 --- a/graphics/java/android/graphics/Paint.java +++ b/graphics/java/android/graphics/Paint.java @@ -36,6 +36,10 @@ public class Paint { private Typeface mTypeface; private Xfermode mXfermode; + private boolean mHasCompatScaling; + private float mCompatScaling; + private float mInvCompatScaling; + private static final Style[] sStyleArray = { Style.FILL, Style.STROKE, Style.FILL_AND_STROKE }; @@ -189,6 +193,7 @@ public class Paint { public Paint(int flags) { mNativePaint = native_init(); setFlags(flags | DEFAULT_PAINT_FLAGS); + mCompatScaling = mInvCompatScaling = 1; } /** @@ -200,12 +205,17 @@ public class Paint { */ public Paint(Paint paint) { mNativePaint = native_initWithPaint(paint.mNativePaint); + mHasCompatScaling = paint.mHasCompatScaling; + mCompatScaling = paint.mCompatScaling; + mInvCompatScaling = paint.mInvCompatScaling; } /** Restores the paint to its default settings. */ public void reset() { native_reset(mNativePaint); setFlags(DEFAULT_PAINT_FLAGS); + mHasCompatScaling = false; + mCompatScaling = mInvCompatScaling = 1; } /** @@ -225,9 +235,24 @@ public class Paint { mShader = src.mShader; mTypeface = src.mTypeface; mXfermode = src.mXfermode; + mHasCompatScaling = src.mHasCompatScaling; + mCompatScaling = src.mCompatScaling; + mInvCompatScaling = src.mInvCompatScaling; } } + /** @hide */ + public void setCompatibilityScaling(float factor) { + if (factor == 1.0) { + mHasCompatScaling = false; + mCompatScaling = mInvCompatScaling = 1.0f; + } else { + mHasCompatScaling = true; + mCompatScaling = factor; + mInvCompatScaling = 1.0f/factor; + } + } + /** * Return the paint's flags. Use the Flag enum to test flag values. * @@ -972,8 +997,17 @@ public class Paint { * @param count THe number of characters to measure, beginning with start * @return The width of the text */ - public native float measureText(char[] text, int index, int count); + public float measureText(char[] text, int index, int count) { + if (!mHasCompatScaling) return native_measureText(text, index, count); + final float oldSize = getTextSize(); + setTextSize(oldSize*mCompatScaling); + float w = native_measureText(text, index, count); + setTextSize(oldSize); + return w*mInvCompatScaling; + } + private native float native_measureText(char[] text, int index, int count); + /** * Return the width of the text. * @@ -982,16 +1016,34 @@ public class Paint { * @param end 1 beyond the index of the last character to measure * @return The width of the text */ - public native float measureText(String text, int start, int end); + public float measureText(String text, int start, int end) { + if (!mHasCompatScaling) return native_measureText(text, start, end); + final float oldSize = getTextSize(); + setTextSize(oldSize*mCompatScaling); + float w = native_measureText(text, start, end); + setTextSize(oldSize); + return w*mInvCompatScaling; + } + private native float native_measureText(String text, int start, int end); + /** * Return the width of the text. * * @param text The text to measure * @return The width of the text */ - public native float measureText(String text); + public float measureText(String text) { + if (!mHasCompatScaling) return native_measureText(text); + final float oldSize = getTextSize(); + setTextSize(oldSize*mCompatScaling); + float w = native_measureText(text); + setTextSize(oldSize); + return w*mInvCompatScaling; + } + private native float native_measureText(String text); + /** * Return the width of the text. * @@ -1013,10 +1065,10 @@ public class Paint { } char[] buf = TemporaryBuffer.obtain(end - start); - TextUtils.getChars(text, start, end, buf, 0); - float result = measureText(buf, 0, end - start); + TextUtils.getChars(text, start, end, buf, 0); + float result = measureText(buf, 0, end - start); TemporaryBuffer.recycle(buf); - return result; + return result; } /** @@ -1036,8 +1088,22 @@ public class Paint { * @return The number of chars that were measured. Will always be <= * abs(count). */ - public native int breakText(char[] text, int index, int count, - float maxWidth, float[] measuredWidth); + public int breakText(char[] text, int index, int count, + float maxWidth, float[] measuredWidth) { + if (!mHasCompatScaling) { + return native_breakText(text, index, count, maxWidth, measuredWidth); + } + final float oldSize = getTextSize(); + setTextSize(oldSize*mCompatScaling); + int res = native_breakText(text, index, count, maxWidth*mCompatScaling, + measuredWidth); + setTextSize(oldSize); + if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling; + return res; + } + + private native int native_breakText(char[] text, int index, int count, + float maxWidth, float[] measuredWidth); /** * Measure the text, stopping early if the measured width exceeds maxWidth. @@ -1094,8 +1160,22 @@ public class Paint { * @return The number of chars that were measured. Will always be <= * abs(count). */ - public native int breakText(String text, boolean measureForwards, - float maxWidth, float[] measuredWidth); + public int breakText(String text, boolean measureForwards, + float maxWidth, float[] measuredWidth) { + if (!mHasCompatScaling) { + return native_breakText(text, measureForwards, maxWidth, measuredWidth); + } + final float oldSize = getTextSize(); + setTextSize(oldSize*mCompatScaling); + int res = native_breakText(text, measureForwards, maxWidth*mCompatScaling, + measuredWidth); + setTextSize(oldSize); + if (measuredWidth != null) measuredWidth[0] *= mInvCompatScaling; + return res; + } + + private native int native_breakText(String text, boolean measureForwards, + float maxWidth, float[] measuredWidth); /** * Return the advance widths for the characters in the string. @@ -1113,7 +1193,18 @@ public class Paint { || count > widths.length) { throw new ArrayIndexOutOfBoundsException(); } - return native_getTextWidths(mNativePaint, text, index, count, widths); + + if (!mHasCompatScaling) { + return native_getTextWidths(mNativePaint, text, index, count, widths); + } + final float oldSize = getTextSize(); + setTextSize(oldSize*mCompatScaling); + int res = native_getTextWidths(mNativePaint, text, index, count, widths); + setTextSize(oldSize); + for (int i=0; i widths.length) { throw new ArrayIndexOutOfBoundsException(); } - return native_getTextWidths(mNativePaint, text, start, end, widths); + + if (!mHasCompatScaling) { + return native_getTextWidths(mNativePaint, text, start, end, widths); + } + final float oldSize = getTextSize(); + setTextSize(oldSize*mCompatScaling); + int res = native_getTextWidths(mNativePaint, text, start, end, widths); + setTextSize(oldSize); + for (int i=0; i= 256"); + } + native_instance = nativeNewTable(table); + } + + private TableMaskFilter(int ni) { + native_instance = ni; + } + + public static TableMaskFilter CreateClipTable(int min, int max) { + return new TableMaskFilter(nativeNewClip(min, max)); + } + + public static TableMaskFilter CreateGammaTable(float gamma) { + return new TableMaskFilter(nativeNewGamma(gamma)); + } + + private static native int nativeNewTable(byte[] table); + private static native int nativeNewClip(int min, int max); + private static native int nativeNewGamma(float gamma); +} diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java index e40e84a..f0d5a6a 100644 --- a/graphics/java/android/graphics/Typeface.java +++ b/graphics/java/android/graphics/Typeface.java @@ -172,4 +172,16 @@ public class Typeface { private static native int nativeGetStyle(int native_instance); private static native int nativeCreateFromAsset(AssetManager mgr, String path); private static native int nativeCreateFromFile(String path); + + /** + * Set the global gamma coefficients for black and white text. This call is + * usually a no-op in shipping products, and only exists for testing during + * development. + * + * @param blackGamma gamma coefficient for black text + * @param whiteGamma gamma coefficient for white text + * + * @hide - this is just for calibrating devices, not for normal apps + */ + public static native void setGammaForText(float blackGamma, float whiteGamma); } diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java index ac96f20..58206d4 100644 --- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java @@ -45,11 +45,11 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac private boolean mRunning; public AnimatedRotateDrawable() { - this(null); + this(null, null); } - private AnimatedRotateDrawable(AnimatedRotateState rotateState) { - mState = new AnimatedRotateState(rotateState, this); + private AnimatedRotateDrawable(AnimatedRotateState rotateState, Resources res) { + mState = new AnimatedRotateState(rotateState, this, res); init(); } @@ -296,9 +296,14 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac private boolean mCanConstantState; private boolean mCheckedConstantState; - public AnimatedRotateState(AnimatedRotateState source, AnimatedRotateDrawable owner) { + public AnimatedRotateState(AnimatedRotateState source, AnimatedRotateDrawable owner, + Resources res) { if (source != null) { - mDrawable = source.mDrawable.getConstantState().newDrawable(); + if (res != null) { + mDrawable = source.mDrawable.getConstantState().newDrawable(res); + } else { + mDrawable = source.mDrawable.getConstantState().newDrawable(); + } mDrawable.setCallback(owner); mPivotXRel = source.mPivotXRel; mPivotX = source.mPivotX; @@ -312,7 +317,12 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac @Override public Drawable newDrawable() { - return new AnimatedRotateDrawable(this); + return new AnimatedRotateDrawable(this, null); + } + + @Override + public Drawable newDrawable(Resources res) { + return new AnimatedRotateDrawable(this, res); } @Override diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java index 68718c9..fdc4c92 100644 --- a/graphics/java/android/graphics/drawable/AnimationDrawable.java +++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java @@ -77,7 +77,7 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An private boolean mMutated; public AnimationDrawable() { - this(null); + this(null, null); } @Override @@ -297,8 +297,9 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An private int[] mDurations; private boolean mOneShot; - AnimationState(AnimationState orig, AnimationDrawable owner) { - super(orig, owner); + AnimationState(AnimationState orig, AnimationDrawable owner, + Resources res) { + super(orig, owner, res); if (orig != null) { mDurations = orig.mDurations; @@ -311,7 +312,12 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An @Override public Drawable newDrawable() { - return new AnimationDrawable(this); + return new AnimationDrawable(this, null); + } + + @Override + public Drawable newDrawable(Resources res) { + return new AnimationDrawable(this, res); } public void addFrame(Drawable dr, int dur) { @@ -330,8 +336,8 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An } } - private AnimationDrawable(AnimationState state) { - AnimationState as = new AnimationState(state, this); + private AnimationDrawable(AnimationState state, Resources res) { + AnimationState as = new AnimationState(state, this, res); mAnimationState = as; setConstantState(as); if (state != null) { diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java index eade73a..29e14d2 100644 --- a/graphics/java/android/graphics/drawable/BitmapDrawable.java +++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java @@ -56,18 +56,19 @@ import java.io.IOException; */ public class BitmapDrawable extends Drawable { - private static final int DEFAULT_PAINT_FLAGS = Paint.FILTER_BITMAP_FLAG; + private static final int DEFAULT_PAINT_FLAGS = + Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG; private BitmapState mBitmapState; private Bitmap mBitmap; + private int mTargetDensity; + private final Rect mDstRect = new Rect(); // Gravity.apply() sets this private boolean mApplyGravity; private boolean mRebuildShader; private boolean mMutated; - private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT; - - // These are scaled to match the target density. + // These are scaled to match the target density. private int mBitmapWidth; private int mBitmapHeight; @@ -76,6 +77,7 @@ public class BitmapDrawable extends Drawable { * @deprecated Use {@link #BitmapDrawable(Resources)} to ensure * that the drawable has correctly set its target density. */ + @Deprecated public BitmapDrawable() { mBitmapState = new BitmapState((Bitmap) null); } @@ -86,10 +88,7 @@ public class BitmapDrawable extends Drawable { */ public BitmapDrawable(Resources res) { mBitmapState = new BitmapState((Bitmap) null); - if (res != null) { - setTargetDensity(res.getDisplayMetrics()); - mBitmapState.mTargetDensity = mTargetDensity; - } + mBitmapState.mTargetDensity = mTargetDensity; } /** @@ -97,8 +96,9 @@ public class BitmapDrawable extends Drawable { * @deprecated Use {@link #BitmapDrawable(Resources, Bitmap)} to ensure * that the drawable has correctly set its target density. */ + @Deprecated public BitmapDrawable(Bitmap bitmap) { - this(new BitmapState(bitmap)); + this(new BitmapState(bitmap), null); } /** @@ -106,22 +106,53 @@ public class BitmapDrawable extends Drawable { * the display metrics of the resources. */ public BitmapDrawable(Resources res, Bitmap bitmap) { - this(new BitmapState(bitmap)); - if (res != null) { - setTargetDensity(res.getDisplayMetrics()); - mBitmapState.mTargetDensity = mTargetDensity; - } + this(new BitmapState(bitmap), res); + mBitmapState.mTargetDensity = mTargetDensity; } + /** + * Create a drawable by opening a given file path and decoding the bitmap. + * @deprecated Use {@link #BitmapDrawable(Resources, String)} to ensure + * that the drawable has correctly set its target density. + */ + @Deprecated public BitmapDrawable(String filepath) { - this(new BitmapState(BitmapFactory.decodeFile(filepath))); + this(new BitmapState(BitmapFactory.decodeFile(filepath)), null); + if (mBitmap == null) { + android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath); + } + } + + /** + * Create a drawable by opening a given file path and decoding the bitmap. + */ + public BitmapDrawable(Resources res, String filepath) { + this(new BitmapState(BitmapFactory.decodeFile(filepath)), null); + mBitmapState.mTargetDensity = mTargetDensity; if (mBitmap == null) { android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath); } } + /** + * Create a drawable by decoding a bitmap from the given input stream. + * @deprecated Use {@link #BitmapDrawable(Resources, java.io.InputStream)} to ensure + * that the drawable has correctly set its target density. + */ + @Deprecated public BitmapDrawable(java.io.InputStream is) { - this(new BitmapState(BitmapFactory.decodeStream(is))); + this(new BitmapState(BitmapFactory.decodeStream(is)), null); + if (mBitmap == null) { + android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is); + } + } + + /** + * Create a drawable by decoding a bitmap from the given input stream. + */ + public BitmapDrawable(Resources res, java.io.InputStream is) { + this(new BitmapState(BitmapFactory.decodeStream(is)), null); + mBitmapState.mTargetDensity = mTargetDensity; if (mBitmap == null) { android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is); } @@ -242,7 +273,8 @@ public class BitmapDrawable extends Drawable { public void setTileModeXY(Shader.TileMode xmode, Shader.TileMode ymode) { final BitmapState state = mBitmapState; - if (state.mTileModeX != xmode || state.mTileModeY != ymode) { + if (state.mPaint.getShader() == null || + state.mTileModeX != xmode || state.mTileModeY != ymode) { state.mTileModeX = xmode; state.mTileModeY = ymode; mRebuildShader = true; @@ -422,7 +454,12 @@ public class BitmapDrawable extends Drawable { @Override public Drawable newDrawable() { - return new BitmapDrawable(this); + return new BitmapDrawable(this, null); + } + + @Override + public Drawable newDrawable(Resources res) { + return new BitmapDrawable(this, res); } @Override @@ -431,9 +468,15 @@ public class BitmapDrawable extends Drawable { } } - private BitmapDrawable(BitmapState state) { + private BitmapDrawable(BitmapState state, Resources res) { mBitmapState = state; - mTargetDensity = state.mTargetDensity; + if (res != null) { + mTargetDensity = res.getDisplayMetrics().densityDpi; + } else if (state != null) { + mTargetDensity = state.mTargetDensity; + } else { + mTargetDensity = DisplayMetrics.DENSITY_DEFAULT; + } setBitmap(state.mBitmap); } } diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java index 95d4dd0..c387a9b 100644 --- a/graphics/java/android/graphics/drawable/ClipDrawable.java +++ b/graphics/java/android/graphics/drawable/ClipDrawable.java @@ -48,14 +48,14 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { public static final int VERTICAL = 2; ClipDrawable() { - this(null); + this(null, null); } /** * @param orientation Bitwise-or of {@link #HORIZONTAL} and/or {@link #VERTICAL} */ public ClipDrawable(Drawable drawable, int gravity, int orientation) { - this(null); + this(null, null); mClipState.mDrawable = drawable; mClipState.mGravity = gravity; @@ -241,9 +241,13 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { private boolean mCheckedConstantState; private boolean mCanConstantState; - ClipState(ClipState orig, ClipDrawable owner) { + ClipState(ClipState orig, ClipDrawable owner, Resources res) { if (orig != null) { - mDrawable = orig.mDrawable.getConstantState().newDrawable(); + if (res != null) { + mDrawable = orig.mDrawable.getConstantState().newDrawable(res); + } else { + mDrawable = orig.mDrawable.getConstantState().newDrawable(); + } mDrawable.setCallback(owner); mOrientation = orig.mOrientation; mGravity = orig.mGravity; @@ -253,7 +257,12 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { @Override public Drawable newDrawable() { - return new ClipDrawable(this); + return new ClipDrawable(this, null); + } + + @Override + public Drawable newDrawable(Resources res) { + return new ClipDrawable(this, res); } @Override @@ -271,8 +280,8 @@ public class ClipDrawable extends Drawable implements Drawable.Callback { } } - private ClipDrawable(ClipState state) { - mClipState = new ClipState(state, this); + private ClipDrawable(ClipState state, Resources res) { + mClipState = new ClipState(state, this, res); } } diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java index 226cc04..604c602 100644 --- a/graphics/java/android/graphics/drawable/ColorDrawable.java +++ b/graphics/java/android/graphics/drawable/ColorDrawable.java @@ -146,6 +146,11 @@ public class ColorDrawable extends Drawable { } @Override + public Drawable newDrawable(Resources res) { + return new ColorDrawable(this); + } + + @Override public int getChangingConfigurations() { return mChangingConfigurations; } diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java index 0a0e4eb..6a7b2d1 100644 --- a/graphics/java/android/graphics/drawable/Drawable.java +++ b/graphics/java/android/graphics/drawable/Drawable.java @@ -102,7 +102,7 @@ public abstract class Drawable { private int[] mStateSet = StateSet.WILD_CARD; private int mLevel = 0; private int mChangingConfigurations = 0; - private Rect mBounds = ZERO_BOUNDS_RECT; + private Rect mBounds = ZERO_BOUNDS_RECT; // lazily becomes a new Rect() /*package*/ Callback mCallback = null; private boolean mVisible = true; @@ -654,7 +654,7 @@ public abstract class Drawable { * Create a drawable from an inputstream */ public static Drawable createFromStream(InputStream is, String srcName) { - return createFromResourceStream(null, null, is, srcName); + return createFromResourceStream(null, null, is, srcName, null); } /** @@ -663,6 +663,15 @@ public abstract class Drawable { */ public static Drawable createFromResourceStream(Resources res, TypedValue value, InputStream is, String srcName) { + return createFromResourceStream(res, value, is, srcName, null); + } + + /** + * Create a drawable from an inputstream, using the given resources and + * value to determine density information. + */ + public static Drawable createFromResourceStream(Resources res, TypedValue value, + InputStream is, String srcName, BitmapFactory.Options opts) { if (is == null) { return null; @@ -683,7 +692,7 @@ public abstract class Drawable { // an application in compatibility mode, without scaling those down // to the compatibility density only to have them scaled back up when // drawn to the screen. - BitmapFactory.Options opts = new BitmapFactory.Options(); + if (opts == null) opts = new BitmapFactory.Options(); opts.inScreenDensity = DisplayMetrics.DENSITY_DEVICE; Bitmap bm = BitmapFactory.decodeResourceStream(res, value, is, pad, opts); if (bm != null) { @@ -813,7 +822,26 @@ public abstract class Drawable { } public static abstract class ConstantState { + /** + * Create a new drawable without supplying resources the caller + * is running in. Note that using this means the density-dependent + * drawables (like bitmaps) will not be able to update their target + * density correctly. + */ public abstract Drawable newDrawable(); + /** + * Create a new Drawable instance from its constant state. This + * must be implemented for drawables that change based on the target + * density of their caller (that is depending on whether it is + * in compatibility mode). + */ + public Drawable newDrawable(Resources res) { + return newDrawable(); + } + /** + * Return a bit mask of configuration changes that will impact + * this drawable (and thus require completely reloading it). + */ public abstract int getChangingConfigurations(); } diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index dc80cf5..c6f57d4 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -16,15 +16,26 @@ package android.graphics.drawable; +import android.content.res.Resources; import android.graphics.*; public class DrawableContainer extends Drawable implements Drawable.Callback { - + + /** + * To be proper, we should have a getter for dither (and alpha, etc.) + * so that proxy classes like this can save/restore their delegates' + * values, but we don't have getters. Since we do have setters + * (e.g. setDither), which this proxy forwards on, we have to have some + * default/initial setting. + * + * The initial setting for dither is now true, since it almost always seems + * to improve the quality at negligible cost. + */ + private static final boolean DEFAULT_DITHER = true; private DrawableContainerState mDrawableContainerState; private Drawable mCurrDrawable; private int mAlpha = 0xFF; private ColorFilter mColorFilter; - private boolean mDither; private int mCurIndex = -1; private boolean mMutated; @@ -71,10 +82,10 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { @Override public void setDither(boolean dither) { - if (mDither != dither) { - mDither = dither; + if (mDrawableContainerState.mDither != dither) { + mDrawableContainerState.mDither = dither; if (mCurrDrawable != null) { - mCurrDrawable.setDither(mDither); + mCurrDrawable.setDither(mDrawableContainerState.mDither); } } } @@ -200,7 +211,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { if (d != null) { d.setVisible(isVisible(), true); d.setAlpha(mAlpha); - d.setDither(mDither); + d.setDither(mDrawableContainerState.mDither); d.setColorFilter(mColorFilter); d.setState(getState()); d.setLevel(getLevel()); @@ -237,7 +248,7 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { final int N = mDrawableContainerState.getChildCount(); final Drawable[] drawables = mDrawableContainerState.getChildren(); for (int i = 0; i < N; i++) { - drawables[i].mutate(); + if (drawables[i] != null) drawables[i].mutate(); } mMutated = true; } @@ -273,8 +284,11 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { boolean mCanConstantState; boolean mPaddingChecked = false; + + boolean mDither = DEFAULT_DITHER; - DrawableContainerState(DrawableContainerState orig, DrawableContainer owner) { + DrawableContainerState(DrawableContainerState orig, DrawableContainer owner, + Resources res) { mOwner = owner; if (orig != null) { @@ -288,7 +302,11 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { final int N = mNumChildren; for (int i=0; i r) { + rad = r; + } canvas.drawRoundRect(mRect, rad, rad, mFillPaint); if (haveStroke) { canvas.drawRoundRect(mRect, rad, rad, mStrokePaint); @@ -917,6 +926,11 @@ public class GradientDrawable extends Drawable { } @Override + public Drawable newDrawable(Resources res) { + return new GradientDrawable(this); + } + + @Override public int getChangingConfigurations() { return mChangingConfigurations; } diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java index 6047726..4fa9d44 100644 --- a/graphics/java/android/graphics/drawable/InsetDrawable.java +++ b/graphics/java/android/graphics/drawable/InsetDrawable.java @@ -49,7 +49,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback private boolean mMutated; /*package*/ InsetDrawable() { - this(null); + this(null, null); } public InsetDrawable(Drawable drawable, int inset) { @@ -58,7 +58,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback public InsetDrawable(Drawable drawable, int insetLeft, int insetTop, int insetRight, int insetBottom) { - this(null); + this(null, null); mInsetState.mDrawable = drawable; mInsetState.mInsetLeft = insetLeft; @@ -263,9 +263,13 @@ public class InsetDrawable extends Drawable implements Drawable.Callback boolean mCheckedConstantState; boolean mCanConstantState; - InsetState(InsetState orig, InsetDrawable owner) { + InsetState(InsetState orig, InsetDrawable owner, Resources res) { if (orig != null) { - mDrawable = orig.mDrawable.getConstantState().newDrawable(); + if (res != null) { + mDrawable = orig.mDrawable.getConstantState().newDrawable(res); + } else { + mDrawable = orig.mDrawable.getConstantState().newDrawable(); + } mDrawable.setCallback(owner); mInsetLeft = orig.mInsetLeft; mInsetTop = orig.mInsetTop; @@ -277,7 +281,12 @@ public class InsetDrawable extends Drawable implements Drawable.Callback @Override public Drawable newDrawable() { - return new InsetDrawable(this); + return new InsetDrawable(this, null); + } + + @Override + public Drawable newDrawable(Resources res) { + return new InsetDrawable(this, res); } @Override @@ -295,8 +304,8 @@ public class InsetDrawable extends Drawable implements Drawable.Callback } } - private InsetDrawable(InsetState state) { - mInsetState = new InsetState(state, this); + private InsetDrawable(InsetState state, Resources res) { + mInsetState = new InsetState(state, this, res); } } diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java index c777205..389fd40 100644 --- a/graphics/java/android/graphics/drawable/LayerDrawable.java +++ b/graphics/java/android/graphics/drawable/LayerDrawable.java @@ -70,7 +70,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { * @param state The constant drawable state. */ LayerDrawable(Drawable[] layers, LayerState state) { - this(state); + this(state, null); int length = layers.length; ChildDrawable[] r = new ChildDrawable[length]; @@ -87,19 +87,19 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { } LayerDrawable() { - this((LayerState) null); + this((LayerState) null, null); } - LayerDrawable(LayerState state) { - LayerState as = createConstantState(state); + LayerDrawable(LayerState state, Resources res) { + LayerState as = createConstantState(state, res); mLayerState = as; if (as.mNum > 0) { ensurePadding(); } } - LayerState createConstantState(LayerState state) { - return new LayerState(state, this); + LayerState createConstantState(LayerState state, Resources res) { + return new LayerState(state, this, res); } @Override @@ -563,7 +563,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { private boolean mCheckedConstantState; private boolean mCanConstantState; - LayerState(LayerState orig, LayerDrawable owner) { + LayerState(LayerState orig, LayerDrawable owner, Resources res) { if (orig != null) { final ChildDrawable[] origChildDrawable = orig.mChildren; final int N = orig.mNum; @@ -577,7 +577,11 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { for (int i = 0; i < N; i++) { final ChildDrawable r = mChildren[i] = new ChildDrawable(); final ChildDrawable or = origChildDrawable[i]; - r.mDrawable = or.mDrawable.getConstantState().newDrawable(); + if (res != null) { + r.mDrawable = or.mDrawable.getConstantState().newDrawable(res); + } else { + r.mDrawable = or.mDrawable.getConstantState().newDrawable(); + } r.mDrawable.setCallback(owner); r.mInsetL = or.mInsetL; r.mInsetT = or.mInsetT; @@ -599,7 +603,12 @@ public class LayerDrawable extends Drawable implements Drawable.Callback { @Override public Drawable newDrawable() { - return new LayerDrawable(this); + return new LayerDrawable(this, null); + } + + @Override + public Drawable newDrawable(Resources res) { + return new LayerDrawable(this, res); } @Override diff --git a/graphics/java/android/graphics/drawable/LevelListDrawable.java b/graphics/java/android/graphics/drawable/LevelListDrawable.java index 7ae649f..ae8f224 100644 --- a/graphics/java/android/graphics/drawable/LevelListDrawable.java +++ b/graphics/java/android/graphics/drawable/LevelListDrawable.java @@ -57,7 +57,7 @@ public class LevelListDrawable extends DrawableContainer { private boolean mMutated; public LevelListDrawable() { - this(null); + this(null, null); } public void addLevel(int low, int high, Drawable drawable) { @@ -154,8 +154,8 @@ public class LevelListDrawable extends DrawableContainer { private int[] mLows; private int[] mHighs; - LevelListState(LevelListState orig, LevelListDrawable owner) { - super(orig, owner); + LevelListState(LevelListState orig, LevelListDrawable owner, Resources res) { + super(orig, owner, res); if (orig != null) { mLows = orig.mLows; @@ -186,7 +186,12 @@ public class LevelListDrawable extends DrawableContainer { @Override public Drawable newDrawable() { - return new LevelListDrawable(this); + return new LevelListDrawable(this, null); + } + + @Override + public Drawable newDrawable(Resources res) { + return new LevelListDrawable(this, res); } @Override @@ -201,8 +206,8 @@ public class LevelListDrawable extends DrawableContainer { } } - private LevelListDrawable(LevelListState state) { - LevelListState as = new LevelListState(state, this); + private LevelListDrawable(LevelListState state, Resources res) { + LevelListState as = new LevelListState(state, this, res); mLevelListState = as; setConstantState(as); onLevelChange(getLevel()); diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java index d5c8a08..67a8015 100644 --- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java +++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java @@ -21,6 +21,7 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.util.AttributeSet; import android.util.DisplayMetrics; +import android.util.Log; import android.util.TypedValue; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; @@ -36,6 +37,8 @@ import java.io.InputStream; * */ public class NinePatchDrawable extends Drawable { + // dithering helps a lot, and is pretty cheap, so default is true + private static final boolean DEFAULT_DITHER = true; private NinePatchState mNinePatchState; private NinePatch mNinePatch; private Rect mPadding; @@ -56,8 +59,9 @@ public class NinePatchDrawable extends Drawable { * @deprecated Use {@link #NinePatchDrawable(Resources, Bitmap, byte[], Rect, String)} * to ensure that the drawable has correctly set its target density. */ + @Deprecated public NinePatchDrawable(Bitmap bitmap, byte[] chunk, Rect padding, String srcName) { - this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding)); + this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), null); } /** @@ -66,11 +70,8 @@ public class NinePatchDrawable extends Drawable { */ public NinePatchDrawable(Resources res, Bitmap bitmap, byte[] chunk, Rect padding, String srcName) { - this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding)); - if (res != null) { - setTargetDensity(res.getDisplayMetrics()); - mNinePatchState.mTargetDensity = mTargetDensity; - } + this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), res); + mNinePatchState.mTargetDensity = mTargetDensity; } /** @@ -78,8 +79,9 @@ public class NinePatchDrawable extends Drawable { * @deprecated Use {@link #NinePatchDrawable(Resources, NinePatch)} * to ensure that the drawable has correctly set its target density. */ + @Deprecated public NinePatchDrawable(NinePatch patch) { - this(new NinePatchState(patch, null)); + this(new NinePatchState(patch, null), null); } /** @@ -87,19 +89,21 @@ public class NinePatchDrawable extends Drawable { * based on the display metrics of the resources. */ public NinePatchDrawable(Resources res, NinePatch patch) { - this(new NinePatchState(patch, null)); - if (res != null) { - setTargetDensity(res.getDisplayMetrics()); - mNinePatchState.mTargetDensity = mTargetDensity; - } + this(new NinePatchState(patch, null), res); + mNinePatchState.mTargetDensity = mTargetDensity; } - private void setNinePatchState(NinePatchState state) { + private void setNinePatchState(NinePatchState state, Resources res) { mNinePatchState = state; mNinePatch = state.mNinePatch; mPadding = state.mPadding; - mTargetDensity = state.mTargetDensity; - if (state.mDither) setDither(state.mDither); + mTargetDensity = res != null ? res.getDisplayMetrics().densityDpi + : state.mTargetDensity; + if (DEFAULT_DITHER != state.mDither) { + // avoid calling the setter unless we need to, since it does a + // lazy allocation of a paint + setDither(state.mDither); + } if (mNinePatch != null) { computeBitmapSize(); } @@ -152,16 +156,35 @@ public class NinePatchDrawable extends Drawable { private void computeBitmapSize() { final int sdensity = mNinePatch.getDensity(); final int tdensity = mTargetDensity; - mBitmapWidth = Bitmap.scaleFromDensity(mNinePatch.getWidth(), - sdensity, tdensity); - mBitmapHeight = Bitmap.scaleFromDensity(mNinePatch.getHeight(), - sdensity, tdensity); + if (sdensity == tdensity) { + mBitmapWidth = mNinePatch.getWidth(); + mBitmapHeight = mNinePatch.getHeight(); + } else { + mBitmapWidth = Bitmap.scaleFromDensity(mNinePatch.getWidth(), + sdensity, tdensity); + mBitmapHeight = Bitmap.scaleFromDensity(mNinePatch.getHeight(), + sdensity, tdensity); + Rect dest = mPadding; + Rect src = mNinePatchState.mPadding; + if (dest == src) { + mPadding = dest = new Rect(src); + } + dest.left = Bitmap.scaleFromDensity(src.left, sdensity, tdensity); + dest.top = Bitmap.scaleFromDensity(src.top, sdensity, tdensity); + dest.right = Bitmap.scaleFromDensity(src.right, sdensity, tdensity); + dest.bottom = Bitmap.scaleFromDensity(src.bottom, sdensity, tdensity); + } } // overrides @Override public void draw(Canvas canvas) { + if (false) { + float[] pts = new float[2]; + canvas.getMatrix().mapPoints(pts); + Log.v("9patch", "Drawing 9-patch @ " + pts[0] + "," + pts[1] + ": " + getBounds()); + } mNinePatch.draw(canvas, getBounds(), mPaint); } @@ -192,6 +215,14 @@ public class NinePatchDrawable extends Drawable { } @Override + public void setFilterBitmap(boolean filter) { + // at the moment, we see no quality improvement, but a big slowdown + // with filtering, so ignore this call for now + // + //getPaint().setFilterBitmap(filter); + } + + @Override public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs) throws XmlPullParserException, IOException { super.inflate(r, parser, attrs); @@ -205,7 +236,8 @@ public class NinePatchDrawable extends Drawable { } final boolean dither = a.getBoolean( - com.android.internal.R.styleable.NinePatchDrawable_dither, false); + com.android.internal.R.styleable.NinePatchDrawable_dither, + DEFAULT_DITHER); final BitmapFactory.Options options = new BitmapFactory.Options(); if (dither) { options.inDither = false; @@ -235,16 +267,17 @@ public class NinePatchDrawable extends Drawable { } setNinePatchState(new NinePatchState( - new NinePatch(bitmap, bitmap.getNinePatchChunk(), "XML 9-patch"), padding, dither)); + new NinePatch(bitmap, bitmap.getNinePatchChunk(), "XML 9-patch"), + padding, dither), r); mNinePatchState.mTargetDensity = mTargetDensity; a.recycle(); } - public Paint getPaint() { if (mPaint == null) { mPaint = new Paint(); + mPaint.setDither(DEFAULT_DITHER); } return mPaint; } @@ -301,7 +334,6 @@ public class NinePatchDrawable extends Drawable { if (!mMutated && super.mutate() == this) { mNinePatchState = new NinePatchState(mNinePatchState); mNinePatch = mNinePatchState.mNinePatch; - mPadding = mNinePatchState.mPadding; mMutated = true; } return this; @@ -315,7 +347,7 @@ public class NinePatchDrawable extends Drawable { int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT; NinePatchState(NinePatch ninePatch, Rect padding) { - this(ninePatch, padding, false); + this(ninePatch, padding, DEFAULT_DITHER); } NinePatchState(NinePatch ninePatch, Rect rect, boolean dither) { @@ -326,7 +358,8 @@ public class NinePatchDrawable extends Drawable { NinePatchState(NinePatchState state) { mNinePatch = new NinePatch(state.mNinePatch); - mPadding = new Rect(state.mPadding); + // Note we don't copy the padding because it is immutable. + mPadding = state.mPadding; mDither = state.mDither; mChangingConfigurations = state.mChangingConfigurations; mTargetDensity = state.mTargetDensity; @@ -334,7 +367,12 @@ public class NinePatchDrawable extends Drawable { @Override public Drawable newDrawable() { - return new NinePatchDrawable(this); + return new NinePatchDrawable(this, null); + } + + @Override + public Drawable newDrawable(Resources res) { + return new NinePatchDrawable(this, res); } @Override @@ -343,8 +381,7 @@ public class NinePatchDrawable extends Drawable { } } - private NinePatchDrawable(NinePatchState state) { - setNinePatchState(state); + private NinePatchDrawable(NinePatchState state, Resources res) { + setNinePatchState(state, res); } } - diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java index cb16cb7..c4a7822 100644 --- a/graphics/java/android/graphics/drawable/RotateDrawable.java +++ b/graphics/java/android/graphics/drawable/RotateDrawable.java @@ -54,7 +54,7 @@ public class RotateDrawable extends Drawable implements Drawable.Callback { *

Create a new rotating drawable with an empty state.

*/ public RotateDrawable() { - this(null); + this(null, null); } /** @@ -64,8 +64,8 @@ public class RotateDrawable extends Drawable implements Drawable.Callback { * * @param rotateState the state for this drawable */ - private RotateDrawable(RotateState rotateState) { - mState = new RotateState(rotateState, this); + private RotateDrawable(RotateState rotateState, Resources res) { + mState = new RotateState(rotateState, this, res); } public void draw(Canvas canvas) { @@ -291,9 +291,13 @@ public class RotateDrawable extends Drawable implements Drawable.Callback { private boolean mCanConstantState; private boolean mCheckedConstantState; - public RotateState(RotateState source, RotateDrawable owner) { + public RotateState(RotateState source, RotateDrawable owner, Resources res) { if (source != null) { - mDrawable = source.mDrawable.getConstantState().newDrawable(); + if (res != null) { + mDrawable = source.mDrawable.getConstantState().newDrawable(res); + } else { + mDrawable = source.mDrawable.getConstantState().newDrawable(); + } mDrawable.setCallback(owner); mPivotXRel = source.mPivotXRel; mPivotX = source.mPivotX; @@ -307,7 +311,12 @@ public class RotateDrawable extends Drawable implements Drawable.Callback { @Override public Drawable newDrawable() { - return new RotateDrawable(this); + return new RotateDrawable(this, null); + } + + @Override + public Drawable newDrawable(Resources res) { + return new RotateDrawable(this, res); } @Override diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java index 7125ab1..275e36f 100644 --- a/graphics/java/android/graphics/drawable/ScaleDrawable.java +++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java @@ -47,11 +47,11 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { private final Rect mTmpRect = new Rect(); ScaleDrawable() { - this(null); + this(null, null); } public ScaleDrawable(Drawable drawable, int gravity, float scaleWidth, float scaleHeight) { - this(null); + this(null, null); mScaleState.mDrawable = drawable; mScaleState.mGravity = gravity; @@ -260,9 +260,13 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { private boolean mCheckedConstantState; private boolean mCanConstantState; - ScaleState(ScaleState orig, ScaleDrawable owner) { + ScaleState(ScaleState orig, ScaleDrawable owner, Resources res) { if (orig != null) { - mDrawable = orig.mDrawable.getConstantState().newDrawable(); + if (res != null) { + mDrawable = orig.mDrawable.getConstantState().newDrawable(res); + } else { + mDrawable = orig.mDrawable.getConstantState().newDrawable(); + } mDrawable.setCallback(owner); mScaleWidth = orig.mScaleWidth; mScaleHeight = orig.mScaleHeight; @@ -273,7 +277,12 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { @Override public Drawable newDrawable() { - return new ScaleDrawable(this); + return new ScaleDrawable(this, null); + } + + @Override + public Drawable newDrawable(Resources res) { + return new ScaleDrawable(this, res); } @Override @@ -291,8 +300,8 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback { } } - private ScaleDrawable(ScaleState state) { - mScaleState = new ScaleState(state, this); + private ScaleDrawable(ScaleState state, Resources res) { + mScaleState = new ScaleState(state, this, res); } } diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java index 6677a35..c699a82 100644 --- a/graphics/java/android/graphics/drawable/ShapeDrawable.java +++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java @@ -396,6 +396,11 @@ public class ShapeDrawable extends Drawable { } @Override + public Drawable newDrawable(Resources res) { + return new ShapeDrawable(this); + } + + @Override public int getChangingConfigurations() { return mChangingConfigurations; } diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java index d22a4ba..b1d588e 100644 --- a/graphics/java/android/graphics/drawable/StateListDrawable.java +++ b/graphics/java/android/graphics/drawable/StateListDrawable.java @@ -50,11 +50,22 @@ import android.util.StateSet; * @attr ref android.R.styleable#DrawableStates_state_pressed */ public class StateListDrawable extends DrawableContainer { + /** + * To be proper, we should have a getter for dither (and alpha, etc.) + * so that proxy classes like this can save/restore their delegates' + * values, but we don't have getters. Since we do have setters + * (e.g. setDither), which this proxy forwards on, we have to have some + * default/initial setting. + * + * The initial setting for dither is now true, since it almost always seems + * to improve the quality at negligible cost. + */ + private static final boolean DEFAULT_DITHER = true; private final StateListState mStateListState; private boolean mMutated; public StateListDrawable() { - this(null); + this(null, null); } /** @@ -105,6 +116,9 @@ public class StateListDrawable extends DrawableContainer { mStateListState.setConstantSize(a.getBoolean( com.android.internal.R.styleable.StateListDrawable_constantSize, false)); + setDither(a.getBoolean(com.android.internal.R.styleable.StateListDrawable_dither, + DEFAULT_DITHER)); + a.recycle(); int type; @@ -234,8 +248,8 @@ public class StateListDrawable extends DrawableContainer { static final class StateListState extends DrawableContainerState { private int[][] mStateSets; - StateListState(StateListState orig, StateListDrawable owner) { - super(orig, owner); + StateListState(StateListState orig, StateListDrawable owner, Resources res) { + super(orig, owner, res); if (orig != null) { mStateSets = orig.mStateSets; @@ -263,7 +277,12 @@ public class StateListDrawable extends DrawableContainer { @Override public Drawable newDrawable() { - return new StateListDrawable(this); + return new StateListDrawable(this, null); + } + + @Override + public Drawable newDrawable(Resources res) { + return new StateListDrawable(this, res); } @Override @@ -275,8 +294,8 @@ public class StateListDrawable extends DrawableContainer { } } - private StateListDrawable(StateListState state) { - StateListState as = new StateListState(state, this); + private StateListDrawable(StateListState state, Resources res) { + StateListState as = new StateListState(state, this, res); mStateListState = as; setConstantState(as); onStateChange(getState()); diff --git a/graphics/java/android/graphics/drawable/TransitionDrawable.java b/graphics/java/android/graphics/drawable/TransitionDrawable.java index 358f889..97b45d8 100644 --- a/graphics/java/android/graphics/drawable/TransitionDrawable.java +++ b/graphics/java/android/graphics/drawable/TransitionDrawable.java @@ -16,6 +16,7 @@ package android.graphics.drawable; +import android.content.res.Resources; import android.graphics.Canvas; import android.os.SystemClock; @@ -72,7 +73,7 @@ public class TransitionDrawable extends LayerDrawable implements Drawable.Callba * 2 layers are required for this drawable to work properly. */ public TransitionDrawable(Drawable[] layers) { - this(new TransitionState(null, null), layers); + this(new TransitionState(null, null, null), layers); } /** @@ -82,11 +83,11 @@ public class TransitionDrawable extends LayerDrawable implements Drawable.Callba * @see #TransitionDrawable(Drawable[]) */ TransitionDrawable() { - this(new TransitionState(null, null)); + this(new TransitionState(null, null, null), (Resources)null); } - private TransitionDrawable(TransitionState state) { - super(state); + private TransitionDrawable(TransitionState state, Resources res) { + super(state, res); } private TransitionDrawable(TransitionState state, Drawable[] layers) { @@ -94,8 +95,8 @@ public class TransitionDrawable extends LayerDrawable implements Drawable.Callba } @Override - LayerState createConstantState(LayerState state) { - return new TransitionState((TransitionState) state, this); + LayerState createConstantState(LayerState state, Resources res) { + return new TransitionState((TransitionState) state, this, res); } /** @@ -229,13 +230,19 @@ public class TransitionDrawable extends LayerDrawable implements Drawable.Callba } static class TransitionState extends LayerState { - TransitionState(TransitionState orig, TransitionDrawable owner) { - super(orig, owner); + TransitionState(TransitionState orig, TransitionDrawable owner, + Resources res) { + super(orig, owner, res); } @Override public Drawable newDrawable() { - return new TransitionDrawable(this); + return new TransitionDrawable(this, (Resources)null); + } + + @Override + public Drawable newDrawable(Resources res) { + return new TransitionDrawable(this, res); } @Override diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java new file mode 100644 index 0000000..957f2dd --- /dev/null +++ b/graphics/java/android/renderscript/Allocation.java @@ -0,0 +1,276 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +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; +import android.graphics.BitmapFactory; +import android.util.Log; +import android.util.TypedValue; + +/** + * @hide + * + **/ +public class Allocation extends BaseObj { + Type mType; + + Allocation(int id, RenderScript rs, Type t) { + super(rs); + mID = id; + mType = t; + } + + public void uploadToTexture(int baseMipLevel) { + mRS.nAllocationUploadToTexture(mID, baseMipLevel); + } + + public void uploadToBufferObject() { + mRS.nAllocationUploadToBufferObject(mID); + } + + public void data(int[] d) { + subData1D(0, mType.getElementCount(), d); + } + public void data(short[] d) { + subData1D(0, mType.getElementCount(), d); + } + public void data(byte[] d) { + subData1D(0, mType.getElementCount(), d); + } + public void data(float[] d) { + subData1D(0, mType.getElementCount(), d); + } + + private void data1DChecks(int off, int count, int len, int dataSize) { + if((off < 0) || (count < 1) || ((off + count) > mType.getElementCount())) { + throw new IllegalArgumentException("Offset or Count out of bounds."); + } + if((len) < dataSize) { + throw new IllegalArgumentException("Array too small for allocation type."); + } + } + + public void subData1D(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); + } + public void subData1D(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); + } + public void subData1D(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); + } + public void subData1D(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); + } + + + + public void subData2D(int xoff, int yoff, int w, int h, int[] d) { + mRS.nAllocationSubData2D(mID, xoff, yoff, w, h, d, d.length * 4); + } + + public void subData2D(int xoff, int yoff, int w, int h, float[] d) { + mRS.nAllocationSubData2D(mID, xoff, yoff, w, h, d, d.length * 4); + } + + public void readData(int[] d) { + mRS.nAllocationRead(mID, d); + } + + public void readData(float[] d) { + mRS.nAllocationRead(mID, d); + } + + public void data(Object o) { + mRS.nAllocationSubDataFromObject(mID, mType, 0, o); + } + + public void read(Object o) { + mRS.nAllocationSubReadFromObject(mID, mType, 0, o); + } + + public void subData(int offset, Object o) { + mRS.nAllocationSubDataFromObject(mID, mType, offset, o); + } + + public class Adapter1D extends BaseObj { + Adapter1D(int id, RenderScript rs) { + super(rs); + mID = id; + } + + public void setConstraint(Dimension dim, int value) { + mRS.nAdapter1DSetConstraint(mID, dim.mID, value); + } + + public void data(int[] d) { + mRS.nAdapter1DData(mID, d); + } + + public void data(float[] d) { + mRS.nAdapter1DData(mID, d); + } + + public void subData(int off, int count, int[] d) { + mRS.nAdapter1DSubData(mID, off, count, d); + } + + public void subData(int off, int count, float[] d) { + mRS.nAdapter1DSubData(mID, off, count, d); + } + } + + public Adapter1D createAdapter1D() { + int id = mRS.nAdapter1DCreate(); + if (id != 0) { + mRS.nAdapter1DBindAllocation(id, mID); + } + return new Adapter1D(id, mRS); + } + + + public class Adapter2D extends BaseObj { + Adapter2D(int id, RenderScript rs) { + super(rs); + mID = id; + } + + public void setConstraint(Dimension dim, int value) { + mRS.nAdapter2DSetConstraint(mID, dim.mID, value); + } + + public void data(int[] d) { + mRS.nAdapter2DData(mID, d); + } + + public void data(float[] d) { + mRS.nAdapter2DData(mID, d); + } + + public void subData(int xoff, int yoff, int w, int h, int[] d) { + mRS.nAdapter2DSubData(mID, xoff, yoff, w, h, d); + } + + public void subData(int xoff, int yoff, int w, int h, float[] d) { + mRS.nAdapter2DSubData(mID, xoff, yoff, w, h, d); + } + } + + public Adapter2D createAdapter2D() { + int id = mRS.nAdapter2DCreate(); + if (id != 0) { + mRS.nAdapter2DBindAllocation(id, mID); + } + return new Adapter2D(id, mRS); + } + + + // creation + + private static BitmapFactory.Options mBitmapOptions = new BitmapFactory.Options(); + static { + mBitmapOptions.inScaled = false; + } + + static public Allocation createTyped(RenderScript rs, Type type) + throws IllegalArgumentException { + + if(type.mID == 0) { + throw new IllegalStateException("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 { + + Type.Builder b = new Type.Builder(rs, e); + b.add(Dimension.X, count); + Type t = b.create(); + + int id = rs.nAllocationCreateTyped(t.mID); + if(id == 0) { + throw new IllegalStateException("Bad element."); + } + return new Allocation(id, rs, t); + } + + static public Allocation createFromBitmap(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips) + throws IllegalArgumentException { + + int id = rs.nAllocationCreateFromBitmap(dstFmt.mID, genMips, b); + return new Allocation(id, rs, null); + } + + static public Allocation createFromBitmapBoxed(RenderScript rs, Bitmap b, Element dstFmt, boolean genMips) + throws IllegalArgumentException { + + int id = rs.nAllocationCreateFromBitmapBoxed(dstFmt.mID, genMips, b); + return new Allocation(id, rs, null); + } + + static public Allocation createFromBitmapResource(RenderScript rs, Resources res, int id, Element dstFmt, boolean genMips) + throws IllegalArgumentException { + + InputStream is = 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); + + return new Allocation(allocationId, rs, null); + } catch (Exception e) { + // Ignore + } finally { + if (is != null) { + try { + is.close(); + } catch (IOException e) { + // Ignore + } + } + } + + return null; + } + + static public Allocation createFromBitmapResourceBoxed(RenderScript rs, Resources res, int id, Element dstFmt, boolean genMips) + throws IllegalArgumentException { + + Bitmap b = BitmapFactory.decodeResource(res, id, mBitmapOptions); + return createFromBitmapBoxed(rs, b, dstFmt, genMips); + } +} + + diff --git a/graphics/java/android/renderscript/BaseObj.java b/graphics/java/android/renderscript/BaseObj.java new file mode 100644 index 0000000..e802ec5 --- /dev/null +++ b/graphics/java/android/renderscript/BaseObj.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + +import android.util.Log; + +/** + * @hide + * + **/ +class BaseObj { + + BaseObj(RenderScript rs) { + mRS = rs; + mID = 0; + mDestroyed = false; + } + + public int getID() { + return mID; + } + + int mID; + boolean mDestroyed; + String mName; + RenderScript mRS; + + public void setName(String s) throws IllegalStateException, IllegalArgumentException + { + if(s.length() < 1) { + throw new IllegalArgumentException("setName does not accept a zero length string."); + } + if(mName != null) { + throw new IllegalArgumentException("setName object already has a name."); + } + + try { + byte[] bytes = s.getBytes("UTF-8"); + mRS.nAssignName(mID, bytes); + mName = s; + } catch (java.io.UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + protected void finalize() throws Throwable + { + if (!mDestroyed) { + if(mID != 0 && mRS.isAlive()) { + mRS.nObjDestroyOOB(mID); + } + mRS = null; + mID = 0; + mDestroyed = true; + //Log.v(RenderScript.LOG_TAG, getClass() + + // " auto finalizing object without having released the RS reference."); + } + super.finalize(); + } + + public void destroy() { + if(mDestroyed) { + throw new IllegalStateException("Object already destroyed."); + } + mDestroyed = true; + mRS.nObjDestroy(mID); + } + +} + diff --git a/graphics/java/android/renderscript/Dimension.java b/graphics/java/android/renderscript/Dimension.java new file mode 100644 index 0000000..f29057d --- /dev/null +++ b/graphics/java/android/renderscript/Dimension.java @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + +/** + * @hide + **/ +public enum Dimension { + X (0), + Y (1), + Z (2), + LOD (3), + FACE (4), + ARRAY_0 (100); + + int mID; + Dimension(int id) { + mID = id; + } +} + diff --git a/graphics/java/android/renderscript/Element.java b/graphics/java/android/renderscript/Element.java new file mode 100644 index 0000000..73d8266 --- /dev/null +++ b/graphics/java/android/renderscript/Element.java @@ -0,0 +1,494 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + +import java.lang.reflect.Field; + +/** + * @hide + * + **/ +public class Element extends BaseObj { + int mSize; + Entry[] mEntries; + + int getSizeBytes() { + return mSize; + } + int getComponentCount() { + return mEntries.length; + } + Element.DataType getComponentDataType(int num) { + return mEntries[num].mType; + } + Element.DataKind getComponentDataKind(int num) { + return mEntries[num].mKind; + } + boolean getComponentIsNormalized(int num) { + return mEntries[num].mIsNormalized; + } + int getComponentBits(int num) { + return mEntries[num].mBits; + } + String getComponentName(int num) { + return mEntries[num].mName; + } + + static class Entry { + //Element mElement; + Element.DataType mType; + Element.DataKind mKind; + boolean mIsNormalized; + int mBits; + String mName; + + //Entry(Element e, int bits) { + //mElement = e; + //int mBits = bits; + //} + + Entry(DataType dt, DataKind dk, boolean isNorm, int bits, String name) { + mType = dt; + mKind = dk; + mIsNormalized = isNorm; + mBits = bits; + mName = name; + } + } + + public static Element USER_U8(RenderScript rs) { + if(rs.mElement_USER_U8 == null) { + rs.mElement_USER_U8 = new Element(rs, 1); + rs.mElement_USER_U8.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.USER, false, 8, null); + rs.mElement_USER_U8.init(); + } + return rs.mElement_USER_U8; + } + + public static Element USER_I8(RenderScript rs) { + if(rs.mElement_USER_I8 == null) { + rs.mElement_USER_I8 = new Element(rs, 1); + rs.mElement_USER_I8.mEntries[0] = new Entry(DataType.SIGNED, DataKind.USER, false, 8, null); + rs.mElement_USER_I8.init(); + } + return rs.mElement_USER_I8; + } + + public static Element USER_U16(RenderScript rs) { + if(rs.mElement_USER_U16 == null) { + rs.mElement_USER_U16 = new Element(rs, 1); + rs.mElement_USER_U16.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.USER, false, 16, null); + rs.mElement_USER_U16.init(); + } + return rs.mElement_USER_U16; + } + + public static Element USER_I16(RenderScript rs) { + if(rs.mElement_USER_I16 == null) { + rs.mElement_USER_I16 = new Element(rs, 1); + rs.mElement_USER_I16.mEntries[0] = new Entry(DataType.SIGNED, DataKind.USER, false, 16, null); + rs.mElement_USER_I16.init(); + } + return rs.mElement_USER_I16; + } + + public static Element USER_U32(RenderScript rs) { + if(rs.mElement_USER_U32 == null) { + rs.mElement_USER_U32 = new Element(rs, 1); + rs.mElement_USER_U32.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.USER, false, 32, null); + rs.mElement_USER_U32.init(); + } + return rs.mElement_USER_U32; + } + + public static Element USER_I32(RenderScript rs) { + if(rs.mElement_USER_I32 == null) { + rs.mElement_USER_I32 = new Element(rs, 1); + rs.mElement_USER_I32.mEntries[0] = new Entry(DataType.SIGNED, DataKind.USER, false, 32, null); + rs.mElement_USER_I32.init(); + } + return rs.mElement_USER_I32; + } + + public static Element USER_F32(RenderScript rs) { + if(rs.mElement_USER_FLOAT == null) { + rs.mElement_USER_FLOAT = new Element(rs, 1); + rs.mElement_USER_FLOAT.mEntries[0] = new Entry(DataType.FLOAT, DataKind.USER, false, 32, null); + rs.mElement_USER_FLOAT.init(); + } + return rs.mElement_USER_FLOAT; + } + + public static Element A_8(RenderScript rs) { + if(rs.mElement_A_8 == null) { + rs.mElement_A_8 = new Element(rs, 1); + rs.mElement_A_8.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.ALPHA, true, 8, "a"); + rs.mElement_A_8.init(); + } + return rs.mElement_A_8; + } + + public static Element RGB_565(RenderScript rs) { + if(rs.mElement_RGB_565 == null) { + rs.mElement_RGB_565 = new Element(rs, 3); + rs.mElement_RGB_565.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.RED, true, 5, "r"); + rs.mElement_RGB_565.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.GREEN, true, 6, "g"); + rs.mElement_RGB_565.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.BLUE, true, 5, "b"); + rs.mElement_RGB_565.init(); + } + return rs.mElement_RGB_565; + } + + public static Element RGB_888(RenderScript rs) { + if(rs.mElement_RGB_888 == null) { + rs.mElement_RGB_888 = new Element(rs, 3); + rs.mElement_RGB_888.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.RED, true, 8, "r"); + rs.mElement_RGB_888.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.GREEN, true, 8, "g"); + rs.mElement_RGB_888.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.BLUE, true, 8, "b"); + rs.mElement_RGB_888.init(); + } + return rs.mElement_RGB_888; + } + + public static Element RGBA_5551(RenderScript rs) { + if(rs.mElement_RGBA_5551 == null) { + rs.mElement_RGBA_5551 = new Element(rs, 4); + rs.mElement_RGBA_5551.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.RED, true, 5, "r"); + rs.mElement_RGBA_5551.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.GREEN, true, 5, "g"); + rs.mElement_RGBA_5551.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.BLUE, true, 5, "b"); + rs.mElement_RGBA_5551.mEntries[3] = new Entry(DataType.UNSIGNED, DataKind.ALPHA, true, 1, "a"); + rs.mElement_RGBA_5551.init(); + } + return rs.mElement_RGBA_5551; + } + + public static Element RGBA_4444(RenderScript rs) { + if(rs.mElement_RGBA_4444 == null) { + rs.mElement_RGBA_4444 = new Element(rs, 4); + rs.mElement_RGBA_4444.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.RED, true, 4, "r"); + rs.mElement_RGBA_4444.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.GREEN, true, 4, "g"); + rs.mElement_RGBA_4444.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.BLUE, true, 4, "b"); + rs.mElement_RGBA_4444.mEntries[3] = new Entry(DataType.UNSIGNED, DataKind.ALPHA, true, 4, "a"); + rs.mElement_RGBA_4444.init(); + } + return rs.mElement_RGBA_4444; + } + + public static Element RGBA_8888(RenderScript rs) { + if(rs.mElement_RGBA_8888 == null) { + rs.mElement_RGBA_8888 = new Element(rs, 4); + rs.mElement_RGBA_8888.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.RED, true, 8, "r"); + rs.mElement_RGBA_8888.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.GREEN, true, 8, "g"); + rs.mElement_RGBA_8888.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.BLUE, true, 8, "b"); + rs.mElement_RGBA_8888.mEntries[3] = new Entry(DataType.UNSIGNED, DataKind.ALPHA, true, 8, "a"); + rs.mElement_RGBA_8888.init(); + } + return rs.mElement_RGBA_8888; + } + + public static Element INDEX_16(RenderScript rs) { + if(rs.mElement_INDEX_16 == null) { + rs.mElement_INDEX_16 = new Element(rs, 1); + rs.mElement_INDEX_16.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.INDEX, false, 16, "index"); + rs.mElement_INDEX_16.init(); + } + return rs.mElement_INDEX_16; + } + + public static Element XY_F32(RenderScript rs) { + if(rs.mElement_XY_F32 == null) { + rs.mElement_XY_F32 = new Element(rs, 2); + rs.mElement_XY_F32.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.X, false, 32, "x"); + rs.mElement_XY_F32.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.Y, false, 32, "y"); + rs.mElement_XY_F32.init(); + } + return rs.mElement_XY_F32; + } + + public static Element XYZ_F32(RenderScript rs) { + if(rs.mElement_XYZ_F32 == null) { + rs.mElement_XYZ_F32 = new Element(rs, 3); + rs.mElement_XYZ_F32.mEntries[0] = new Entry(DataType.UNSIGNED, DataKind.X, false, 32, "x"); + rs.mElement_XYZ_F32.mEntries[1] = new Entry(DataType.UNSIGNED, DataKind.Y, false, 32, "y"); + rs.mElement_XYZ_F32.mEntries[2] = new Entry(DataType.UNSIGNED, DataKind.Z, false, 32, "z"); + rs.mElement_XYZ_F32.init(); + } + return rs.mElement_XYZ_F32; + } + + static void initPredefined(RenderScript rs) { + rs.nInitElements(A_8(rs).mID, RGBA_4444(rs).mID, RGBA_8888(rs).mID, RGB_565(rs).mID); + } + + public enum DataType { + FLOAT (0), + UNSIGNED (1), + SIGNED (2); + + int mID; + DataType(int id) { + mID = id; + } + } + + public enum DataKind { + USER (0), + RED (1), + GREEN (2), + BLUE (3), + ALPHA (4), + LUMINANCE (5), + INTENSITY (6), + X (7), + Y (8), + Z (9), + W (10), + S (11), + T (12), + Q (13), + R (14), + NX (15), + NY (16), + NZ (17), + INDEX (18), + POINT_SIZE(19); + + int mID; + DataKind(int id) { + mID = id; + } + } + + Element(RenderScript rs, int count) { + super(rs); + mSize = 0; + mEntries = new Entry[count]; + } + + public void destroy() throws IllegalStateException { + super.destroy(); + } + + public static Element createFromClass(RenderScript rs, Class c) { + Field[] fields = c.getFields(); + Builder b = new Builder(rs); + + for(Field f: fields) { + Class fc = f.getType(); + if(fc == int.class) { + b.add(Element.DataType.SIGNED, Element.DataKind.USER, false, 32, f.getName()); + } else if(fc == short.class) { + b.add(Element.DataType.SIGNED, Element.DataKind.USER, false, 16, f.getName()); + } else if(fc == byte.class) { + b.add(Element.DataType.SIGNED, Element.DataKind.USER, false, 8, f.getName()); + } else if(fc == float.class) { + b.add(Element.DataType.FLOAT, Element.DataKind.USER, false, 32, f.getName()); + } else { + throw new IllegalArgumentException("Unkown field type"); + } + } + return b.create(); + } + + static synchronized void internalCreate(RenderScript rs, Element e) { + rs.nElementBegin(); + int bits = 0; + for (int ct=0; ct < e.mEntries.length; ct++) { + Entry en = e.mEntries[ct]; + //if(en.mElement != null) { + //rs.nElementAdd(en.mElement.mID); + //} else + { + rs.nElementAdd(en.mKind.mID, en.mType.mID, en.mIsNormalized, en.mBits, en.mName); + bits += en.mBits; + } + } + e.mID = rs.nElementCreate(); + e.mSize = (bits + 7) >> 3; + } + + void init() { + internalCreate(mRS, this); + } + + + public static class Builder { + RenderScript mRS; + Entry[] mEntries; + int mEntryCount; + + public Builder(RenderScript rs) { + mRS = rs; + mEntryCount = 0; + mEntries = new Entry[8]; + } + + void addEntry(Entry e) { + if(mEntries.length >= mEntryCount) { + Entry[] en = new Entry[mEntryCount + 8]; + System.arraycopy(mEntries, 0, en, 0, mEntries.length); + mEntries = en; + } + mEntries[mEntryCount] = e; + mEntryCount++; + } + + //public Builder add(Element e) throws IllegalArgumentException { + //Entry en = new Entry(e, e.mSize * 8); + //addEntry(en); + //return this; + //} + + public Builder add(Element.DataType dt, Element.DataKind dk, boolean isNormalized, int bits, String name) { + Entry en = new Entry(dt, dk, isNormalized, bits, name); + addEntry(en); + return this; + } + + public Builder add(Element.DataType dt, Element.DataKind dk, boolean isNormalized, int bits) { + add(dt, dk, isNormalized, bits, null); + return this; + } + + public Builder addFloat(Element.DataKind dk) { + add(DataType.FLOAT, dk, false, 32, null); + return this; + } + + public Builder addFloat(Element.DataKind dk, String name) { + add(DataType.FLOAT, dk, false, 32, name); + return this; + } + + public Builder addFloatXY() { + add(DataType.FLOAT, DataKind.X, false, 32, null); + add(DataType.FLOAT, DataKind.Y, false, 32, null); + return this; + } + + public Builder addFloatXY(String prefix) { + add(DataType.FLOAT, DataKind.X, false, 32, prefix + "x"); + add(DataType.FLOAT, DataKind.Y, false, 32, prefix + "y"); + return this; + } + + public Builder addFloatXYZ() { + add(DataType.FLOAT, DataKind.X, false, 32, null); + add(DataType.FLOAT, DataKind.Y, false, 32, null); + add(DataType.FLOAT, DataKind.Z, false, 32, null); + return this; + } + + public Builder addFloatXYZ(String prefix) { + add(DataType.FLOAT, DataKind.X, false, 32, prefix + "x"); + add(DataType.FLOAT, DataKind.Y, false, 32, prefix + "y"); + add(DataType.FLOAT, DataKind.Z, false, 32, prefix + "z"); + return this; + } + + public Builder addFloatST() { + add(DataType.FLOAT, DataKind.S, false, 32, null); + add(DataType.FLOAT, DataKind.T, false, 32, null); + return this; + } + + public Builder addFloatST(String prefix) { + add(DataType.FLOAT, DataKind.S, false, 32, prefix + "s"); + add(DataType.FLOAT, DataKind.T, false, 32, prefix + "t"); + return this; + } + + public Builder addFloatNorm() { + add(DataType.FLOAT, DataKind.NX, false, 32, null); + add(DataType.FLOAT, DataKind.NY, false, 32, null); + add(DataType.FLOAT, DataKind.NZ, false, 32, null); + return this; + } + + public Builder addFloatNorm(String prefix) { + add(DataType.FLOAT, DataKind.NX, false, 32, prefix + "nx"); + add(DataType.FLOAT, DataKind.NY, false, 32, prefix + "ny"); + add(DataType.FLOAT, DataKind.NZ, false, 32, prefix + "nz"); + return this; + } + + public Builder addFloatPointSize() { + add(DataType.FLOAT, DataKind.POINT_SIZE, false, 32, null); + return this; + } + + public Builder addFloatPointSize(String prefix) { + add(DataType.FLOAT, DataKind.POINT_SIZE, false, 32, prefix + "pointSize"); + return this; + } + + public Builder addFloatRGB() { + add(DataType.FLOAT, DataKind.RED, false, 32, null); + add(DataType.FLOAT, DataKind.GREEN, false, 32, null); + add(DataType.FLOAT, DataKind.BLUE, false, 32, null); + return this; + } + + public Builder addFloatRGB(String prefix) { + add(DataType.FLOAT, DataKind.RED, false, 32, prefix + "r"); + add(DataType.FLOAT, DataKind.GREEN, false, 32, prefix + "g"); + add(DataType.FLOAT, DataKind.BLUE, false, 32, prefix + "b"); + return this; + } + + public Builder addFloatRGBA() { + add(DataType.FLOAT, DataKind.RED, false, 32, null); + add(DataType.FLOAT, DataKind.GREEN, false, 32, null); + add(DataType.FLOAT, DataKind.BLUE, false, 32, null); + add(DataType.FLOAT, DataKind.ALPHA, false, 32, null); + return this; + } + + public Builder addFloatRGBA(String prefix) { + add(DataType.FLOAT, DataKind.RED, false, 32, prefix + "r"); + add(DataType.FLOAT, DataKind.GREEN, false, 32, prefix + "g"); + add(DataType.FLOAT, DataKind.BLUE, false, 32, prefix + "b"); + add(DataType.FLOAT, DataKind.ALPHA, false, 32, prefix + "a"); + return this; + } + + public Builder addUNorm8RGBA() { + add(DataType.UNSIGNED, DataKind.RED, true, 8, null); + add(DataType.UNSIGNED, DataKind.GREEN, true, 8, null); + add(DataType.UNSIGNED, DataKind.BLUE, true, 8, null); + add(DataType.UNSIGNED, DataKind.ALPHA, true, 8, null); + return this; + } + + public Builder addUNorm8RGBA(String prefix) { + add(DataType.UNSIGNED, DataKind.RED, true, 8, prefix + "r"); + add(DataType.UNSIGNED, DataKind.GREEN, true, 8, prefix + "g"); + add(DataType.UNSIGNED, DataKind.BLUE, true, 8, prefix + "b"); + add(DataType.UNSIGNED, DataKind.ALPHA, true, 8, prefix + "a"); + return this; + } + + public Element create() { + Element e = new Element(mRS, mEntryCount); + java.lang.System.arraycopy(mEntries, 0, e.mEntries, 0, mEntryCount); + e.init(); + return e; + } + } + +} + diff --git a/graphics/java/android/renderscript/Light.java b/graphics/java/android/renderscript/Light.java new file mode 100644 index 0000000..115ae03 --- /dev/null +++ b/graphics/java/android/renderscript/Light.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + +import android.util.Config; +import android.util.Log; + +/** + * @hide + * + **/ +public class Light extends BaseObj { + Light(int id, RenderScript rs) { + super(rs); + mID = id; + } + + public void setColor(float r, float g, float b) { + mRS.nLightSetColor(mID, r, g, b); + } + + public void setPosition(float x, float y, float z) { + mRS.nLightSetPosition(mID, x, y, z); + } + + public static class Builder { + RenderScript mRS; + boolean mIsMono; + boolean mIsLocal; + + public Builder(RenderScript rs) { + mRS = rs; + mIsMono = false; + mIsLocal = false; + } + + public void lightSetIsMono(boolean isMono) { + mIsMono = isMono; + } + + public void lightSetIsLocal(boolean isLocal) { + mIsLocal = isLocal; + } + + static synchronized Light internalCreate(RenderScript rs, Builder b) { + rs.nSamplerBegin(); + rs.nLightSetIsMono(b.mIsMono); + rs.nLightSetIsLocal(b.mIsLocal); + int id = rs.nLightCreate(); + return new Light(id, rs); + } + + public Light create() { + return internalCreate(mRS, this); + } + } + +} + diff --git a/graphics/java/android/renderscript/Matrix.java b/graphics/java/android/renderscript/Matrix.java new file mode 100644 index 0000000..a266d6b --- /dev/null +++ b/graphics/java/android/renderscript/Matrix.java @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + +import java.lang.Math; +import android.util.Log; + + +/** + * @hide + * + **/ +public class Matrix { + + public Matrix() { + mMat = new float[16]; + loadIdentity(); + } + + public float get(int i, int j) { + return mMat[i*4 + j]; + } + + public void set(int i, int j, float v) { + mMat[i*4 + j] = v; + } + + public void loadIdentity() { + mMat[0] = 1; + mMat[1] = 0; + mMat[2] = 0; + mMat[3] = 0; + + mMat[4] = 0; + mMat[5] = 1; + mMat[6] = 0; + mMat[7] = 0; + + mMat[8] = 0; + mMat[9] = 0; + mMat[10] = 1; + mMat[11] = 0; + + mMat[12] = 0; + mMat[13] = 0; + mMat[14] = 0; + mMat[15] = 1; + } + + public void load(Matrix src) { + mMat = src.mMat; + } + + public void loadRotate(float rot, float x, float y, float z) { + float c, s; + mMat[3] = 0; + mMat[7] = 0; + mMat[11]= 0; + mMat[12]= 0; + mMat[13]= 0; + mMat[14]= 0; + mMat[15]= 1; + rot *= (float)(java.lang.Math.PI / 180.0f); + c = (float)java.lang.Math.cos(rot); + s = (float)java.lang.Math.sin(rot); + + float len = (float)java.lang.Math.sqrt(x*x + y*y + z*z); + if (!(len != 1)) { + float recipLen = 1.f / len; + x *= recipLen; + y *= recipLen; + z *= recipLen; + } + float nc = 1.0f - c; + float xy = x * y; + float yz = y * z; + float zx = z * x; + float xs = x * s; + float ys = y * s; + float zs = z * s; + mMat[ 0] = x*x*nc + c; + mMat[ 4] = xy*nc - zs; + mMat[ 8] = zx*nc + ys; + mMat[ 1] = xy*nc + zs; + mMat[ 5] = y*y*nc + c; + mMat[ 9] = yz*nc - xs; + mMat[ 2] = zx*nc - ys; + mMat[ 6] = yz*nc + xs; + mMat[10] = z*z*nc + c; + } + + public void loadScale(float x, float y, float z) { + loadIdentity(); + mMat[0] = x; + mMat[5] = y; + mMat[10] = z; + } + + public void loadTranslate(float x, float y, float z) { + loadIdentity(); + mMat[12] = x; + mMat[13] = y; + mMat[14] = z; + } + + public void loadMultiply(Matrix lhs, Matrix rhs) { + for (int i=0 ; i<4 ; i++) { + float ri0 = 0; + float ri1 = 0; + float ri2 = 0; + float ri3 = 0; + for (int j=0 ; j<4 ; j++) { + float rhs_ij = rhs.get(i,j); + ri0 += lhs.get(j,0) * rhs_ij; + ri1 += lhs.get(j,1) * rhs_ij; + ri2 += lhs.get(j,2) * rhs_ij; + ri3 += lhs.get(j,3) * rhs_ij; + } + set(i,0, ri0); + set(i,1, ri1); + set(i,2, ri2); + set(i,3, ri3); + } + } + + public void loadOrtho(float l, float r, float b, float t, float n, float f) { + loadIdentity(); + mMat[0] = 2 / (r - l); + mMat[5] = 2 / (t - b); + mMat[10]= -2 / (f - n); + mMat[12]= -(r + l) / (r - l); + mMat[13]= -(t + b) / (t - b); + mMat[14]= -(f + n) / (f - n); + } + + public void loadFrustum(float l, float r, float b, float t, float n, float f) { + loadIdentity(); + mMat[0] = 2 * n / (r - l); + mMat[5] = 2 * n / (t - b); + mMat[8] = (r + l) / (r - l); + mMat[9] = (t + b) / (t - b); + mMat[10]= -(f + n) / (f - n); + mMat[11]= -1; + mMat[14]= -2*f*n / (f - n); + mMat[15]= 0; + } + + public void multiply(Matrix rhs) { + Matrix tmp = new Matrix(); + tmp.loadMultiply(this, rhs); + load(tmp); + } + public void rotate(float rot, float x, float y, float z) { + Matrix tmp = new Matrix(); + tmp.loadRotate(rot, x, y, z); + multiply(tmp); + } + public void scale(float x, float y, float z) { + Matrix tmp = new Matrix(); + tmp.loadScale(x, y, z); + multiply(tmp); + } + public void translate(float x, float y, float z) { + Matrix tmp = new Matrix(); + tmp.loadTranslate(x, y, z); + multiply(tmp); + } + + + + float[] mMat; + +} + + + + + diff --git a/graphics/java/android/renderscript/Primitive.java b/graphics/java/android/renderscript/Primitive.java new file mode 100644 index 0000000..7925cac --- /dev/null +++ b/graphics/java/android/renderscript/Primitive.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + +/** + * @hide + **/ +public enum Primitive { + POINT (0), + LINE (1), + LINE_STRIP (2), + TRIANGLE (3), + TRIANGLE_STRIP (4), + TRIANGLE_FAN (5); + + int mID; + Primitive(int id) { + mID = id; + } +} + + + diff --git a/graphics/java/android/renderscript/ProgramFragment.java b/graphics/java/android/renderscript/ProgramFragment.java new file mode 100644 index 0000000..392d93d --- /dev/null +++ b/graphics/java/android/renderscript/ProgramFragment.java @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + + +import android.util.Config; +import android.util.Log; + + +/** + * @hide + * + **/ +public class ProgramFragment extends BaseObj { + public static final int MAX_SLOT = 2; + + public enum EnvMode { + REPLACE (0), + MODULATE (1), + DECAL (2); + + int mID; + EnvMode(int id) { + mID = id; + } + } + + + ProgramFragment(int id, RenderScript rs) { + super(rs); + mID = id; + } + + public void bindTexture(Allocation va, int slot) + throws IllegalArgumentException { + if((slot < 0) || (slot >= MAX_SLOT)) { + throw new IllegalArgumentException("Slot ID out of range."); + } + + mRS.nProgramFragmentBindTexture(mID, slot, va.mID); + } + + public void bindSampler(Sampler vs, int slot) + throws IllegalArgumentException { + if((slot < 0) || (slot >= MAX_SLOT)) { + throw new IllegalArgumentException("Slot ID out of range."); + } + + mRS.nProgramFragmentBindSampler(mID, slot, vs.mID); + } + + + public static class Builder { + RenderScript mRS; + Element mIn; + Element mOut; + boolean mPointSpriteEnable; + + private class Slot { + Type mType; + EnvMode mEnv; + boolean mTexEnable; + + Slot() { + mTexEnable = false; + } + } + Slot[] mSlots; + + public Builder(RenderScript rs, Element in, Element out) { + mRS = rs; + mIn = in; + mOut = out; + mSlots = new Slot[MAX_SLOT]; + mPointSpriteEnable = false; + for(int ct=0; ct < MAX_SLOT; ct++) { + mSlots[ct] = new Slot(); + } + } + + public void setType(int slot, Type t) + throws IllegalArgumentException { + if((slot < 0) || (slot >= MAX_SLOT)) { + throw new IllegalArgumentException("Slot ID out of range."); + } + + mSlots[slot].mType = t; + } + + public void setTexEnable(boolean enable, int slot) + throws IllegalArgumentException { + if((slot < 0) || (slot >= MAX_SLOT)) { + throw new IllegalArgumentException("Slot ID out of range."); + } + + mSlots[slot].mTexEnable = enable; + } + + public void setTexEnvMode(EnvMode env, int slot) + throws IllegalArgumentException { + if((slot < 0) || (slot >= MAX_SLOT)) { + throw new IllegalArgumentException("Slot ID out of range."); + } + + mSlots[slot].mEnv = env; + } + + public void setPointSpriteTexCoordinateReplacement(boolean enable) { + mPointSpriteEnable = enable; + } + + static synchronized ProgramFragment internalCreate(RenderScript rs, Builder b) { + int inID = 0; + int outID = 0; + if (b.mIn != null) { + inID = b.mIn.mID; + } + if (b.mOut != null) { + outID = b.mOut.mID; + } + rs.nProgramFragmentBegin(inID, outID, b.mPointSpriteEnable); + for(int ct=0; ct < MAX_SLOT; ct++) { + if(b.mSlots[ct].mTexEnable) { + Slot s = b.mSlots[ct]; + int typeID = 0; + if(s.mType != null) { + typeID = s.mType.mID; + } + rs.nProgramFragmentSetSlot(ct, true, s.mEnv.mID, typeID); + } + } + + int id = rs.nProgramFragmentCreate(); + return new ProgramFragment(id, rs); + } + + public ProgramFragment create() { + return internalCreate(mRS, this); + } + } +} + + + diff --git a/graphics/java/android/renderscript/ProgramRaster.java b/graphics/java/android/renderscript/ProgramRaster.java new file mode 100644 index 0000000..ab327f1 --- /dev/null +++ b/graphics/java/android/renderscript/ProgramRaster.java @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + + +import android.util.Config; +import android.util.Log; + + +/** + * @hide + * + **/ +public class ProgramRaster extends BaseObj { + boolean mPointSmooth; + boolean mLineSmooth; + boolean mPointSprite; + float mPointSize; + float mLineWidth; + Element mIn; + Element mOut; + + ProgramRaster(int id, RenderScript rs) { + super(rs); + mID = id; + + mPointSize = 1.0f; + mLineWidth = 1.0f; + mPointSmooth = false; + mLineSmooth = false; + mPointSprite = false; + } + + public void setLineWidth(float w) { + mLineWidth = w; + mRS.nProgramRasterSetLineWidth(mID, w); + } + + public void setPointSize(float s) { + mPointSize = s; + mRS.nProgramRasterSetPointSize(mID, s); + } + + void internalInit() { + int inID = 0; + int outID = 0; + if (mIn != null) { + inID = mIn.mID; + } + if (mOut != null) { + outID = mOut.mID; + } + mID = mRS.nProgramRasterCreate(inID, outID, mPointSmooth, mLineSmooth, mPointSprite); + } + + + public static class Builder { + RenderScript mRS; + ProgramRaster mPR; + + public Builder(RenderScript rs, Element in, Element out) { + mRS = rs; + mPR = new ProgramRaster(0, rs); + } + + public void setPointSpriteEnable(boolean enable) { + mPR.mPointSprite = enable; + } + + public void setPointSmoothEnable(boolean enable) { + mPR.mPointSmooth = enable; + } + + public void setLineSmoothEnable(boolean enable) { + mPR.mLineSmooth = enable; + } + + + static synchronized ProgramRaster internalCreate(RenderScript rs, Builder b) { + b.mPR.internalInit(); + ProgramRaster pr = b.mPR; + b.mPR = new ProgramRaster(0, b.mRS); + return pr; + } + + public ProgramRaster create() { + return internalCreate(mRS, this); + } + } + +} + + + + + diff --git a/graphics/java/android/renderscript/ProgramStore.java b/graphics/java/android/renderscript/ProgramStore.java new file mode 100644 index 0000000..5cbe1b2 --- /dev/null +++ b/graphics/java/android/renderscript/ProgramStore.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + + +import android.util.Config; +import android.util.Log; + + +/** + * @hide + * + **/ +public class ProgramStore extends BaseObj { + public enum DepthFunc { + ALWAYS (0), + LESS (1), + LEQUAL (2), + GREATER (3), + GEQUAL (4), + EQUAL (5), + NOTEQUAL (6); + + int mID; + DepthFunc(int id) { + mID = id; + } + } + + public enum BlendSrcFunc { + ZERO (0), + ONE (1), + DST_COLOR (2), + ONE_MINUS_DST_COLOR (3), + SRC_ALPHA (4), + ONE_MINUS_SRC_ALPHA (5), + DST_ALPHA (6), + ONE_MINUS_DST_ALPHA (7), + SRC_ALPHA_SATURATE (8); + + int mID; + BlendSrcFunc(int id) { + mID = id; + } + } + + public enum BlendDstFunc { + ZERO (0), + ONE (1), + SRC_COLOR (2), + ONE_MINUS_SRC_COLOR (3), + SRC_ALPHA (4), + ONE_MINUS_SRC_ALPHA (5), + DST_ALPHA (6), + ONE_MINUS_DST_ALPHA (7); + + int mID; + BlendDstFunc(int id) { + mID = id; + } + } + + + ProgramStore(int id, RenderScript rs) { + super(rs); + mID = id; + } + + + + public static class Builder { + RenderScript mRS; + Element mIn; + Element mOut; + DepthFunc mDepthFunc; + boolean mDepthMask; + boolean mColorMaskR; + boolean mColorMaskG; + boolean mColorMaskB; + boolean mColorMaskA; + BlendSrcFunc mBlendSrc; + BlendDstFunc mBlendDst; + boolean mDither; + + + + public Builder(RenderScript rs, Element in, Element out) { + mRS = rs; + mIn = in; + mOut = out; + mDepthFunc = DepthFunc.ALWAYS; + mDepthMask = false; + mColorMaskR = true; + mColorMaskG = true; + mColorMaskB = true; + mColorMaskA = true; + mBlendSrc = BlendSrcFunc.ONE; + mBlendDst = BlendDstFunc.ZERO; + + + } + + public void setDepthFunc(DepthFunc func) { + mDepthFunc = func; + } + + public void setDepthMask(boolean enable) { + mDepthMask = enable; + } + + public void setColorMask(boolean r, boolean g, boolean b, boolean a) { + mColorMaskR = r; + mColorMaskG = g; + mColorMaskB = b; + mColorMaskA = a; + } + + public void setBlendFunc(BlendSrcFunc src, BlendDstFunc dst) { + mBlendSrc = src; + mBlendDst = dst; + } + + public void setDitherEnable(boolean enable) { + mDither = enable; + } + + static synchronized ProgramStore internalCreate(RenderScript rs, Builder b) { + int inID = 0; + int outID = 0; + if (b.mIn != null) { + inID = b.mIn.mID; + } + if (b.mOut != null) { + outID = b.mOut.mID; + } + rs.nProgramFragmentStoreBegin(inID, outID); + rs.nProgramFragmentStoreDepthFunc(b.mDepthFunc.mID); + rs.nProgramFragmentStoreDepthMask(b.mDepthMask); + rs.nProgramFragmentStoreColorMask(b.mColorMaskR, + b.mColorMaskG, + b.mColorMaskB, + b.mColorMaskA); + rs.nProgramFragmentStoreBlendFunc(b.mBlendSrc.mID, b.mBlendDst.mID); + rs.nProgramFragmentStoreDither(b.mDither); + + int id = rs.nProgramFragmentStoreCreate(); + return new ProgramStore(id, rs); + } + + public ProgramStore create() { + return internalCreate(mRS, this); + } + } + +} + + + + diff --git a/graphics/java/android/renderscript/ProgramVertex.java b/graphics/java/android/renderscript/ProgramVertex.java new file mode 100644 index 0000000..ddb23ac --- /dev/null +++ b/graphics/java/android/renderscript/ProgramVertex.java @@ -0,0 +1,185 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + + +import android.util.Config; +import android.util.Log; + + +/** + * @hide + * + **/ +public class ProgramVertex extends BaseObj { + public static final int MAX_LIGHT = 8; + + ProgramVertex(int id, RenderScript rs) { + super(rs); + mID = id; + } + + public void bindAllocation(MatrixAllocation va) { + mRS.nProgramVertexBindAllocation(mID, va.mAlloc.mID); + } + + + public static class Builder { + RenderScript mRS; + Element mIn; + Element mOut; + Light[] mLights; + int mLightCount; + boolean mTextureMatrixEnable; + + + public Builder(RenderScript rs, Element in, Element out) { + mRS = rs; + mIn = in; + mOut = out; + mLights = new Light[MAX_LIGHT]; + mLightCount = 0; + } + + public void setTextureMatrixEnable(boolean enable) { + mTextureMatrixEnable = enable; + } + + public void addLight(Light l) throws IllegalStateException { + if(mLightCount >= MAX_LIGHT) { + throw new IllegalArgumentException("Max light count exceeded."); + } + mLights[mLightCount] = l; + mLightCount++; + } + + + + static synchronized ProgramVertex internalCreate(RenderScript rs, Builder b) { + int inID = 0; + int outID = 0; + if (b.mIn != null) { + inID = b.mIn.mID; + } + if (b.mOut != null) { + outID = b.mOut.mID; + } + rs.nProgramVertexBegin(inID, outID); + for(int ct=0; ct < b.mLightCount; ct++) { + rs.nProgramVertexAddLight(b.mLights[ct].mID); + } + rs.nProgramVertexSetTextureMatrixEnable(b.mTextureMatrixEnable); + int id = rs.nProgramVertexCreate(); + return new ProgramVertex(id, rs); + } + + public ProgramVertex create() { + return internalCreate(mRS, this); + } + } + + + + public static class MatrixAllocation { + static final int MODELVIEW_OFFSET = 0; + static final int PROJECTION_OFFSET = 16; + static final int TEXTURE_OFFSET = 32; + + Matrix mModel; + Matrix mProjection; + Matrix mTexture; + + public Allocation mAlloc; + + public MatrixAllocation(RenderScript rs) { + mModel = new Matrix(); + mProjection = new Matrix(); + mTexture = new Matrix(); + + mAlloc = Allocation.createSized(rs, Element.USER_F32(rs), 48); + mAlloc.subData1D(MODELVIEW_OFFSET, 16, mModel.mMat); + mAlloc.subData1D(PROJECTION_OFFSET, 16, mProjection.mMat); + mAlloc.subData1D(TEXTURE_OFFSET, 16, mTexture.mMat); + } + + public void destroy() { + mAlloc.destroy(); + mAlloc = null; + } + + public void loadModelview(Matrix m) { + mModel = m; + mAlloc.subData1D(MODELVIEW_OFFSET, 16, m.mMat); + } + + public void loadProjection(Matrix m) { + mProjection = m; + mAlloc.subData1D(PROJECTION_OFFSET, 16, m.mMat); + } + + public void loadTexture(Matrix m) { + mTexture = m; + mAlloc.subData1D(TEXTURE_OFFSET, 16, m.mMat); + } + + public void setupOrthoWindow(int w, int h) { + mProjection.loadOrtho(0,w, h,0, -1,1); + mAlloc.subData1D(PROJECTION_OFFSET, 16, mProjection.mMat); + } + + public void setupOrthoNormalized(int w, int h) { + // range -1,1 in the narrow axis. + if(w > h) { + float aspect = ((float)w) / h; + mProjection.loadOrtho(-aspect,aspect, -1,1, -1,1); + } else { + float aspect = ((float)h) / w; + mProjection.loadOrtho(-1,1, -aspect,aspect, -1,1); + } + mAlloc.subData1D(PROJECTION_OFFSET, 16, mProjection.mMat); + } + + public void setupProjectionNormalized(int w, int h) { + // range -1,1 in the narrow axis at z = 0. + Matrix m1 = new Matrix(); + Matrix m2 = new Matrix(); + + if(w > h) { + float aspect = ((float)w) / h; + m1.loadFrustum(-aspect,aspect, -1,1, 1,100); + } else { + float aspect = ((float)h) / w; + m1.loadFrustum(-1,1, -aspect,aspect, 1,100); + } + + m2.loadRotate(180, 0, 1, 0); + m1.loadMultiply(m1, m2); + + m2.loadScale(-2, 2, 1); + m1.loadMultiply(m1, m2); + + m2.loadTranslate(0, 0, 2); + m1.loadMultiply(m1, m2); + + mProjection = m1; + mAlloc.subData1D(PROJECTION_OFFSET, 16, mProjection.mMat); + } + + } + +} + diff --git a/graphics/java/android/renderscript/RSSurfaceView.java b/graphics/java/android/renderscript/RSSurfaceView.java new file mode 100644 index 0000000..1bc03ac --- /dev/null +++ b/graphics/java/android/renderscript/RSSurfaceView.java @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + +import java.io.Writer; +import java.util.ArrayList; +import java.util.concurrent.Semaphore; + +import android.content.Context; +import android.os.Handler; +import android.os.Message; +import android.util.AttributeSet; +import android.util.Log; +import android.util.Log; +import android.view.Surface; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +/** + * @hide + * + **/ +public class RSSurfaceView extends SurfaceView implements SurfaceHolder.Callback { + private SurfaceHolder mSurfaceHolder; + private RenderScript mRS; + + /** + * Standard View constructor. In order to render something, you + * must call {@link #setRenderer} to register a renderer. + */ + public RSSurfaceView(Context context) { + super(context); + init(); + //Log.v(RenderScript.LOG_TAG, "RSSurfaceView"); + } + + /** + * Standard View constructor. In order to render something, you + * must call {@link #setRenderer} to register a renderer. + */ + public RSSurfaceView(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + //Log.v(RenderScript.LOG_TAG, "RSSurfaceView"); + } + + private void init() { + // Install a SurfaceHolder.Callback so we get notified when the + // underlying surface is created and destroyed + SurfaceHolder holder = getHolder(); + holder.addCallback(this); + } + + /** + * This method is part of the SurfaceHolder.Callback interface, and is + * not normally called or subclassed by clients of RSSurfaceView. + */ + public void surfaceCreated(SurfaceHolder holder) { + Log.v(RenderScript.LOG_TAG, "surfaceCreated"); + mSurfaceHolder = holder; + } + + /** + * This method is part of the SurfaceHolder.Callback interface, and is + * not normally called or subclassed by clients of RSSurfaceView. + */ + public void surfaceDestroyed(SurfaceHolder holder) { + // Surface will be destroyed when we return + if (mRS != null) { + mRS.contextSetSurface(null); + } + //Log.v(RenderScript.LOG_TAG, "surfaceDestroyed"); + } + + /** + * This method is part of the SurfaceHolder.Callback interface, and is + * not normally called or subclassed by clients of RSSurfaceView. + */ + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + if (mRS != null) { + mRS.contextSetSurface(holder.getSurface()); + } + //Log.v(RenderScript.LOG_TAG, "surfaceChanged"); + } + + /** + * Inform the view that the activity is paused. The owner of this view must + * call this method when the activity is paused. Calling this method will + * pause the rendering thread. + * Must not be called before a renderer has been set. + */ + public void onPause() { + if(mRS != null) { + mRS.pause(); + } + //Log.v(RenderScript.LOG_TAG, "onPause"); + } + + /** + * Inform the view that the activity is resumed. The owner of this view must + * call this method when the activity is resumed. Calling this method will + * recreate the OpenGL display and resume the rendering + * thread. + * Must not be called before a renderer has been set. + */ + public void onResume() { + if(mRS != null) { + mRS.resume(); + } + //Log.v(RenderScript.LOG_TAG, "onResume"); + } + + /** + * Queue a runnable to be run on the GL rendering thread. This can be used + * to communicate with the Renderer on the rendering thread. + * Must not be called before a renderer has been set. + * @param r the runnable to be run on the GL rendering thread. + */ + public void queueEvent(Runnable r) { + //Log.v(RenderScript.LOG_TAG, "queueEvent"); + } + + /** + * This method is used as part of the View class and is not normally + * called or subclassed by clients of RSSurfaceView. + * Must not be called before a renderer has been set. + */ + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + } + + // ---------------------------------------------------------------------- + + public RenderScript createRenderScript(boolean useDepth, boolean forceSW) { + Surface sur = null; + while ((sur == null) || (mSurfaceHolder == null)) { + sur = getHolder().getSurface(); + } + mRS = new RenderScript(sur, useDepth, forceSW); + return mRS; + } + + public RenderScript createRenderScript(boolean useDepth) { + return createRenderScript(useDepth, false); + } + + public void destroyRenderScript() { + mRS.destroy(); + mRS = null; + } +} + diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java new file mode 100644 index 0000000..f1e5af1 --- /dev/null +++ b/graphics/java/android/renderscript/RenderScript.java @@ -0,0 +1,366 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + +import java.lang.reflect.Field; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.util.Config; +import android.util.Log; +import android.view.Surface; + + +/** + * @hide + * + **/ +public class RenderScript { + static final String LOG_TAG = "libRS_jni"; + private static final boolean DEBUG = false; + @SuppressWarnings({"UnusedDeclaration", "deprecation"}) + private static final boolean LOG_ENABLED = DEBUG ? Config.LOGD : Config.LOGV; + + + + /* + * We use a class initializer to allow the native code to cache some + * field offsets. + */ + @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) + private static boolean sInitialized; + native private static void _nInit(); + + + static { + sInitialized = false; + try { + System.loadLibrary("rs_jni"); + _nInit(); + sInitialized = true; + } catch (UnsatisfiedLinkError e) { + Log.d(LOG_TAG, "RenderScript JNI library not found!"); + } + } + + native void nInitElements(int a8, int rgba4444, int rgba8888, int rgb565); + + native int nDeviceCreate(); + native void nDeviceDestroy(int dev); + native void nDeviceSetConfig(int dev, int param, int value); + native int nContextCreate(int dev, Surface sur, int ver, boolean useDepth); + native void nContextDestroy(int con); + native void nContextSetSurface(Surface sur); + + native void nContextBindRootScript(int script); + native void nContextBindSampler(int sampler, int slot); + native void nContextBindProgramFragmentStore(int pfs); + native void nContextBindProgramFragment(int pf); + native void nContextBindProgramVertex(int pf); + native void nContextBindProgramRaster(int pr); + native void nContextAddDefineI32(String name, int value); + native void nContextAddDefineF(String name, float value); + native void nContextPause(); + native void nContextResume(); + native int nContextGetMessage(int[] data, boolean wait); + native void nContextInitToClient(); + native void nContextDeinitToClient(); + + native void nAssignName(int obj, byte[] name); + native void nObjDestroy(int id); + native void nObjDestroyOOB(int id); + native int nFileOpen(byte[] name); + + native void nElementBegin(); + native void nElementAdd(int kind, int type, boolean norm, int bits, String s); + native int nElementCreate(); + + native void nTypeBegin(int elementID); + native void nTypeAdd(int dim, int val); + native int nTypeCreate(); + native void nTypeFinalDestroy(Type t); + native void nTypeSetupFields(Type t, int[] types, int[] bits, Field[] IDs); + + native int nAllocationCreateTyped(int type); + native int nAllocationCreateFromBitmap(int dstFmt, boolean genMips, Bitmap bmp); + native int nAllocationCreateFromBitmapBoxed(int dstFmt, boolean genMips, Bitmap bmp); + native int nAllocationCreateFromAssetStream(int dstFmt, boolean genMips, int assetStream); + + native void nAllocationUploadToTexture(int alloc, int baseMioLevel); + native void nAllocationUploadToBufferObject(int alloc); + + native void nAllocationSubData1D(int id, int off, int count, int[] d, int sizeBytes); + native void nAllocationSubData1D(int id, int off, int count, short[] d, int sizeBytes); + native void nAllocationSubData1D(int id, int off, int count, byte[] d, int sizeBytes); + native void nAllocationSubData1D(int id, int off, int count, float[] d, int sizeBytes); + + native void nAllocationSubData2D(int id, int xoff, int yoff, int w, int h, int[] d, int sizeBytes); + native void nAllocationSubData2D(int id, int xoff, int yoff, int w, int h, float[] d, int sizeBytes); + native void nAllocationRead(int id, int[] d); + native void nAllocationRead(int id, float[] d); + native void nAllocationSubDataFromObject(int id, Type t, int offset, Object o); + native void nAllocationSubReadFromObject(int id, Type t, int offset, Object o); + + native void nAdapter1DBindAllocation(int ad, int alloc); + native void nAdapter1DSetConstraint(int ad, int dim, int value); + native void nAdapter1DData(int ad, int[] d); + native void nAdapter1DData(int ad, float[] d); + native void nAdapter1DSubData(int ad, int off, int count, int[] d); + native void nAdapter1DSubData(int ad, int off, int count, float[] d); + native int nAdapter1DCreate(); + + native void nAdapter2DBindAllocation(int ad, int alloc); + native void nAdapter2DSetConstraint(int ad, int dim, int value); + native void nAdapter2DData(int ad, int[] d); + native void nAdapter2DData(int ad, float[] d); + native void nAdapter2DSubData(int ad, int xoff, int yoff, int w, int h, int[] d); + native void nAdapter2DSubData(int ad, int xoff, int yoff, int w, int h, float[] d); + native int nAdapter2DCreate(); + + native void nScriptBindAllocation(int script, int alloc, int slot); + native void nScriptSetClearColor(int script, float r, float g, float b, float a); + native void nScriptSetClearDepth(int script, float depth); + native void nScriptSetClearStencil(int script, int stencil); + native void nScriptSetTimeZone(int script, byte[] timeZone); + native void nScriptSetType(int type, boolean writable, String name, int slot); + native void nScriptSetRoot(boolean isRoot); + native void nScriptSetInvokable(String name, int slot); + native void nScriptInvoke(int id, int slot); + + native void nScriptCBegin(); + native void nScriptCSetScript(byte[] script, int offset, int length); + native int nScriptCCreate(); + native void nScriptCAddDefineI32(String name, int value); + native void nScriptCAddDefineF(String name, float value); + + native void nSamplerBegin(); + native void nSamplerSet(int param, int value); + native int nSamplerCreate(); + + native void nProgramFragmentStoreBegin(int in, int out); + native void nProgramFragmentStoreDepthFunc(int func); + native void nProgramFragmentStoreDepthMask(boolean enable); + native void nProgramFragmentStoreColorMask(boolean r, boolean g, boolean b, boolean a); + native void nProgramFragmentStoreBlendFunc(int src, int dst); + native void nProgramFragmentStoreDither(boolean enable); + native int nProgramFragmentStoreCreate(); + + native int nProgramRasterCreate(int in, int out, boolean pointSmooth, boolean lineSmooth, boolean pointSprite); + native void nProgramRasterSetLineWidth(int pr, float v); + native void nProgramRasterSetPointSize(int pr, float v); + + native void nProgramFragmentBegin(int in, int out, boolean pointSpriteEnable); + native void nProgramFragmentBindTexture(int vpf, int slot, int a); + native void nProgramFragmentBindSampler(int vpf, int slot, int s); + native void nProgramFragmentSetSlot(int slot, boolean enable, int env, int vt); + native int nProgramFragmentCreate(); + + native void nProgramVertexBindAllocation(int pv, int mID); + native void nProgramVertexBegin(int inID, int outID); + native void nProgramVertexSetTextureMatrixEnable(boolean enable); + native void nProgramVertexAddLight(int id); + native int nProgramVertexCreate(); + + native void nLightBegin(); + native void nLightSetIsMono(boolean isMono); + native void nLightSetIsLocal(boolean isLocal); + native int nLightCreate(); + native void nLightSetColor(int l, float r, float g, float b); + native void nLightSetPosition(int l, float x, float y, float z); + + native int nSimpleMeshCreate(int batchID, int idxID, int[] vtxID, int prim); + native void nSimpleMeshBindVertex(int id, int alloc, int slot); + native void nSimpleMeshBindIndex(int id, int alloc); + + native void nAnimationBegin(int attribCount, int keyframeCount); + native void nAnimationAdd(float time, float[] attribs); + native int nAnimationCreate(); + + private int mDev; + private int mContext; + @SuppressWarnings({"FieldCanBeLocal"}) + private Surface mSurface; + private MessageThread mMessageThread; + + + Element mElement_USER_U8; + Element mElement_USER_I8; + Element mElement_USER_U16; + Element mElement_USER_I16; + Element mElement_USER_U32; + Element mElement_USER_I32; + Element mElement_USER_FLOAT; + + Element mElement_A_8; + Element mElement_RGB_565; + Element mElement_RGB_888; + Element mElement_RGBA_5551; + Element mElement_RGBA_4444; + Element mElement_RGBA_8888; + + Element mElement_INDEX_16; + Element mElement_XY_F32; + Element mElement_XYZ_F32; + + /////////////////////////////////////////////////////////////////////////////////// + // + + public static class RSMessage implements Runnable { + protected int[] mData; + protected int mID; + public void run() { + } + } + public RSMessage mMessageCallback = null; + + private static class MessageThread extends Thread { + RenderScript mRS; + boolean mRun = true; + + MessageThread(RenderScript rs) { + super("RSMessageThread"); + mRS = rs; + + } + + public void run() { + // This function is a temporary solution. The final solution will + // used typed allocations where the message id is the type indicator. + int[] rbuf = new int[16]; + mRS.nContextInitToClient(); + while(mRun) { + int msg = mRS.nContextGetMessage(rbuf, true); + if (msg == 0) { + // Should only happen during teardown. + // But we want to avoid starving other threads during + // teardown by yielding until the next line in the destructor + // can execute to set mRun = false + try { + sleep(1, 0); + } catch(InterruptedException e) { + } + } + if(mRS.mMessageCallback != null) { + mRS.mMessageCallback.mData = rbuf; + mRS.mMessageCallback.mID = msg; + mRS.mMessageCallback.run(); + } + //Log.d("rs", "MessageThread msg " + msg + " v1 " + rbuf[0] + " v2 " + rbuf[1] + " v3 " +rbuf[2]); + } + Log.d("rs", "MessageThread exiting."); + } + } + + public RenderScript(Surface sur, boolean useDepth, boolean forceSW) { + mSurface = sur; + mDev = nDeviceCreate(); + if(forceSW) { + nDeviceSetConfig(mDev, 0, 1); + } + mContext = nContextCreate(mDev, mSurface, 0, useDepth); + Element.initPredefined(this); + mMessageThread = new MessageThread(this); + mMessageThread.start(); + } + + public void contextSetSurface(Surface sur) { + mSurface = sur; + nContextSetSurface(mSurface); + } + + public void destroy() { + nContextDeinitToClient(); + mMessageThread.mRun = false; + + nContextDestroy(mContext); + mContext = 0; + + nDeviceDestroy(mDev); + mDev = 0; + } + + boolean isAlive() { + return mContext != 0; + } + + void pause() { + nContextPause(); + } + + void resume() { + nContextResume(); + } + + ////////////////////////////////////////////////////////////////////////////////// + // File + + public class File extends BaseObj { + File(int id) { + super(RenderScript.this); + mID = id; + } + } + + public File fileOpen(String s) throws IllegalStateException, IllegalArgumentException + { + if(s.length() < 1) { + throw new IllegalArgumentException("fileOpen does not accept a zero length string."); + } + + try { + byte[] bytes = s.getBytes("UTF-8"); + int id = nFileOpen(bytes); + return new File(id); + } catch (java.io.UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + + /////////////////////////////////////////////////////////////////////////////////// + // Root state + + private int safeID(BaseObj o) { + if(o != null) { + return o.mID; + } + return 0; + } + + public void contextBindRootScript(Script s) { + nContextBindRootScript(safeID(s)); + } + + public void contextBindProgramFragmentStore(ProgramStore p) { + nContextBindProgramFragmentStore(safeID(p)); + } + + public void contextBindProgramFragment(ProgramFragment p) { + nContextBindProgramFragment(safeID(p)); + } + + public void contextBindProgramRaster(ProgramRaster p) { + nContextBindProgramRaster(safeID(p)); + } + + public void contextBindProgramVertex(ProgramVertex p) { + nContextBindProgramVertex(safeID(p)); + } + +} + + diff --git a/graphics/java/android/renderscript/Sampler.java b/graphics/java/android/renderscript/Sampler.java new file mode 100644 index 0000000..5e0b110 --- /dev/null +++ b/graphics/java/android/renderscript/Sampler.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + + +import java.io.IOException; +import java.io.InputStream; + +import android.content.res.Resources; +import android.os.Bundle; +import android.util.Config; +import android.util.Log; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; + +/** + * @hide + * + **/ +public class Sampler extends BaseObj { + public enum Value { + NEAREST (0), + LINEAR (1), + LINEAR_MIP_LINEAR (2), + WRAP (3), + CLAMP (4); + + int mID; + Value(int id) { + mID = id; + } + } + + Sampler(int id, RenderScript rs) { + super(rs); + mID = id; + } + + public static class Builder { + RenderScript mRS; + Value mMin; + Value mMag; + Value mWrapS; + Value mWrapT; + Value mWrapR; + + public Builder(RenderScript rs) { + mRS = rs; + mMin = Value.NEAREST; + mMag = Value.NEAREST; + mWrapS = Value.WRAP; + mWrapT = Value.WRAP; + mWrapR = Value.WRAP; + } + + public void setMin(Value v) { + mMin = v; + } + + public void setMag(Value v) { + mMag = v; + } + + public void setWrapS(Value v) { + mWrapS = v; + } + + public void setWrapT(Value v) { + mWrapT = v; + } + + public void setWrapR(Value v) { + mWrapR = v; + } + + static synchronized Sampler internalCreate(RenderScript rs, Builder b) { + rs.nSamplerBegin(); + rs.nSamplerSet(0, b.mMin.mID); + rs.nSamplerSet(1, b.mMag.mID); + rs.nSamplerSet(2, b.mWrapS.mID); + rs.nSamplerSet(3, b.mWrapT.mID); + rs.nSamplerSet(4, b.mWrapR.mID); + int id = rs.nSamplerCreate(); + return new Sampler(id, rs); + } + + public Sampler create() { + return internalCreate(mRS, this); + } + } + +} + diff --git a/graphics/java/android/renderscript/Script.java b/graphics/java/android/renderscript/Script.java new file mode 100644 index 0000000..35791a3 --- /dev/null +++ b/graphics/java/android/renderscript/Script.java @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + +/** + * @hide + **/ +public class Script extends BaseObj { + public static final int MAX_SLOT = 16; + + boolean mIsRoot; + Type[] mTypes; + boolean[] mWritable; + Invokable[] mInvokables; + + public static class Invokable { + RenderScript mRS; + Script mScript; + int mSlot; + String mName; + + Invokable() { + mSlot = -1; + } + + public void execute() { + mRS.nScriptInvoke(mScript.mID, mSlot); + } + } + + Script(int id, RenderScript rs) { + super(rs); + mID = id; + } + + public void bindAllocation(Allocation va, int slot) { + mRS.nScriptBindAllocation(mID, va.mID, slot); + } + + public void setClearColor(float r, float g, float b, float a) { + mRS.nScriptSetClearColor(mID, r, g, b, a); + } + + public void setClearDepth(float d) { + mRS.nScriptSetClearDepth(mID, d); + } + + public void setClearStencil(int stencil) { + mRS.nScriptSetClearStencil(mID, stencil); + } + + public void setTimeZone(String timeZone) { + try { + mRS.nScriptSetTimeZone(mID, timeZone.getBytes("UTF-8")); + } catch (java.io.UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + public static class Builder { + RenderScript mRS; + boolean mIsRoot = false; + Type[] mTypes; + String[] mNames; + boolean[] mWritable; + int mInvokableCount = 0; + Invokable[] mInvokables; + + Builder(RenderScript rs) { + mRS = rs; + mTypes = new Type[MAX_SLOT]; + mNames = new String[MAX_SLOT]; + mWritable = new boolean[MAX_SLOT]; + mInvokables = new Invokable[MAX_SLOT]; + } + + public void setType(Type t, int slot) { + mTypes[slot] = t; + mNames[slot] = null; + } + + public void setType(Type t, String name, int slot) { + mTypes[slot] = t; + mNames[slot] = name; + } + + public Invokable addInvokable(String func) { + Invokable i = new Invokable(); + i.mName = func; + i.mRS = mRS; + i.mSlot = mInvokableCount; + mInvokables[mInvokableCount++] = i; + return i; + } + + public void setType(boolean writable, int slot) { + mWritable[slot] = writable; + } + + void transferCreate() { + mRS.nScriptSetRoot(mIsRoot); + for(int ct=0; ct < mTypes.length; ct++) { + if(mTypes[ct] != null) { + mRS.nScriptSetType(mTypes[ct].mID, mWritable[ct], mNames[ct], ct); + } + } + for(int ct=0; ct < mInvokableCount; ct++) { + mRS.nScriptSetInvokable(mInvokables[ct].mName, ct); + } + } + + void transferObject(Script s) { + s.mIsRoot = mIsRoot; + s.mTypes = mTypes; + s.mInvokables = new Invokable[mInvokableCount]; + for(int ct=0; ct < mInvokableCount; ct++) { + s.mInvokables[ct] = mInvokables[ct]; + s.mInvokables[ct].mScript = s; + } + s.mInvokables = null; + } + + public void setRoot(boolean r) { + mIsRoot = r; + } + + } + +} + diff --git a/graphics/java/android/renderscript/ScriptC.java b/graphics/java/android/renderscript/ScriptC.java new file mode 100644 index 0000000..bb99e23 --- /dev/null +++ b/graphics/java/android/renderscript/ScriptC.java @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + +import android.content.res.Resources; +import android.util.Log; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map.Entry; +import java.util.HashMap; + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +/** + * @hide + **/ +public class ScriptC extends Script { + private static final String TAG = "ScriptC"; + + ScriptC(int id, RenderScript rs) { + super(id, rs); + } + + public static class Builder extends Script.Builder { + byte[] mProgram; + int mProgramLength; + HashMap mIntDefines = new HashMap(); + HashMap mFloatDefines = new HashMap(); + + public Builder(RenderScript rs) { + super(rs); + } + + public void setScript(String s) { + try { + mProgram = s.getBytes("UTF-8"); + mProgramLength = mProgram.length; + } catch (java.io.UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + public void setScript(Resources resources, int id) { + InputStream is = resources.openRawResource(id); + try { + try { + setScript(is); + } finally { + is.close(); + } + } catch(IOException e) { + throw new Resources.NotFoundException(); + } + } + + public void setScript(InputStream is) throws IOException { + byte[] buf = new byte[1024]; + int currentPos = 0; + while(true) { + int bytesLeft = buf.length - currentPos; + if (bytesLeft == 0) { + byte[] buf2 = new byte[buf.length * 2]; + System.arraycopy(buf, 0, buf2, 0, buf.length); + buf = buf2; + bytesLeft = buf.length - currentPos; + } + int bytesRead = is.read(buf, currentPos, bytesLeft); + if (bytesRead <= 0) { + break; + } + currentPos += bytesRead; + } + mProgram = buf; + mProgramLength = currentPos; + } + + static synchronized ScriptC internalCreate(Builder b) { + b.mRS.nScriptCBegin(); + b.transferCreate(); + + for (Entry e: b.mIntDefines.entrySet()) { + b.mRS.nScriptCAddDefineI32(e.getKey(), e.getValue().intValue()); + } + for (Entry e: b.mFloatDefines.entrySet()) { + b.mRS.nScriptCAddDefineF(e.getKey(), e.getValue().floatValue()); + } + + b.mRS.nScriptCSetScript(b.mProgram, 0, b.mProgramLength); + + int id = b.mRS.nScriptCCreate(); + ScriptC obj = new ScriptC(id, b.mRS); + b.transferObject(obj); + + return obj; + } + + public void addDefine(String name, int value) { + mIntDefines.put(name, value); + } + + public void addDefine(String name, float value) { + mFloatDefines.put(name, value); + } + + /** + * Takes the all public static final fields for a class, and adds defines + * for them, using the name of the field as the name of the define. + */ + public void addDefines(Class cl) { + addDefines(cl.getFields(), (Modifier.STATIC | Modifier.FINAL | Modifier.PUBLIC), null); + } + + /** + * Takes the all public fields for an object, and adds defines + * for them, using the name of the field as the name of the define. + */ + public void addDefines(Object o) { + addDefines(o.getClass().getFields(), Modifier.PUBLIC, o); + } + + void addDefines(Field[] fields, int mask, Object o) { + for (Field f: fields) { + try { + if ((f.getModifiers() & mask) == mask) { + Class t = f.getType(); + if (t == int.class) { + mIntDefines.put(f.getName(), f.getInt(o)); + } + else if (t == float.class) { + mFloatDefines.put(f.getName(), f.getFloat(o)); + } + } + } catch (IllegalAccessException ex) { + // TODO: Do we want this log? + Log.d(TAG, "addDefines skipping field " + f.getName()); + } + } + } + + public ScriptC create() { + return internalCreate(this); + } + } +} + diff --git a/graphics/java/android/renderscript/SimpleMesh.java b/graphics/java/android/renderscript/SimpleMesh.java new file mode 100644 index 0000000..3d10e3b --- /dev/null +++ b/graphics/java/android/renderscript/SimpleMesh.java @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + +import android.util.Config; +import android.util.Log; + +/** + * @hide + * + **/ +public class SimpleMesh extends BaseObj { + Type[] mVertexTypes; + Type mIndexType; + //Type mBatcheType; + Primitive mPrimitive; + + SimpleMesh(int id, RenderScript rs) { + super(rs); + mID = id; + } + + public void bindVertexAllocation(Allocation a, int slot) { + mRS.nSimpleMeshBindVertex(mID, a.mID, slot); + } + + public void bindIndexAllocation(Allocation a) { + mRS.nSimpleMeshBindIndex(mID, a.mID); + } + + public Allocation createVertexAllocation(int slot) { + return Allocation.createTyped(mRS, mVertexTypes[slot]); + } + + public Allocation createIndexAllocation() { + return Allocation.createTyped(mRS, mIndexType); + } + + public Type getVertexType(int slot) { + return mVertexTypes[slot]; + } + + public Type getIndexType() { + return mIndexType; + } + + public static class Builder { + RenderScript mRS; + + class Entry { + Type t; + Element e; + int size; + } + + int mVertexTypeCount; + Entry[] mVertexTypes; + Entry mIndexType; + //Entry mBatchType; + Primitive mPrimitive; + + + public Builder(RenderScript rs) { + mRS = rs; + mVertexTypeCount = 0; + mVertexTypes = new Entry[16]; + mIndexType = new Entry(); + } + + public int addVertexType(Type t) throws IllegalStateException { + if (mVertexTypeCount >= mVertexTypes.length) { + throw new IllegalStateException("Max vertex types exceeded."); + } + + int addedIndex = mVertexTypeCount; + mVertexTypes[mVertexTypeCount] = new Entry(); + mVertexTypes[mVertexTypeCount].t = t; + mVertexTypeCount++; + return addedIndex; + } + + public int addVertexType(Element e, int size) throws IllegalStateException { + if (mVertexTypeCount >= mVertexTypes.length) { + throw new IllegalStateException("Max vertex types exceeded."); + } + + int addedIndex = mVertexTypeCount; + mVertexTypes[mVertexTypeCount] = new Entry(); + mVertexTypes[mVertexTypeCount].e = e; + mVertexTypes[mVertexTypeCount].size = size; + mVertexTypeCount++; + return addedIndex; + } + + public void setIndexType(Type t) { + mIndexType.t = t; + mIndexType.e = null; + mIndexType.size = 0; + } + + public void setIndexType(Element e, int size) { + mIndexType.t = null; + mIndexType.e = e; + mIndexType.size = size; + } + + public void setPrimitive(Primitive p) { + mPrimitive = p; + } + + + Type newType(Element e, int size) { + Type.Builder tb = new Type.Builder(mRS, e); + tb.add(Dimension.X, size); + return tb.create(); + } + + static synchronized SimpleMesh internalCreate(RenderScript rs, Builder b) { + Type[] toDestroy = new Type[18]; + int toDestroyCount = 0; + + int indexID = 0; + if (b.mIndexType.t != null) { + indexID = b.mIndexType.t.mID; + } else if (b.mIndexType.size != 0) { + b.mIndexType.t = b.newType(b.mIndexType.e, b.mIndexType.size); + indexID = b.mIndexType.t.mID; + toDestroy[toDestroyCount++] = b.mIndexType.t; + } + + int[] IDs = new int[b.mVertexTypeCount]; + for(int ct=0; ct < b.mVertexTypeCount; ct++) { + if (b.mVertexTypes[ct].t != null) { + IDs[ct] = b.mVertexTypes[ct].t.mID; + } else { + b.mVertexTypes[ct].t = b.newType(b.mVertexTypes[ct].e, b.mVertexTypes[ct].size); + IDs[ct] = b.mVertexTypes[ct].t.mID; + toDestroy[toDestroyCount++] = b.mVertexTypes[ct].t; + } + } + + int id = rs.nSimpleMeshCreate(0, indexID, IDs, b.mPrimitive.mID); + for(int ct=0; ct < toDestroyCount; ct++) { + toDestroy[ct].destroy(); + } + + return new SimpleMesh(id, rs); + } + + public SimpleMesh create() { + SimpleMesh sm = internalCreate(mRS, this); + sm.mVertexTypes = new Type[mVertexTypeCount]; + for(int ct=0; ct < mVertexTypeCount; ct++) { + sm.mVertexTypes[ct] = mVertexTypes[ct].t; + } + sm.mIndexType = mIndexType.t; + sm.mPrimitive = mPrimitive; + return sm; + } + } + + public static class TriangleMeshBuilder { + float mVtxData[]; + int mVtxCount; + short mIndexData[]; + int mIndexCount; + RenderScript mRS; + Element mElement; + + float mNX = 0; + float mNY = 0; + float mNZ = -1; + float mS0 = 0; + float mT0 = 0; + float mR = 1; + float mG = 1; + float mB = 1; + float mA = 1; + + int mVtxSize; + int mFlags; + + public static final int COLOR = 0x0001; + public static final int NORMAL = 0x0002; + public static final int TEXTURE_0 = 0x0100; + + public TriangleMeshBuilder(RenderScript rs, int vtxSize, int flags) { + mRS = rs; + mVtxCount = 0; + mIndexCount = 0; + mVtxData = new float[128]; + mIndexData = new short[128]; + mVtxSize = vtxSize; + mFlags = flags; + + if (vtxSize < 2 || vtxSize > 3) { + throw new IllegalArgumentException("Vertex size out of range."); + } + } + + private void makeSpace(int count) { + if ((mVtxCount + count) >= mVtxData.length) { + float t[] = new float[mVtxData.length * 2]; + System.arraycopy(mVtxData, 0, t, 0, mVtxData.length); + mVtxData = t; + } + } + + private void latch() { + if ((mFlags & COLOR) != 0) { + makeSpace(4); + mVtxData[mVtxCount++] = mR; + mVtxData[mVtxCount++] = mG; + mVtxData[mVtxCount++] = mB; + mVtxData[mVtxCount++] = mA; + } + if ((mFlags & TEXTURE_0) != 0) { + makeSpace(2); + mVtxData[mVtxCount++] = mS0; + mVtxData[mVtxCount++] = mT0; + } + if ((mFlags & NORMAL) != 0) { + makeSpace(3); + mVtxData[mVtxCount++] = mNX; + mVtxData[mVtxCount++] = mNY; + mVtxData[mVtxCount++] = mNZ; + } + } + + public void addVertex(float x, float y) { + if (mVtxSize != 2) { + throw new IllegalStateException("add mistmatch with declared components."); + } + makeSpace(2); + mVtxData[mVtxCount++] = x; + mVtxData[mVtxCount++] = y; + latch(); + } + + public void addVertex(float x, float y, float z) { + if (mVtxSize != 3) { + throw new IllegalStateException("add mistmatch with declared components."); + } + makeSpace(3); + mVtxData[mVtxCount++] = x; + mVtxData[mVtxCount++] = y; + mVtxData[mVtxCount++] = z; + latch(); + } + + public void setTexture(float s, float t) { + if ((mFlags & TEXTURE_0) == 0) { + throw new IllegalStateException("add mistmatch with declared components."); + } + mS0 = s; + mT0 = t; + } + + public void setNormal(float x, float y, float z) { + if ((mFlags & NORMAL) == 0) { + throw new IllegalStateException("add mistmatch with declared components."); + } + mNX = x; + mNY = y; + mNZ = z; + } + + public void setColor(float r, float g, float b, float a) { + if ((mFlags & COLOR) == 0) { + throw new IllegalStateException("add mistmatch with declared components."); + } + mR = r; + mG = g; + mB = b; + mA = a; + } + + public void addTriangle(int idx1, int idx2, int idx3) { + if((idx1 >= mVtxCount) || (idx1 < 0) || + (idx2 >= mVtxCount) || (idx2 < 0) || + (idx3 >= mVtxCount) || (idx3 < 0)) { + throw new IllegalStateException("Index provided greater than vertex count."); + } + if ((mIndexCount + 3) >= mIndexData.length) { + short t[] = new short[mIndexData.length * 2]; + System.arraycopy(mIndexData, 0, t, 0, mIndexData.length); + mIndexData = t; + } + mIndexData[mIndexCount++] = (short)idx1; + mIndexData[mIndexCount++] = (short)idx2; + mIndexData[mIndexCount++] = (short)idx3; + } + + public SimpleMesh create() { + Element.Builder b = new Element.Builder(mRS); + int floatCount = mVtxSize; + if (mVtxSize == 2) { + b.addFloatXY(); + } else { + b.addFloatXYZ(); + } + if ((mFlags & COLOR) != 0) { + floatCount += 4; + b.addFloatRGBA(); + } + if ((mFlags & TEXTURE_0) != 0) { + floatCount += 2; + b.addFloatST(); + } + if ((mFlags & NORMAL) != 0) { + floatCount += 3; + b.addFloatNorm(); + } + mElement = b.create(); + + Builder smb = new Builder(mRS); + smb.addVertexType(mElement, mVtxCount / floatCount); + smb.setIndexType(Element.INDEX_16(mRS), mIndexCount); + smb.setPrimitive(Primitive.TRIANGLE); + SimpleMesh sm = smb.create(); + + Allocation vertexAlloc = sm.createVertexAllocation(0); + Allocation indexAlloc = sm.createIndexAllocation(); + sm.bindVertexAllocation(vertexAlloc, 0); + sm.bindIndexAllocation(indexAlloc); + + vertexAlloc.data(mVtxData); + vertexAlloc.uploadToBufferObject(); + + indexAlloc.data(mIndexData); + indexAlloc.uploadToBufferObject(); + + return sm; + } + } +} + diff --git a/graphics/java/android/renderscript/Type.java b/graphics/java/android/renderscript/Type.java new file mode 100644 index 0000000..ad4cf6b --- /dev/null +++ b/graphics/java/android/renderscript/Type.java @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.renderscript; + +import java.lang.reflect.Field; + +/** + * @hide + * + **/ +public class Type extends BaseObj { + int mDimX; + int mDimY; + int mDimZ; + boolean mDimLOD; + boolean mDimFaces; + int mElementCount; + Element mElement; + + private int mNativeCache; + Class mJavaClass; + + + public int getX() { + return mDimX; + } + public int getY() { + return mDimY; + } + public int getZ() { + return mDimZ; + } + public boolean getLOD() { + return mDimLOD; + } + public boolean getFaces() { + return mDimFaces; + } + public int getElementCount() { + return mElementCount; + } + + void calcElementCount() { + boolean hasLod = getLOD(); + int x = getX(); + int y = getY(); + int z = getZ(); + int faces = 1; + if(getFaces()) { + faces = 6; + } + if(x == 0) { + x = 1; + } + if(y == 0) { + y = 1; + } + if(z == 0) { + z = 1; + } + + int count = x * y * z * faces; + if(hasLod && (x > 1) && (y > 1) && (z > 1)) { + if(x > 1) { + x >>= 1; + } + if(y > 1) { + y >>= 1; + } + if(z > 1) { + z >>= 1; + } + + count += x * y * z * faces; + } + mElementCount = count; + } + + + Type(int id, RenderScript rs) { + super(rs); + mID = id; + mNativeCache = 0; + } + + protected void finalize() throws Throwable { + if(mNativeCache != 0) { + mRS.nTypeFinalDestroy(this); + mNativeCache = 0; + } + super.finalize(); + } + + public static Type createFromClass(RenderScript rs, Class c, int size) { + Element e = Element.createFromClass(rs, c); + Builder b = new Builder(rs, e); + b.add(Dimension.X, size); + Type t = b.create(); + e.destroy(); + + // native fields + { + Field[] fields = c.getFields(); + int[] arTypes = new int[fields.length]; + int[] arBits = new int[fields.length]; + + for(int ct=0; ct < fields.length; ct++) { + Field f = fields[ct]; + Class fc = f.getType(); + if(fc == int.class) { + arTypes[ct] = Element.DataType.SIGNED.mID; + arBits[ct] = 32; + } else if(fc == short.class) { + arTypes[ct] = Element.DataType.SIGNED.mID; + arBits[ct] = 16; + } else if(fc == byte.class) { + arTypes[ct] = Element.DataType.SIGNED.mID; + arBits[ct] = 8; + } else if(fc == float.class) { + arTypes[ct] = Element.DataType.FLOAT.mID; + arBits[ct] = 32; + } else { + throw new IllegalArgumentException("Unkown field type"); + } + } + rs.nTypeSetupFields(t, arTypes, arBits, fields); + } + t.mJavaClass = c; + return t; + } + + public static Type createFromClass(RenderScript rs, Class c, int size, String scriptName) { + Type t = createFromClass(rs, c, size); + t.setName(scriptName); + return t; + } + + + public static class Builder { + RenderScript mRS; + Entry[] mEntries; + int mEntryCount; + Element mElement; + + class Entry { + Dimension mDim; + int mValue; + } + + public Builder(RenderScript rs, Element e) { + if(e.mID == 0) { + throw new IllegalArgumentException("Invalid element."); + } + + mRS = rs; + mEntries = new Entry[4]; + mElement = e; + } + + public void add(Dimension d, int value) { + if(value < 1) { + throw new IllegalArgumentException("Values of less than 1 for Dimensions are not valid."); + } + if(mEntries.length >= mEntryCount) { + Entry[] en = new Entry[mEntryCount + 8]; + System.arraycopy(mEntries, 0, en, 0, mEntries.length); + mEntries = en; + } + mEntries[mEntryCount] = new Entry(); + mEntries[mEntryCount].mDim = d; + mEntries[mEntryCount].mValue = value; + mEntryCount++; + } + + static synchronized Type internalCreate(RenderScript rs, Builder b) { + rs.nTypeBegin(b.mElement.mID); + for (int ct=0; ct < b.mEntryCount; ct++) { + Entry en = b.mEntries[ct]; + rs.nTypeAdd(en.mDim.mID, en.mValue); + } + int id = rs.nTypeCreate(); + return new Type(id, rs); + } + + public Type create() { + Type t = internalCreate(mRS, this); + t.mElement = mElement; + + for(int ct=0; ct < mEntryCount; ct++) { + if(mEntries[ct].mDim == Dimension.X) { + t.mDimX = mEntries[ct].mValue; + } + if(mEntries[ct].mDim == Dimension.Y) { + t.mDimY = mEntries[ct].mValue; + } + if(mEntries[ct].mDim == Dimension.Z) { + t.mDimZ = mEntries[ct].mValue; + } + if(mEntries[ct].mDim == Dimension.LOD) { + t.mDimLOD = mEntries[ct].mValue != 0; + } + if(mEntries[ct].mDim == Dimension.FACE) { + t.mDimFaces = mEntries[ct].mValue != 0; + } + } + t.calcElementCount(); + return t; + } + } + +} -- cgit v1.1