am ffb9333c: Merge "Fix app bug, where some memory could remain uninitialized due to early exit."

* commit 'ffb9333cb40a69b578e4ffbd44526bfc11b66a03':
  Fix app bug, where some memory could remain uninitialized due to early exit.
diff --git a/samples/RenderScript/Levels/Android.mk b/samples/RenderScript/Levels/Android.mk
new file mode 100644
index 0000000..3f1445d
--- /dev/null
+++ b/samples/RenderScript/Levels/Android.mk
@@ -0,0 +1,26 @@
+#
+# Copyright (C) 2012 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.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := LevelsRS
+
+include $(BUILD_PACKAGE)
diff --git a/samples/RenderScript/Levels/AndroidManifest.xml b/samples/RenderScript/Levels/AndroidManifest.xml
new file mode 100644
index 0000000..8294048
--- /dev/null
+++ b/samples/RenderScript/Levels/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2012 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.
+*/
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.rs.levels">
+    <uses-sdk android:minSdkVersion="14" />
+    <application android:label="Levels RS"
+                 android:hardwareAccelerated="true">
+
+        <activity android:name="LevelsRSActivity"
+                  android:label="Levels RS">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+        <activity android:name="LevelsDalvikActivity"
+                  android:label="Levels Dalvik">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+
+    </application>
+</manifest>
diff --git a/samples/RenderScript/Levels/res/drawable-nodpi/city.png b/samples/RenderScript/Levels/res/drawable-nodpi/city.png
new file mode 100644
index 0000000..856eeff
--- /dev/null
+++ b/samples/RenderScript/Levels/res/drawable-nodpi/city.png
Binary files differ
diff --git a/samples/RenderScript/Levels/res/layout/main.xml b/samples/RenderScript/Levels/res/layout/main.xml
new file mode 100644
index 0000000..a6a075c
--- /dev/null
+++ b/samples/RenderScript/Levels/res/layout/main.xml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+            android:orientation="vertical"
+            android:layout_width="fill_parent"
+            android:layout_height="fill_parent"
+            android:id="@+id/toplevel">
+    <SurfaceView
+        android:id="@+id/surface"
+        android:layout_width="1dip"
+        android:layout_height="1dip" />
+    <ScrollView
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent">
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="vertical"
+                android:layout_width="fill_parent"
+                android:layout_height="fill_parent">
+            <ImageView
+                android:id="@+id/display"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content" />
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:orientation="horizontal"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content">
+                    <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:text="@string/benchmark"
+                        android:onClick="benchmark"/>
+                    <TextView
+                        android:id="@+id/benchmarkText"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:textSize="8pt"
+                        android:text="@string/saturation"/>
+            </LinearLayout>
+            <TextView
+                android:id="@+id/inSaturationText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/saturation"/>
+             <SeekBar
+                android:id="@+id/inSaturation"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/outWhiteText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:textSize="8pt"
+                android:text="@string/out_white"/>
+            <SeekBar
+                android:id="@+id/outWhite"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inWhiteText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_white"/>
+            <SeekBar
+                android:id="@+id/inWhite"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/outBlackText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/out_black"/>
+            <SeekBar
+                android:id="@+id/outBlack"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inBlackText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/in_black"/>
+            <SeekBar
+                android:id="@+id/inBlack"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            <TextView
+                android:id="@+id/inGammaText"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:textSize="8pt"
+                android:layout_marginLeft="10sp"
+                android:layout_marginTop="15sp"
+                android:text="@string/gamma"/>
+            <SeekBar
+                android:id="@+id/inGamma"
+                android:layout_marginLeft="10sp"
+                android:layout_marginRight="10sp"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+            </LinearLayout>
+    </ScrollView>
+</LinearLayout>
+
diff --git a/samples/RenderScript/Levels/res/values/strings.xml b/samples/RenderScript/Levels/res/values/strings.xml
new file mode 100644
index 0000000..0552d3b
--- /dev/null
+++ b/samples/RenderScript/Levels/res/values/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+* Copyright (C) 2012 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- General -->
+    <skip />
+    <!--slider label -->
+    <string name="in_white">In White</string>
+    <string name="out_white">Out White</string>
+    <string name="in_black">In Black</string>
+    <string name="out_black">Out Black</string>
+    <string name="gamma">Gamma</string>
+    <string name="saturation">Saturation</string>
+    <string name="benchmark">Benchmark</string>
+
+</resources>
diff --git a/samples/RenderScript/Levels/src/com/android/rs/levels/LevelsDalvikActivity.java b/samples/RenderScript/Levels/src/com/android/rs/levels/LevelsDalvikActivity.java
new file mode 100644
index 0000000..8d94bf8
--- /dev/null
+++ b/samples/RenderScript/Levels/src/com/android/rs/levels/LevelsDalvikActivity.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2012 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 com.android.rs.levels;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.os.Bundle;
+import android.renderscript.Matrix3f;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+public class LevelsDalvikActivity extends Activity
+                                  implements SeekBar.OnSeekBarChangeListener {
+    private final String TAG = "Img";
+    private Bitmap mBitmapIn;
+    private Bitmap mBitmapOut;
+    private float mInBlack = 0.0f;
+    private SeekBar mInBlackSeekBar;
+    private float mOutBlack = 0.0f;
+    private SeekBar mOutBlackSeekBar;
+    private float mInWhite = 255.0f;
+    private SeekBar mInWhiteSeekBar;
+    private float mOutWhite = 255.0f;
+    private SeekBar mOutWhiteSeekBar;
+    private float mGamma = 1.0f;
+    private SeekBar mGammaSeekBar;
+    private float mSaturation = 1.0f;
+    private SeekBar mSaturationSeekBar;
+    private TextView mBenchmarkResult;
+    private ImageView mDisplayView;
+
+    Matrix3f satMatrix = new Matrix3f();
+    float mInWMinInB;
+    float mOutWMinOutB;
+    float mOverInWMinInB;
+
+    int mInPixels[];
+    int mOutPixels[];
+
+    private void setLevels() {
+        mInWMinInB = mInWhite - mInBlack;
+        mOutWMinOutB = mOutWhite - mOutBlack;
+        mOverInWMinInB = 1.f / mInWMinInB;
+    }
+
+    private void setSaturation() {
+        float rWeight = 0.299f;
+        float gWeight = 0.587f;
+        float bWeight = 0.114f;
+        float oneMinusS = 1.0f - mSaturation;
+
+        satMatrix.set(0, 0, oneMinusS * rWeight + mSaturation);
+        satMatrix.set(0, 1, oneMinusS * rWeight);
+        satMatrix.set(0, 2, oneMinusS * rWeight);
+        satMatrix.set(1, 0, oneMinusS * gWeight);
+        satMatrix.set(1, 1, oneMinusS * gWeight + mSaturation);
+        satMatrix.set(1, 2, oneMinusS * gWeight);
+        satMatrix.set(2, 0, oneMinusS * bWeight);
+        satMatrix.set(2, 1, oneMinusS * bWeight);
+        satMatrix.set(2, 2, oneMinusS * bWeight + mSaturation);
+    }
+
+    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+        if (fromUser) {
+            if (seekBar == mInBlackSeekBar) {
+                mInBlack = (float)progress;
+                setLevels();
+            } else if (seekBar == mOutBlackSeekBar) {
+                mOutBlack = (float)progress;
+                setLevels();
+            } else if (seekBar == mInWhiteSeekBar) {
+                mInWhite = (float)progress + 127.0f;
+                setLevels();
+            } else if (seekBar == mOutWhiteSeekBar) {
+                mOutWhite = (float)progress + 127.0f;
+                setLevels();
+            } else if (seekBar == mGammaSeekBar) {
+                mGamma = (float)progress/100.0f;
+                mGamma = Math.max(mGamma, 0.1f);
+                mGamma = 1.0f / mGamma;
+            } else if (seekBar == mSaturationSeekBar) {
+                mSaturation = (float)progress / 50.0f;
+                setSaturation();
+            }
+
+            filter();
+            mDisplayView.invalidate();
+        }
+    }
+
+    public void onStartTrackingTouch(SeekBar seekBar) {
+    }
+
+    public void onStopTrackingTouch(SeekBar seekBar) {
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mBitmapIn = loadBitmap(R.drawable.city);
+        mBitmapOut = loadBitmap(R.drawable.city);
+
+        mDisplayView = (ImageView) findViewById(R.id.display);
+        mDisplayView.setImageBitmap(mBitmapOut);
+
+        mInBlackSeekBar = (SeekBar)findViewById(R.id.inBlack);
+        mInBlackSeekBar.setOnSeekBarChangeListener(this);
+        mInBlackSeekBar.setMax(128);
+        mInBlackSeekBar.setProgress(0);
+        mOutBlackSeekBar = (SeekBar)findViewById(R.id.outBlack);
+        mOutBlackSeekBar.setOnSeekBarChangeListener(this);
+        mOutBlackSeekBar.setMax(128);
+        mOutBlackSeekBar.setProgress(0);
+
+        mInWhiteSeekBar = (SeekBar)findViewById(R.id.inWhite);
+        mInWhiteSeekBar.setOnSeekBarChangeListener(this);
+        mInWhiteSeekBar.setMax(128);
+        mInWhiteSeekBar.setProgress(128);
+        mOutWhiteSeekBar = (SeekBar)findViewById(R.id.outWhite);
+        mOutWhiteSeekBar.setOnSeekBarChangeListener(this);
+        mOutWhiteSeekBar.setMax(128);
+        mOutWhiteSeekBar.setProgress(128);
+
+        mGammaSeekBar = (SeekBar)findViewById(R.id.inGamma);
+        mGammaSeekBar.setOnSeekBarChangeListener(this);
+        mGammaSeekBar.setMax(150);
+        mGammaSeekBar.setProgress(100);
+
+        mSaturationSeekBar = (SeekBar)findViewById(R.id.inSaturation);
+        mSaturationSeekBar.setOnSeekBarChangeListener(this);
+        mSaturationSeekBar.setProgress(50);
+
+        mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
+        mBenchmarkResult.setText("Result: not run");
+
+        mInPixels = new int[mBitmapIn.getHeight() * mBitmapIn.getWidth()];
+        mOutPixels = new int[mBitmapOut.getHeight() * mBitmapOut.getWidth()];
+        mBitmapIn.getPixels(mInPixels, 0, mBitmapIn.getWidth(), 0, 0,
+                            mBitmapIn.getWidth(), mBitmapIn.getHeight());
+
+        setLevels();
+        setSaturation();
+        filter();
+    }
+
+    private Bitmap loadBitmap(int resource) {
+        final BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        Bitmap b = BitmapFactory.decodeResource(getResources(), resource, options);
+        Bitmap b2 = Bitmap.createBitmap(b.getWidth(), b.getHeight(), b.getConfig());
+        Canvas c = new Canvas(b2);
+        c.drawBitmap(b, 0, 0, null);
+        b.recycle();
+        return b2;
+    }
+
+
+
+    private void filter() {
+        final float[] m = satMatrix.getArray();
+
+        for (int i=0; i < mInPixels.length; i++) {
+            float r = (float)(mInPixels[i] & 0xff);
+            float g = (float)((mInPixels[i] >> 8) & 0xff);
+            float b = (float)((mInPixels[i] >> 16) & 0xff);
+
+            float tr = r * m[0] + g * m[3] + b * m[6];
+            float tg = r * m[1] + g * m[4] + b * m[7];
+            float tb = r * m[2] + g * m[5] + b * m[8];
+            r = tr;
+            g = tg;
+            b = tb;
+
+            if (r < 0.f) r = 0.f;
+            if (r > 255.f) r = 255.f;
+            if (g < 0.f) g = 0.f;
+            if (g > 255.f) g = 255.f;
+            if (b < 0.f) b = 0.f;
+            if (b > 255.f) b = 255.f;
+
+            r = (r - mInBlack) * mOverInWMinInB;
+            g = (g - mInBlack) * mOverInWMinInB;
+            b = (b - mInBlack) * mOverInWMinInB;
+
+            if (mGamma != 1.0f) {
+                r = (float)java.lang.Math.pow(r, mGamma);
+                g = (float)java.lang.Math.pow(g, mGamma);
+                b = (float)java.lang.Math.pow(b, mGamma);
+            }
+
+            r = (r * mOutWMinOutB) + mOutBlack;
+            g = (g * mOutWMinOutB) + mOutBlack;
+            b = (b * mOutWMinOutB) + mOutBlack;
+
+            if (r < 0.f) r = 0.f;
+            if (r > 255.f) r = 255.f;
+            if (g < 0.f) g = 0.f;
+            if (g > 255.f) g = 255.f;
+            if (b < 0.f) b = 0.f;
+            if (b > 255.f) b = 255.f;
+
+            mOutPixels[i] = ((int)r) + (((int)g) << 8) + (((int)b) << 16)
+                            + (mInPixels[i] & 0xff000000);
+        }
+
+        mBitmapOut.setPixels(mOutPixels, 0, mBitmapOut.getWidth(), 0, 0,
+                             mBitmapOut.getWidth(), mBitmapOut.getHeight());
+    }
+
+    public void benchmark(View v) {
+        filter();
+        long t = java.lang.System.currentTimeMillis();
+        filter();
+        t = java.lang.System.currentTimeMillis() - t;
+        mDisplayView.invalidate();
+        mBenchmarkResult.setText("Result: " + t + " ms");
+    }
+}
diff --git a/samples/RenderScript/Levels/src/com/android/rs/levels/LevelsRSActivity.java b/samples/RenderScript/Levels/src/com/android/rs/levels/LevelsRSActivity.java
new file mode 100644
index 0000000..f5139db
--- /dev/null
+++ b/samples/RenderScript/Levels/src/com/android/rs/levels/LevelsRSActivity.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2012 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 com.android.rs.levels;
+
+import android.app.Activity;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.os.Bundle;
+import android.renderscript.Matrix3f;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.renderscript.Allocation;
+import android.renderscript.RenderScript;
+
+public class LevelsRSActivity extends Activity
+                              implements SeekBar.OnSeekBarChangeListener {
+    private final String TAG = "Img";
+    private Bitmap mBitmapIn;
+    private Bitmap mBitmapOut;
+    private float mInBlack = 0.0f;
+    private SeekBar mInBlackSeekBar;
+    private float mOutBlack = 0.0f;
+    private SeekBar mOutBlackSeekBar;
+    private float mInWhite = 255.0f;
+    private SeekBar mInWhiteSeekBar;
+    private float mOutWhite = 255.0f;
+    private SeekBar mOutWhiteSeekBar;
+    private float mGamma = 1.0f;
+    private SeekBar mGammaSeekBar;
+    private float mSaturation = 1.0f;
+    private SeekBar mSaturationSeekBar;
+    private TextView mBenchmarkResult;
+    private ImageView mDisplayView;
+
+    Matrix3f satMatrix = new Matrix3f();
+    float mInWMinInB;
+    float mOutWMinOutB;
+    float mOverInWMinInB;
+
+    private RenderScript mRS;
+    private Allocation mInPixelsAllocation;
+    private Allocation mOutPixelsAllocation;
+    private ScriptC_levels mScript;
+
+    private void setLevels() {
+        mInWMinInB = mInWhite - mInBlack;
+        mOutWMinOutB = mOutWhite - mOutBlack;
+        mOverInWMinInB = 1.f / mInWMinInB;
+
+        mScript.set_inBlack(mInBlack);
+        mScript.set_outBlack(mOutBlack);
+        mScript.set_inWMinInB(mInWMinInB);
+        mScript.set_outWMinOutB(mOutWMinOutB);
+        mScript.set_overInWMinInB(mOverInWMinInB);
+    }
+
+    private void setSaturation() {
+        float rWeight = 0.299f;
+        float gWeight = 0.587f;
+        float bWeight = 0.114f;
+        float oneMinusS = 1.0f - mSaturation;
+
+        satMatrix.set(0, 0, oneMinusS * rWeight + mSaturation);
+        satMatrix.set(0, 1, oneMinusS * rWeight);
+        satMatrix.set(0, 2, oneMinusS * rWeight);
+        satMatrix.set(1, 0, oneMinusS * gWeight);
+        satMatrix.set(1, 1, oneMinusS * gWeight + mSaturation);
+        satMatrix.set(1, 2, oneMinusS * gWeight);
+        satMatrix.set(2, 0, oneMinusS * bWeight);
+        satMatrix.set(2, 1, oneMinusS * bWeight);
+        satMatrix.set(2, 2, oneMinusS * bWeight + mSaturation);
+        mScript.set_colorMat(satMatrix);
+    }
+
+    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+        if (fromUser) {
+            if (seekBar == mInBlackSeekBar) {
+                mInBlack = (float)progress;
+                setLevels();
+            } else if (seekBar == mOutBlackSeekBar) {
+                mOutBlack = (float)progress;
+                setLevels();
+            } else if (seekBar == mInWhiteSeekBar) {
+                mInWhite = (float)progress + 127.0f;
+                setLevels();
+            } else if (seekBar == mOutWhiteSeekBar) {
+                mOutWhite = (float)progress + 127.0f;
+                setLevels();
+            } else if (seekBar == mGammaSeekBar) {
+                mGamma = (float)progress/100.0f;
+                mGamma = Math.max(mGamma, 0.1f);
+                mGamma = 1.0f / mGamma;
+                mScript.set_gamma(mGamma);
+            } else if (seekBar == mSaturationSeekBar) {
+                mSaturation = (float)progress / 50.0f;
+                setSaturation();
+            }
+
+            filter();
+            mDisplayView.invalidate();
+        }
+    }
+
+    public void onStartTrackingTouch(SeekBar seekBar) {
+    }
+
+    public void onStopTrackingTouch(SeekBar seekBar) {
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+
+        mBitmapIn = loadBitmap(R.drawable.city);
+        mBitmapOut = loadBitmap(R.drawable.city);
+
+        mDisplayView = (ImageView) findViewById(R.id.display);
+        mDisplayView.setImageBitmap(mBitmapOut);
+
+        mInBlackSeekBar = (SeekBar)findViewById(R.id.inBlack);
+        mInBlackSeekBar.setOnSeekBarChangeListener(this);
+        mInBlackSeekBar.setMax(128);
+        mInBlackSeekBar.setProgress(0);
+        mOutBlackSeekBar = (SeekBar)findViewById(R.id.outBlack);
+        mOutBlackSeekBar.setOnSeekBarChangeListener(this);
+        mOutBlackSeekBar.setMax(128);
+        mOutBlackSeekBar.setProgress(0);
+
+        mInWhiteSeekBar = (SeekBar)findViewById(R.id.inWhite);
+        mInWhiteSeekBar.setOnSeekBarChangeListener(this);
+        mInWhiteSeekBar.setMax(128);
+        mInWhiteSeekBar.setProgress(128);
+        mOutWhiteSeekBar = (SeekBar)findViewById(R.id.outWhite);
+        mOutWhiteSeekBar.setOnSeekBarChangeListener(this);
+        mOutWhiteSeekBar.setMax(128);
+        mOutWhiteSeekBar.setProgress(128);
+
+        mGammaSeekBar = (SeekBar)findViewById(R.id.inGamma);
+        mGammaSeekBar.setOnSeekBarChangeListener(this);
+        mGammaSeekBar.setMax(150);
+        mGammaSeekBar.setProgress(100);
+
+        mSaturationSeekBar = (SeekBar)findViewById(R.id.inSaturation);
+        mSaturationSeekBar.setOnSeekBarChangeListener(this);
+        mSaturationSeekBar.setProgress(50);
+
+        mBenchmarkResult = (TextView) findViewById(R.id.benchmarkText);
+        mBenchmarkResult.setText("Result: not run");
+
+        mRS = RenderScript.create(this);
+        mInPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapIn,
+                                                          Allocation.MipmapControl.MIPMAP_NONE,
+                                                          Allocation.USAGE_SCRIPT);
+        mOutPixelsAllocation = Allocation.createFromBitmap(mRS, mBitmapOut,
+                                                           Allocation.MipmapControl.MIPMAP_NONE,
+                                                           Allocation.USAGE_SCRIPT);
+        mScript = new ScriptC_levels(mRS, getResources(), R.raw.levels);
+        mScript.set_gamma(mGamma);
+
+        setSaturation();
+        setLevels();
+        filter();
+    }
+
+    private Bitmap loadBitmap(int resource) {
+        final BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        Bitmap b = BitmapFactory.decodeResource(getResources(), resource, options);
+        Bitmap b2 = Bitmap.createBitmap(b.getWidth(), b.getHeight(), b.getConfig());
+        Canvas c = new Canvas(b2);
+        c.drawBitmap(b, 0, 0, null);
+        b.recycle();
+        return b2;
+    }
+
+    private void filter() {
+        mScript.forEach_root(mInPixelsAllocation, mOutPixelsAllocation);
+        mOutPixelsAllocation.copyTo(mBitmapOut);
+    }
+
+    public void benchmark(View v) {
+        filter();
+        long t = java.lang.System.currentTimeMillis();
+        filter();
+        t = java.lang.System.currentTimeMillis() - t;
+        mDisplayView.invalidate();
+        mBenchmarkResult.setText("Result: " + t + " ms");
+    }
+}
diff --git a/samples/RenderScript/Levels/src/com/android/rs/levels/levels.rs b/samples/RenderScript/Levels/src/com/android/rs/levels/levels.rs
new file mode 100644
index 0000000..fd14772
--- /dev/null
+++ b/samples/RenderScript/Levels/src/com/android/rs/levels/levels.rs
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#pragma version(1)
+#pragma rs java_package_name(com.android.rs.levels)
+
+float inBlack;
+float outBlack;
+float inWMinInB;
+float outWMinOutB;
+float overInWMinInB;
+float gamma;
+rs_matrix3x3 colorMat;
+
+void root(const uchar4 *in, uchar4 *out, uint32_t x, uint32_t y) {
+    float3 pixel = convert_float4(in[0]).rgb;
+    pixel = rsMatrixMultiply(&colorMat, pixel);
+    pixel = clamp(pixel, 0.f, 255.f);
+    pixel = (pixel - inBlack) * overInWMinInB;
+    if (gamma != 1.0f)
+        pixel = pow(pixel, (float3)gamma);
+    pixel = pixel * outWMinOutB + outBlack;
+    pixel = clamp(pixel, 0.f, 255.f);
+    out->xyz = convert_uchar3(pixel);
+}
+
diff --git a/tools/a3dconvert/ColladaConditioner.cpp b/tools/a3dconvert/ColladaConditioner.cpp
index 0a99e0e..afebb8c 100644
--- a/tools/a3dconvert/ColladaConditioner.cpp
+++ b/tools/a3dconvert/ColladaConditioner.cpp
@@ -204,15 +204,27 @@
 
 bool ColladaConditioner::stripGeometry(DAE *dae) {
     bool convertSuceeded = true;
-    int geometryElementCount = (int)(dae->getDatabase()->getElementCount(NULL,
-                                                                         "library_geometries" ));
 
+    int error = 0;
+
+    // How many geometry elements are there?
+    int geometryElementCount = (int)(dae->getDatabase()->getElementCount(NULL, "geometry" ));
     for(int currentGeometry = 0; currentGeometry < geometryElementCount; currentGeometry++) {
 
+        // Find the next geometry element
+        domGeometry *thisGeometry = 0;
         daeElement * element = 0;
-        int error = dae->getDatabase()->getElement(&element, currentGeometry,
-                                                   NULL, "library_geometries");
-        daeBool removed = daeElement::removeFromParent(element);
+        error = dae->getDatabase()->getElement(&element, currentGeometry, NULL, "geometry");
+        thisGeometry = (domGeometry *) element;
+
+        // Get the mesh out of the geometry
+        domMesh *thisMesh = thisGeometry->getMesh();
+
+        if (thisMesh == NULL){
+            continue;
+        }
+
+        daeBool removed = daeElement::removeFromParent(thisMesh);
         convertSuceeded = convertSuceeded && removed;
     }
     return convertSuceeded;
diff --git a/tools/a3dconvert/a3dconvert.cpp b/tools/a3dconvert/a3dconvert.cpp
index 4e48642..aa8ee0e 100644
--- a/tools/a3dconvert/a3dconvert.cpp
+++ b/tools/a3dconvert/a3dconvert.cpp
@@ -42,8 +42,6 @@
     }
 }
 
-// We only care to implement allocation memory initialization and destruction
-// because we need no other renderscript hal features for serialization
 static RsdHalFunctions FunctionTable;
 bool rsdHalInit(Context *rsc, uint32_t version_major, uint32_t version_minor) {
     memset(&FunctionTable, 0, sizeof(FunctionTable));