• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.magicsmoke;
18 
19 import static android.renderscript.ProgramFragment.EnvMode.REPLACE;
20 import static android.renderscript.Sampler.Value.LINEAR;
21 import static android.renderscript.Sampler.Value.WRAP;
22 
23 import com.android.magicsmoke.R;
24 
25 import android.content.Context;
26 import android.content.SharedPreferences;
27 import android.content.SharedPreferences.Editor;
28 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
29 import android.graphics.Bitmap;
30 import android.graphics.BitmapFactory;
31 import android.media.MediaPlayer;
32 import android.os.Handler;
33 import android.renderscript.Allocation;
34 import android.renderscript.Dimension;
35 import android.renderscript.Element;
36 import android.renderscript.Primitive;
37 import android.renderscript.ProgramFragment;
38 import android.renderscript.ProgramStore;
39 import android.renderscript.ProgramVertex;
40 import android.renderscript.Sampler;
41 import android.renderscript.ScriptC;
42 import android.renderscript.SimpleMesh;
43 import android.renderscript.Type;
44 import android.renderscript.Element.Builder;
45 import android.renderscript.ProgramStore.BlendDstFunc;
46 import android.renderscript.ProgramStore.BlendSrcFunc;
47 import android.util.Log;
48 import android.view.MotionEvent;
49 
50 import java.util.TimeZone;
51 
52 class MagicSmokeRS extends RenderScriptScene implements OnSharedPreferenceChangeListener {
53 
54     static class WorldState {
55         public float mXOffset;
56         public float mTilt;
57         public int   mPreset;
58         public int   mTextureMask;
59         public int   mRotate;
60         public int   mTextureSwap;
61         public int   mProcessTextureMode;
62         public int   mBackCol;
63         public int   mLowCol;
64         public int   mHighCol;
65         public float mAlphaMul;
66         public int   mPreMul;
67         public int   mBlendFunc;
68     }
69     WorldState mWorldState = new WorldState();
70     private Type mStateType;
71     private Allocation mState;
72 
73     private ProgramStore mPfsBackgroundOne;
74     private ProgramStore mPfsBackgroundSrc;
75     private ProgramFragment mPfBackground;
76     private Sampler mSampler;
77     private Allocation[] mSourceTextures;
78     private Allocation[] mRealTextures;
79 
80     private ProgramVertex mPVBackground;
81     private ProgramVertex.MatrixAllocation mPVAlloc;
82 
83     private static final int RSID_STATE = 0;
84     //private static final int RSID_PROGRAMVERTEX = 3;
85     private static final int RSID_NOISESRC1 = 1;
86     private static final int RSID_NOISESRC2 = 2;
87     private static final int RSID_NOISESRC3 = 3;
88     private static final int RSID_NOISESRC4 = 4;
89     private static final int RSID_NOISESRC5 = 5;
90     private static final int RSID_NOISEDST1 = 6;
91     private static final int RSID_NOISEDST2 = 7;
92     private static final int RSID_NOISEDST3 = 8;
93     private static final int RSID_NOISEDST4 = 9;
94     private static final int RSID_NOISEDST5 = 10;
95 
96     private Context mContext;
97     private SharedPreferences mSharedPref;
98 
99     static class Preset {
Preset(int processmode, int backcol, int locol, int hicol, float mul, int mask, boolean rot, int blend, boolean texswap, boolean premul)100         Preset(int processmode, int backcol, int locol, int hicol, float mul, int mask,
101                  boolean rot, int blend, boolean texswap, boolean premul) {
102             mProcessTextureMode = processmode;
103             mBackColor = backcol;
104             mLowColor = locol;
105             mHighColor = hicol;
106             mAlphaMul = mul;
107             mTextureMask = mask;
108             mRotate = rot;
109             mBlendFunc = blend;
110             mTextureSwap = texswap;
111             mPreMul = premul;
112         }
113         public int mProcessTextureMode;
114         public int mBackColor;
115         public int mLowColor;
116         public int mHighColor;
117         public float mAlphaMul;
118         public int mTextureMask;
119         public boolean mRotate;
120         public int mBlendFunc;
121         public boolean mTextureSwap;
122         public boolean mPreMul;
123     }
124 
125     public static final int DEFAULT_PRESET = 4;
126     public static final Preset [] mPreset = new Preset[] {
127         //       proc    back     low       high     alph  mask  rot  blend  swap premul
128         new Preset(1,  0x000000, 0x000000, 0xffffff, 2.0f, 0x0f, true,  0, false, false),
129         new Preset(1,  0x0000ff, 0x000000, 0xffffff, 2.0f, 0x0f, true,  0, false, false),
130         new Preset(1,  0x00ff00, 0x000000, 0xffffff, 2.0f, 0x0f, true,  0, false, false),
131         new Preset(1,  0x00ff00, 0x000000, 0xffffff, 2.0f, 0x0f, true,  0, false, true),
132         new Preset(1,  0x00ff00, 0x00ff00, 0xffffff, 2.5f, 0x1f, true,  0, true, true),
133         new Preset(1,  0x800000, 0xff0000, 0xffffff, 2.5f, 0x1f, true,  0, true,  false),
134         new Preset(0,  0x000000, 0x000000, 0xffffff, 0.0f, 0x1f, true,  0, false, false),
135         new Preset(1,  0x0000ff, 0x00ff00, 0xffff00, 2.0f, 0x1f, true,  0, true,  false),
136         new Preset(1,  0x008000, 0x00ff00, 0xffffff, 2.5f, 0x1f, true,  0, true,  false),
137         new Preset(1,  0x800000, 0xff0000, 0xffffff, 2.5f, 0x1f, true,  0, true, true),
138         new Preset(1,  0x808080, 0x000000, 0xffffff, 2.0f, 0x0f, true,  0, false, true),
139         new Preset(1,  0x0000ff, 0x000000, 0xffffff, 2.0f, 0x0f, true,  0, false, true),
140         new Preset(1,  0x0000ff, 0x00ff00, 0xffff00, 1.5f, 0x1f, false, 0, false, true),
141         new Preset(1,  0x0000ff, 0x00ff00, 0xffff00, 2.0f, 0x1f, true,  0, true, true),
142         new Preset(1,  0x0000ff, 0x00ff00, 0xffff00, 1.5f, 0x1f, true,  0, true, true),
143         new Preset(1,  0x808080, 0x000000, 0xffffff, 2.0f, 0x0f, true,  0, false, false),
144         new Preset(1,  0x000000, 0x000000, 0xffffff, 2.0f, 0x0f, true,  0, true, false),
145         new Preset(2,  0x000000, 0x000070, 0xff2020, 2.5f, 0x1f, true,  0, false, false),
146         new Preset(2,  0x6060ff, 0x000070, 0xffffff, 2.5f, 0x1f, true,  0, false, false),
147         new Preset(3,  0x0000f0, 0x000000, 0xffffff, 2.0f, 0x0f, true,  0, true, false),
148     };
149 
150     private float mTouchY;
151 
MagicSmokeRS(Context context, int width, int height)152     MagicSmokeRS(Context context, int width, int height) {
153         super(width, height);
154         mWidth = width;
155         mHeight = height;
156         mWorldState.mTilt = 0;
157         mContext = context;
158         mSharedPref = mContext.getSharedPreferences("magicsmoke", Context.MODE_PRIVATE);
159         makeNewState();
160     }
161 
onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)162     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
163 
164         makeNewState();
165         mState.data(mWorldState);
166     }
167 
makeNewState()168     void makeNewState() {
169         int p = mSharedPref.getInt("preset", DEFAULT_PRESET);
170         if (p >= mPreset.length) {
171             p = 0;
172         }
173         mWorldState.mPreset = p;
174         mWorldState.mTextureMask = mPreset[p].mTextureMask;
175         mWorldState.mRotate = mPreset[p].mRotate ? 1 : 0;
176         mWorldState.mTextureSwap = mPreset[p].mTextureSwap ? 1 : 0;
177         mWorldState.mProcessTextureMode = mPreset[p].mProcessTextureMode;
178         mWorldState.mBackCol = mPreset[p].mBackColor;
179         mWorldState.mLowCol = mPreset[p].mLowColor;
180         mWorldState.mHighCol = mPreset[p].mHighColor;
181         mWorldState.mAlphaMul = mPreset[p].mAlphaMul;
182         mWorldState.mPreMul = mPreset[p].mPreMul ? 1 : 0;
183         mWorldState.mBlendFunc = mPreset[p].mBlendFunc;
184     }
185 
186     @Override
resize(int width, int height)187     public void resize(int width, int height) {
188         super.resize(width, height);
189         if (mPVAlloc != null) {
190             mPVAlloc.setupProjectionNormalized(width, height);
191         }
192     }
193 
194     @Override
onTouchEvent(MotionEvent event)195     public void onTouchEvent(MotionEvent event) {
196         switch(event.getAction()) {
197             case MotionEvent.ACTION_DOWN:
198                 mTouchY = event.getY();
199                 break;
200             case MotionEvent.ACTION_MOVE:
201                 float dy = event.getY() - mTouchY;
202                 mTouchY += dy;
203                 dy /= 20;
204                 dy += mWorldState.mTilt;
205                 if (dy > 4) {
206                     dy = 4;
207                 } else if (dy < -4) {
208                     dy = -4;
209                 }
210                 mWorldState.mTilt = dy;
211                 mState.data(mWorldState);
212         }
213     }
214 
215     @Override
setOffset(float xOffset, float yOffset, float xStep, float yStep, int xPixels, int yPixels)216     public void setOffset(float xOffset, float yOffset, float xStep, float yStep,
217             int xPixels, int yPixels) {
218         // update our state, then push it to the renderscript
219         mWorldState.mXOffset = xOffset;
220         mState.data(mWorldState);
221     }
222 
223     @Override
stop()224     public void stop() {
225         mSharedPref.unregisterOnSharedPreferenceChangeListener(this);
226         super.stop();
227     }
228 
229     @Override
start()230     public void start() {
231         super.start();
232         mSharedPref.registerOnSharedPreferenceChangeListener(this);
233         makeNewState();
234         mState.data(mWorldState);
235     }
236 
237     float alphafactor;
238     Type mTextureType;
239 
loadBitmap(int id, int index, String name, float alphamul, int lowcol, int highcol)240     void loadBitmap(int id, int index, String name, float alphamul, int lowcol, int highcol) {
241         BitmapFactory.Options opts = new BitmapFactory.Options();
242         opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
243         Bitmap in = BitmapFactory.decodeResource(mResources, id, opts);
244 
245         int pixels[] = new int[65536];
246         in.getPixels(pixels, 0, 256, 0, 0, 256, 256);
247         mRealTextures[index] = Allocation.createTyped(mRS, mTextureType);
248         mSourceTextures[index] = Allocation.createTyped(mRS, mTextureType);
249         mSourceTextures[index].setName(name+"_src");
250         mSourceTextures[index].data(pixels);
251         mRealTextures[index].setName(name);
252         in.recycle();
253     }
254 
loadBitmaps()255     void loadBitmaps() {
256         alphafactor = 1f;
257         float alphamul = mPreset[mWorldState.mPreset].mAlphaMul;
258         int lowcol = mPreset[mWorldState.mPreset].mLowColor;
259         int highcol = mPreset[mWorldState.mPreset].mHighColor;
260         //Log.i("@@@@", "preset " + mWorldState.mPreset + ", mul: " + alphamul +
261         //        ", colors: " + Integer.toHexString(lowcol) + "/" + Integer.toHexString(highcol));
262 
263         // TODO: using different high and low colors for each layer offers some cool effects too
264         loadBitmap(R.drawable.noise1, 0, "Tnoise1", alphamul, lowcol, highcol);
265         loadBitmap(R.drawable.noise2, 1, "Tnoise2", alphamul, lowcol, highcol);
266         loadBitmap(R.drawable.noise3, 2, "Tnoise3", alphamul, lowcol, highcol);
267         loadBitmap(R.drawable.noise4, 3, "Tnoise4", alphamul, lowcol, highcol);
268         loadBitmap(R.drawable.noise5, 4, "Tnoise5", alphamul, lowcol, highcol);
269     }
270 
271     @Override
createScript()272     protected ScriptC createScript() {
273 
274         // Create a renderscript type from a java class. The specified name doesn't
275         // really matter; the name by which we refer to the object in RenderScript
276         // will be specified later.
277         mStateType = Type.createFromClass(mRS, WorldState.class, 1, "WorldState");
278         // Create an allocation from the type we just created.
279         mState = Allocation.createTyped(mRS, mStateType);
280         mState.data(mWorldState);
281 
282         // First set up the coordinate system and such
283         ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
284         mPVBackground = pvb.create();
285         mPVBackground.setName("PVBackground");
286         mPVAlloc = new ProgramVertex.MatrixAllocation(mRS);
287         mPVBackground.bindAllocation(mPVAlloc);
288         mPVAlloc.setupProjectionNormalized(mWidth, mHeight);
289 
290         mSourceTextures = new Allocation[5];
291         mRealTextures = new Allocation[5];
292 
293         Type.Builder tb = new Type.Builder(mRS, Element.RGBA_8888(mRS));
294         tb.add(Dimension.X, 256);
295         tb.add(Dimension.Y, 256);
296         mTextureType = tb.create();
297         loadBitmaps();
298 
299         Sampler.Builder samplerBuilder = new Sampler.Builder(mRS);
300         samplerBuilder.setMin(LINEAR);
301         samplerBuilder.setMag(LINEAR);
302         samplerBuilder.setWrapS(WRAP);
303         samplerBuilder.setWrapT(WRAP);
304         mSampler = samplerBuilder.create();
305 
306         {
307             ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS, null, null);
308             builder.setTexEnable(true, 0);
309             builder.setTexEnvMode(ProgramFragment.EnvMode.MODULATE, 0);
310             mPfBackground = builder.create();
311             mPfBackground.setName("PFBackground");
312             mPfBackground.bindSampler(mSampler, 0);
313         }
314 
315         {
316             ProgramStore.Builder builder = new ProgramStore.Builder(mRS, null, null);
317             builder.setDepthFunc(ProgramStore.DepthFunc.EQUAL);
318             builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
319             builder.setDitherEnable(true); // without dithering there is severe banding
320             builder.setDepthMask(false);
321             mPfsBackgroundOne = builder.create();
322             mPfsBackgroundOne.setName("PFSBackgroundOne");
323             builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
324             mPfsBackgroundSrc = builder.create();
325             mPfsBackgroundSrc.setName("PFSBackgroundSrc");
326         }
327 
328         // Time to create the script
329         ScriptC.Builder sb = new ScriptC.Builder(mRS);
330         // Specify the name by which to refer to the WorldState object in the
331         // renderscript.
332         sb.setType(mStateType, "State", RSID_STATE);
333         sb.setType(mTextureType, "noisesrc1", RSID_NOISESRC1);
334         sb.setType(mTextureType, "noisedst1", RSID_NOISEDST1);
335         sb.setType(mTextureType, "noisesrc2", RSID_NOISESRC2);
336         sb.setType(mTextureType, "noisedst2", RSID_NOISEDST2);
337         sb.setType(mTextureType, "noisesrc3", RSID_NOISESRC3);
338         sb.setType(mTextureType, "noisedst3", RSID_NOISEDST3);
339         sb.setType(mTextureType, "noisesrc4", RSID_NOISESRC4);
340         sb.setType(mTextureType, "noisedst4", RSID_NOISEDST4);
341         sb.setType(mTextureType, "noisesrc5", RSID_NOISESRC5);
342         sb.setType(mTextureType, "noisedst5", RSID_NOISEDST5);
343         sb.setScript(mResources, R.raw.clouds);
344         sb.setRoot(true);
345 
346         ScriptC script = sb.create();
347         script.setClearColor(1.0f, 0.0f, 0.0f, 1.0f);
348         script.setTimeZone(TimeZone.getDefault().getID());
349 
350         script.bindAllocation(mState, RSID_STATE);
351         script.bindAllocation(mSourceTextures[0], RSID_NOISESRC1);
352         script.bindAllocation(mRealTextures[0], RSID_NOISEDST1);
353         script.bindAllocation(mSourceTextures[1], RSID_NOISESRC2);
354         script.bindAllocation(mRealTextures[1], RSID_NOISEDST2);
355         script.bindAllocation(mSourceTextures[2], RSID_NOISESRC3);
356         script.bindAllocation(mRealTextures[2], RSID_NOISEDST3);
357         script.bindAllocation(mSourceTextures[3], RSID_NOISESRC4);
358         script.bindAllocation(mRealTextures[3], RSID_NOISEDST4);
359         script.bindAllocation(mSourceTextures[4], RSID_NOISESRC5);
360         script.bindAllocation(mRealTextures[4], RSID_NOISEDST5);
361         //script.bindAllocation(mPVAlloc.mAlloc, RSID_PROGRAMVERTEX);
362 
363 
364         return script;
365     }
366 }
367