Move gfx samples to test directory for compatibility testing.
Change-Id: Iede1c0a14abf9aa3f31ab219fba3bf3a15ef8c90
diff --git a/tests/RenderScriptTests/Balls/Android.mk b/tests/RenderScriptTests/Balls/Android.mk
new file mode 100644
index 0000000..b109584
--- /dev/null
+++ b/tests/RenderScriptTests/Balls/Android.mk
@@ -0,0 +1,26 @@
+#
+# 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.
+#
+
+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 := RsBalls
+
+include $(BUILD_PACKAGE)
diff --git a/tests/RenderScriptTests/Balls/AndroidManifest.xml b/tests/RenderScriptTests/Balls/AndroidManifest.xml
new file mode 100644
index 0000000..80e6b39
--- /dev/null
+++ b/tests/RenderScriptTests/Balls/AndroidManifest.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.android.rs.balls">
+ <uses-sdk android:minSdkVersion="14" />
+ <application
+ android:label="RsBalls"
+ android:icon="@drawable/test_pattern">
+ <activity android:name="Balls"
+ android:screenOrientation="landscape">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+</manifest>
diff --git a/tests/RenderScriptTests/Balls/_index.html b/tests/RenderScriptTests/Balls/_index.html
new file mode 100644
index 0000000..8760485
--- /dev/null
+++ b/tests/RenderScriptTests/Balls/_index.html
@@ -0,0 +1 @@
+<p>A brute force physics simulation that renders many balls onto the screen and moves them according to user touch and gravity.</p>
\ No newline at end of file
diff --git a/tests/RenderScriptTests/Balls/res/drawable/flares.png b/tests/RenderScriptTests/Balls/res/drawable/flares.png
new file mode 100644
index 0000000..3a5c970
--- /dev/null
+++ b/tests/RenderScriptTests/Balls/res/drawable/flares.png
Binary files differ
diff --git a/tests/RenderScriptTests/Balls/res/drawable/test_pattern.png b/tests/RenderScriptTests/Balls/res/drawable/test_pattern.png
new file mode 100644
index 0000000..e7d1455
--- /dev/null
+++ b/tests/RenderScriptTests/Balls/res/drawable/test_pattern.png
Binary files differ
diff --git a/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/Balls.java b/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/Balls.java
new file mode 100644
index 0000000..2c6558e
--- /dev/null
+++ b/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/Balls.java
@@ -0,0 +1,118 @@
+/*
+ * 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 com.example.android.rs.balls;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+
+import android.app.Activity;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.provider.Settings.System;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.Window;
+import android.widget.Button;
+import android.widget.ListView;
+
+import android.app.Activity;
+import android.content.Context;
+import android.os.Bundle;
+import android.view.View;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+
+public class Balls extends Activity implements SensorEventListener {
+ //EventListener mListener = new EventListener();
+
+ private static final String LOG_TAG = "libRS_jni";
+ private static final boolean DEBUG = false;
+ private static final boolean LOG_ENABLED = false;
+
+ private BallsView mView;
+ private SensorManager mSensorManager;
+
+ // get the current looper (from your Activity UI thread for instance
+
+
+ public void onSensorChanged(SensorEvent event) {
+ //android.util.Log.d("rs", "sensor: " + event.sensor + ", x: " + event.values[0] + ", y: " + event.values[1] + ", z: " + event.values[2]);
+ synchronized (this) {
+ if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
+ if(mView != null) {
+ mView.setAccel(event.values[0], event.values[1], event.values[2]);
+ }
+ }
+ }
+ }
+
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {
+ }
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
+
+ // Create our Preview view and set it as the content of our
+ // Activity
+ mView = new BallsView(this);
+ setContentView(mView);
+ }
+
+ @Override
+ protected void onResume() {
+ mSensorManager.registerListener(this,
+ mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
+ SensorManager.SENSOR_DELAY_FASTEST);
+
+ // Ideally a game should implement onResume() and onPause()
+ // to take appropriate action when the activity looses focus
+ super.onResume();
+ mView.resume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mView.pause();
+ onStop();
+ }
+
+ @Override
+ protected void onStop() {
+ mSensorManager.unregisterListener(this);
+ super.onStop();
+ }
+
+ static void log(String message) {
+ if (LOG_ENABLED) {
+ Log.v(LOG_TAG, message);
+ }
+ }
+
+
+}
+
diff --git a/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/BallsRS.java b/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/BallsRS.java
new file mode 100644
index 0000000..8cab9b8
--- /dev/null
+++ b/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/BallsRS.java
@@ -0,0 +1,143 @@
+/*
+ * 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 com.example.android.rs.balls;
+
+import android.content.res.Resources;
+import android.renderscript.*;
+import android.util.Log;
+
+public class BallsRS {
+ public static final int PART_COUNT = 900;
+
+ public BallsRS() {
+ }
+
+ private Resources mRes;
+ private RenderScriptGL mRS;
+ private ScriptC_balls mScript;
+ private ScriptC_ball_physics mPhysicsScript;
+ private ProgramFragment mPFLines;
+ private ProgramFragment mPFPoints;
+ private ProgramVertex mPV;
+ private ScriptField_Point mPoints;
+ private ScriptField_VpConsts mVpConsts;
+
+ void updateProjectionMatrices() {
+ mVpConsts = new ScriptField_VpConsts(mRS, 1,
+ Allocation.USAGE_SCRIPT |
+ Allocation.USAGE_GRAPHICS_CONSTANTS);
+ ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item();
+ Matrix4f mvp = new Matrix4f();
+ mvp.loadOrtho(0, mRS.getWidth(), mRS.getHeight(), 0, -1, 1);
+ i.MVP = mvp;
+ mVpConsts.set(i, 0, true);
+ }
+
+ private void createProgramVertex() {
+ updateProjectionMatrices();
+
+ ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS);
+ String t = "varying vec4 varColor;\n" +
+ "void main() {\n" +
+ " vec4 pos = vec4(0.0, 0.0, 0.0, 1.0);\n" +
+ " pos.xy = ATTRIB_position;\n" +
+ " gl_Position = UNI_MVP * pos;\n" +
+ " varColor = vec4(1.0, 1.0, 1.0, 1.0);\n" +
+ " gl_PointSize = ATTRIB_size;\n" +
+ "}\n";
+ sb.setShader(t);
+ sb.addConstant(mVpConsts.getType());
+ sb.addInput(mPoints.getElement());
+ ProgramVertex pvs = sb.create();
+ pvs.bindConstants(mVpConsts.getAllocation(), 0);
+ mRS.bindProgramVertex(pvs);
+ }
+
+ private Allocation loadTexture(int id) {
+ final Allocation allocation =
+ Allocation.createFromBitmapResource(mRS, mRes,
+ id, Allocation.MipmapControl.MIPMAP_NONE,
+ Allocation.USAGE_GRAPHICS_TEXTURE);
+ return allocation;
+ }
+
+ ProgramStore BLEND_ADD_DEPTH_NONE(RenderScript rs) {
+ ProgramStore.Builder builder = new ProgramStore.Builder(rs);
+ builder.setDepthFunc(ProgramStore.DepthFunc.ALWAYS);
+ builder.setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ONE);
+ builder.setDitherEnabled(false);
+ builder.setDepthMaskEnabled(false);
+ return builder.create();
+ }
+
+ public void init(RenderScriptGL rs, Resources res, int width, int height) {
+ mRS = rs;
+ mRes = res;
+
+ ProgramFragmentFixedFunction.Builder pfb = new ProgramFragmentFixedFunction.Builder(rs);
+ pfb.setPointSpriteTexCoordinateReplacement(true);
+ pfb.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,
+ ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
+ pfb.setVaryingColor(true);
+ mPFPoints = pfb.create();
+
+ pfb = new ProgramFragmentFixedFunction.Builder(rs);
+ pfb.setVaryingColor(true);
+ mPFLines = pfb.create();
+
+ android.util.Log.e("rs", "Load texture");
+ mPFPoints.bindTexture(loadTexture(R.drawable.flares), 0);
+
+ mPoints = new ScriptField_Point(mRS, PART_COUNT, Allocation.USAGE_SCRIPT);
+
+ Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);
+ smb.addVertexAllocation(mPoints.getAllocation());
+ smb.addIndexSetType(Mesh.Primitive.POINT);
+ Mesh smP = smb.create();
+
+ mPhysicsScript = new ScriptC_ball_physics(mRS, mRes, R.raw.ball_physics);
+
+ mScript = new ScriptC_balls(mRS, mRes, R.raw.balls);
+ mScript.set_partMesh(smP);
+ mScript.set_physics_script(mPhysicsScript);
+ mScript.bind_point(mPoints);
+ mScript.bind_balls1(new ScriptField_Ball(mRS, PART_COUNT, Allocation.USAGE_SCRIPT));
+ mScript.bind_balls2(new ScriptField_Ball(mRS, PART_COUNT, Allocation.USAGE_SCRIPT));
+
+ mScript.set_gPFLines(mPFLines);
+ mScript.set_gPFPoints(mPFPoints);
+ createProgramVertex();
+
+ mRS.bindProgramStore(BLEND_ADD_DEPTH_NONE(mRS));
+
+ mPhysicsScript.set_gMinPos(new Float2(5, 5));
+ mPhysicsScript.set_gMaxPos(new Float2(width - 5, height - 5));
+
+ mScript.invoke_initParts(width, height);
+
+ mRS.bindRootScript(mScript);
+ }
+
+ public void newTouchPosition(float x, float y, float pressure, int id) {
+ mPhysicsScript.invoke_touch(x, y, pressure, id);
+ }
+
+ public void setAccel(float x, float y) {
+ mPhysicsScript.set_gGravityVector(new Float2(x, y));
+ }
+
+}
diff --git a/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/BallsView.java b/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/BallsView.java
new file mode 100644
index 0000000..b3b3756
--- /dev/null
+++ b/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/BallsView.java
@@ -0,0 +1,116 @@
+/*
+ * 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 com.example.android.rs.balls;
+
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Message;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+
+public class BallsView extends RSSurfaceView {
+
+ public BallsView(Context context) {
+ super(context);
+ //setFocusable(true);
+ }
+
+ private RenderScriptGL mRS;
+ private BallsRS mRender;
+
+ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+ super.surfaceChanged(holder, format, w, h);
+ if (mRS == null) {
+ RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+ mRS = createRenderScriptGL(sc);
+ mRS.setSurface(holder, w, h);
+ mRender = new BallsRS();
+ mRender.init(mRS, getResources(), w, h);
+ }
+ mRender.updateProjectionMatrices();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ if(mRS != null) {
+ mRS = null;
+ destroyRenderScriptGL();
+ }
+ }
+
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev)
+ {
+ int act = ev.getActionMasked();
+ if (act == ev.ACTION_UP) {
+ mRender.newTouchPosition(0, 0, 0, ev.getPointerId(0));
+ return false;
+ } else if (act == MotionEvent.ACTION_POINTER_UP) {
+ // only one pointer going up, we can get the index like this
+ int pointerIndex = ev.getActionIndex();
+ int pointerId = ev.getPointerId(pointerIndex);
+ mRender.newTouchPosition(0, 0, 0, pointerId);
+ return false;
+ }
+ int count = ev.getHistorySize();
+ int pcount = ev.getPointerCount();
+
+ for (int p=0; p < pcount; p++) {
+ int id = ev.getPointerId(p);
+ mRender.newTouchPosition(ev.getX(p),
+ ev.getY(p),
+ ev.getPressure(p),
+ id);
+
+ for (int i=0; i < count; i++) {
+ mRender.newTouchPosition(ev.getHistoricalX(p, i),
+ ev.getHistoricalY(p, i),
+ ev.getHistoricalPressure(p, i),
+ id);
+ }
+ }
+ return true;
+ }
+
+ void setAccel(float x, float y, float z) {
+ if (mRender == null) {
+ return;
+ }
+ mRender.setAccel(x, -y);
+ }
+
+}
+
+
diff --git a/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/ball_physics.rs b/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/ball_physics.rs
new file mode 100644
index 0000000..8a3db6d
--- /dev/null
+++ b/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/ball_physics.rs
@@ -0,0 +1,146 @@
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.rs.balls)
+
+#include "balls.rsh"
+
+float2 gGravityVector = {0.f, 9.8f};
+
+float2 gMinPos = {0.f, 0.f};
+float2 gMaxPos = {1280.f, 700.f};
+
+static float2 touchPos[10];
+static float touchPressure[10];
+
+void touch(float x, float y, float pressure, int id) {
+ if (id >= 10) {
+ return;
+ }
+
+ touchPos[id].x = x;
+ touchPos[id].y = y;
+ touchPressure[id] = pressure;
+}
+
+void root(const Ball_t *ballIn, Ball_t *ballOut, const BallControl_t *ctl, uint32_t x) {
+ float2 fv = {0, 0};
+ float2 pos = ballIn->position;
+
+ int arcID = -1;
+ float arcInvStr = 100000;
+
+ const Ball_t * bPtr = rsGetElementAt(ctl->ain, 0);
+ for (uint32_t xin = 0; xin < ctl->dimX; xin++) {
+ float2 vec = bPtr[xin].position - pos;
+ float2 vec2 = vec * vec;
+ float len2 = vec2.x + vec2.y;
+
+ if (len2 < 10000) {
+ //float minDist = ballIn->size + bPtr[xin].size;
+ float forceScale = ballIn->size * bPtr[xin].size;
+ forceScale *= forceScale;
+
+ if (len2 > 16 /* (minDist*minDist)*/) {
+ // Repulsion
+ float len = sqrt(len2);
+ fv -= (vec / (len * len * len)) * 20000.f * forceScale;
+ } else {
+ if (len2 < 1) {
+ if (xin == x) {
+ continue;
+ }
+ ballOut->delta = 0.f;
+ ballOut->position = ballIn->position;
+ if (xin > x) {
+ ballOut->position.x += 1.f;
+ } else {
+ ballOut->position.x -= 1.f;
+ }
+ //ballOut->color.rgb = 1.f;
+ //ballOut->arcID = -1;
+ //ballOut->arcStr = 0;
+ continue;
+ }
+ // Collision
+ float2 axis = normalize(vec);
+ float e1 = dot(axis, ballIn->delta);
+ float e2 = dot(axis, bPtr[xin].delta);
+ float e = (e1 - e2) * 0.45f;
+ if (e1 > 0) {
+ fv -= axis * e;
+ } else {
+ fv += axis * e;
+ }
+ }
+ }
+ }
+
+ fv /= ballIn->size * ballIn->size * ballIn->size;
+ fv -= gGravityVector * 4.f;
+ fv *= ctl->dt;
+
+ for (int i=0; i < 10; i++) {
+ if (touchPressure[i] > 0.1f) {
+ float2 vec = touchPos[i] - ballIn->position;
+ float2 vec2 = vec * vec;
+ float len2 = max(2.f, vec2.x + vec2.y);
+ fv -= (vec / len2) * touchPressure[i] * 300.f;
+ }
+ }
+
+ ballOut->delta = (ballIn->delta * (1.f - 0.004f)) + fv;
+ ballOut->position = ballIn->position + (ballOut->delta * ctl->dt);
+
+ const float wallForce = 400.f;
+ if (ballOut->position.x > (gMaxPos.x - 20.f)) {
+ float d = gMaxPos.x - ballOut->position.x;
+ if (d < 0.f) {
+ if (ballOut->delta.x > 0) {
+ ballOut->delta.x *= -0.7f;
+ }
+ ballOut->position.x = gMaxPos.x;
+ } else {
+ ballOut->delta.x -= min(wallForce / (d * d), 10.f);
+ }
+ }
+
+ if (ballOut->position.x < (gMinPos.x + 20.f)) {
+ float d = ballOut->position.x - gMinPos.x;
+ if (d < 0.f) {
+ if (ballOut->delta.x < 0) {
+ ballOut->delta.x *= -0.7f;
+ }
+ ballOut->position.x = gMinPos.x + 1.f;
+ } else {
+ ballOut->delta.x += min(wallForce / (d * d), 10.f);
+ }
+ }
+
+ if (ballOut->position.y > (gMaxPos.y - 20.f)) {
+ float d = gMaxPos.y - ballOut->position.y;
+ if (d < 0.f) {
+ if (ballOut->delta.y > 0) {
+ ballOut->delta.y *= -0.7f;
+ }
+ ballOut->position.y = gMaxPos.y;
+ } else {
+ ballOut->delta.y -= min(wallForce / (d * d), 10.f);
+ }
+ }
+
+ if (ballOut->position.y < (gMinPos.y + 20.f)) {
+ float d = ballOut->position.y - gMinPos.y;
+ if (d < 0.f) {
+ if (ballOut->delta.y < 0) {
+ ballOut->delta.y *= -0.7f;
+ }
+ ballOut->position.y = gMinPos.y + 1.f;
+ } else {
+ ballOut->delta.y += min(wallForce / (d * d * d), 10.f);
+ }
+ }
+
+ ballOut->size = ballIn->size;
+
+ //rsDebug("physics pos out", ballOut->position);
+}
+
diff --git a/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/balls.rs b/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/balls.rs
new file mode 100644
index 0000000..dcdd586
--- /dev/null
+++ b/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/balls.rs
@@ -0,0 +1,83 @@
+#pragma version(1)
+#pragma rs java_package_name(com.example.android.rs.balls)
+#include "rs_graphics.rsh"
+
+#include "balls.rsh"
+
+#pragma stateVertex(parent)
+#pragma stateStore(parent)
+
+rs_program_fragment gPFPoints;
+rs_program_fragment gPFLines;
+rs_mesh partMesh;
+
+typedef struct __attribute__((packed, aligned(4))) Point {
+ float2 position;
+ float size;
+} Point_t;
+Point_t *point;
+
+typedef struct VpConsts {
+ rs_matrix4x4 MVP;
+} VpConsts_t;
+VpConsts_t *vpConstants;
+
+rs_script physics_script;
+
+Ball_t *balls1;
+Ball_t *balls2;
+
+static int frame = 0;
+
+void initParts(int w, int h)
+{
+ uint32_t dimX = rsAllocationGetDimX(rsGetAllocation(balls1));
+
+ for (uint32_t ct=0; ct < dimX; ct++) {
+ balls1[ct].position.x = rsRand(0.f, (float)w);
+ balls1[ct].position.y = rsRand(0.f, (float)h);
+ balls1[ct].delta.x = 0.f;
+ balls1[ct].delta.y = 0.f;
+ balls1[ct].size = 1.f;
+
+ float r = rsRand(100.f);
+ if (r > 90.f) {
+ balls1[ct].size += pow(10.f, rsRand(0.f, 2.f)) * 0.07f;
+ }
+ }
+}
+
+
+
+int root() {
+ rsgClearColor(0.f, 0.f, 0.f, 1.f);
+
+ BallControl_t bc;
+ Ball_t *bout;
+
+ if (frame & 1) {
+ bc.ain = rsGetAllocation(balls2);
+ bc.aout = rsGetAllocation(balls1);
+ bout = balls1;
+ } else {
+ bc.ain = rsGetAllocation(balls1);
+ bc.aout = rsGetAllocation(balls2);
+ bout = balls2;
+ }
+
+ bc.dimX = rsAllocationGetDimX(bc.ain);
+ bc.dt = 1.f / 30.f;
+
+ rsForEach(physics_script, bc.ain, bc.aout, &bc, sizeof(bc));
+
+ for (uint32_t ct=0; ct < bc.dimX; ct++) {
+ point[ct].position = bout[ct].position;
+ point[ct].size = 6.f /*+ bout[ct].color.g * 6.f*/ * bout[ct].size;
+ }
+
+ frame++;
+ rsgBindProgramFragment(gPFPoints);
+ rsgDrawMesh(partMesh);
+ return 1;
+}
+
diff --git a/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/balls.rsh b/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/balls.rsh
new file mode 100644
index 0000000..fc886f9
--- /dev/null
+++ b/tests/RenderScriptTests/Balls/src/com/example/android/rs/balls/balls.rsh
@@ -0,0 +1,18 @@
+
+typedef struct __attribute__((packed, aligned(4))) Ball {
+ float2 delta;
+ float2 position;
+ //float3 color;
+ float size;
+ //int arcID;
+ //float arcStr;
+} Ball_t;
+Ball_t *balls;
+
+
+typedef struct BallControl {
+ uint32_t dimX;
+ rs_allocation ain;
+ rs_allocation aout;
+ float dt;
+} BallControl_t;