• 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.wallpaper.fall;
18 
19 import android.os.Bundle;
20 import android.renderscript.*;
21 import static android.renderscript.Sampler.Value.LINEAR;
22 import static android.renderscript.Sampler.Value.CLAMP;
23 import static android.renderscript.ProgramStore.DepthFunc.*;
24 import static android.renderscript.ProgramStore.BlendDstFunc;
25 import static android.renderscript.ProgramStore.BlendSrcFunc;
26 import static android.renderscript.Element.*;
27 
28 import android.util.Log;
29 
30 import android.app.WallpaperManager;
31 import android.graphics.BitmapFactory;
32 import android.graphics.Bitmap;
33 import static android.util.MathUtils.*;
34 
35 import java.util.TimeZone;
36 
37 import com.android.wallpaper.R;
38 import com.android.wallpaper.RenderScriptScene;
39 
40 class FallRS extends RenderScriptScene {
41     private static final int MESH_RESOLUTION = 48;
42 
43     private static final int RSID_STATE = 0;
44     private static final int RSID_CONSTANTS = 1;
45     private static final int RSID_DROP = 2;
46 
47     private static final int TEXTURES_COUNT = 2;
48     private static final int RSID_TEXTURE_RIVERBED = 0;
49     private static final int RSID_TEXTURE_LEAVES = 1;
50 
51     private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
52 
53     @SuppressWarnings({"FieldCanBeLocal"})
54     private ProgramFragment mPfBackground;
55     @SuppressWarnings({"FieldCanBeLocal"})
56     private ProgramFragment mPfSky;
57     @SuppressWarnings({"FieldCanBeLocal"})
58     private ProgramStore mPfsBackground;
59     @SuppressWarnings({"FieldCanBeLocal"})
60     private ProgramStore mPfsLeaf;
61     @SuppressWarnings({"FieldCanBeLocal"})
62     private ProgramVertex mPvSky;
63     @SuppressWarnings({"FieldCanBeLocal"})
64     private ProgramVertex mPvWater;
65     private ProgramVertexFixedFunction.Constants mPvOrthoAlloc;
66     @SuppressWarnings({"FieldCanBeLocal"})
67     private Sampler mSampler;
68 
69     private int mMeshWidth;
70     private Allocation mUniformAlloc;
71 
72     private int mMeshHeight;
73     @SuppressWarnings({"FieldCanBeLocal"})
74     private Mesh mMesh;
75     private WorldState mWorldState;
76 
77     private ScriptC_fall mScript;
78 
79     private ScriptField_Constants mConstants;
80 
81     private float mGlHeight;
82 
FallRS(int width, int height)83     public FallRS(int width, int height) {
84         super(width, height);
85 
86         mOptionsARGB.inScaled = false;
87         mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
88     }
89 
90     @Override
setOffset(float xOffset, float yOffset, int xPixels, int yPixels)91     public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
92         mWorldState.xOffset = xOffset;
93         mScript.set_g_xOffset(mWorldState.xOffset);
94     }
95 
96     @Override
onCommand(String action, int x, int y, int z, Bundle extras, boolean resultRequested)97     public Bundle onCommand(String action, int x, int y, int z, Bundle extras,
98             boolean resultRequested) {
99         if (WallpaperManager.COMMAND_TAP.equals(action)
100                 || WallpaperManager.COMMAND_SECONDARY_TAP.equals(action)
101                 || WallpaperManager.COMMAND_DROP.equals(action)) {
102             addDrop(x + (mWorldState.rotate == 0 ? (mWorldState.width * mWorldState.xOffset) : 0), y);
103         }
104         return null;
105     }
106 
107     @Override
start()108     public void start() {
109         super.start();
110         final WorldState worldState = mWorldState;
111         final int width = worldState.width;
112         final int x = width / 4 + (int)(Math.random() * (width / 2));
113         final int y = worldState.height / 4 + (int)(Math.random() * (worldState.height / 2));
114         addDrop(x + (mWorldState.rotate == 0 ? (width * worldState.xOffset) : 0), y);
115     }
116 
117     @Override
resize(int width, int height)118     public void resize(int width, int height) {
119         super.resize(width, height);
120 
121         mWorldState.width = width;
122         mWorldState.height = height;
123         mWorldState.rotate = width > height ? 1 : 0;
124 
125         mScript.set_g_glWidth(mWorldState.width);
126         mScript.set_g_glHeight(mWorldState.height);
127         mScript.set_g_rotate(mWorldState.rotate);
128 
129         mScript.invoke_initLeaves();
130 
131         Matrix4f proj = new Matrix4f();
132         proj.loadProjectionNormalized(mWidth, mHeight);
133         mPvOrthoAlloc.setProjection(proj);
134     }
135 
136     @Override
createScript()137     protected ScriptC createScript() {
138         mScript = new ScriptC_fall(mRS, mResources, R.raw.fall);
139 
140         createMesh();
141         createState();
142         createProgramVertex();
143         createProgramFragmentStore();
144         createProgramFragment();
145         loadTextures();
146 
147         mScript.setTimeZone(TimeZone.getDefault().getID());
148 
149         mScript.bind_g_Constants(mConstants);
150 
151         return mScript;
152     }
153 
createMesh()154     private void createMesh() {
155         Mesh.TriangleMeshBuilder tmb = new Mesh.TriangleMeshBuilder(mRS, 2, 0);
156 
157         final int width = mWidth > mHeight ? mHeight : mWidth;
158         final int height = mWidth > mHeight ? mWidth : mHeight;
159 
160         int wResolution = MESH_RESOLUTION;
161         int hResolution = (int) (MESH_RESOLUTION * height / (float) width);
162 
163         mGlHeight = 2.0f * height / (float) width;
164 
165         wResolution += 2;
166         hResolution += 2;
167 
168         for (int y = 0; y <= hResolution; y++) {
169             final float yOffset = (((float)y / hResolution) * 2.f - 1.f) * height / width;
170             for (int x = 0; x <= wResolution; x++) {
171                 tmb.addVertex(((float)x / wResolution) * 2.f - 1.f, yOffset);
172             }
173         }
174 
175         for (int y = 0; y < hResolution; y++) {
176             final boolean shift = (y & 0x1) == 0;
177             final int yOffset = y * (wResolution + 1);
178             for (int x = 0; x < wResolution; x++) {
179                 final int index = yOffset + x;
180                 final int iWR1 = index + wResolution + 1;
181                 if (shift) {
182                     tmb.addTriangle(index, index + 1, iWR1);
183                     tmb.addTriangle(index + 1, iWR1 + 1, iWR1);
184                 } else {
185                     tmb.addTriangle(index, iWR1 + 1, iWR1);
186                     tmb.addTriangle(index, index + 1, iWR1 + 1);
187                 }
188             }
189         }
190 
191         mMesh = tmb.create(true);
192 
193         mMeshWidth = wResolution + 1;
194         mMeshHeight = hResolution + 1;
195 
196         mScript.set_g_WaterMesh(mMesh);
197     }
198 
199     static class WorldState {
200         public int frameCount;
201         public int width;
202         public int height;
203         public int meshWidth;
204         public int meshHeight;
205         public int rippleIndex;
206         public float glWidth;
207         public float glHeight;
208         public float skySpeedX;
209         public float skySpeedY;
210         public int rotate;
211         public int isPreview;
212         public float xOffset;
213     }
214 
createState()215     private void createState() {
216         mWorldState = new WorldState();
217         mWorldState.width = mWidth;
218         mWorldState.height = mHeight;
219         mWorldState.meshWidth = mMeshWidth;
220         mWorldState.meshHeight = mMeshHeight;
221         mWorldState.rippleIndex = 0;
222         mWorldState.glWidth = 2.0f;
223         mWorldState.glHeight = mGlHeight;
224         mWorldState.skySpeedX = random(-0.001f, 0.001f);
225         mWorldState.skySpeedY = random(0.00008f, 0.0002f);
226         mWorldState.rotate = mWidth > mHeight ? 1 : 0;
227         mWorldState.isPreview = isPreview() ? 1 : 0;
228 
229         mScript.set_g_glWidth(mWorldState.glWidth);
230         mScript.set_g_glHeight(mWorldState.glHeight);
231         mScript.set_g_meshWidth(mWorldState.meshWidth);
232         mScript.set_g_meshHeight(mWorldState.meshHeight);
233         mScript.set_g_xOffset(0);
234         mScript.set_g_rotate(mWorldState.rotate);
235     }
236 
loadTextures()237     private void loadTextures() {
238         mScript.set_g_TLeaves(loadTextureARGB(R.drawable.leaves));
239         mScript.set_g_TRiverbed(loadTexture(R.drawable.pond));
240     }
241 
loadTexture(int id)242     private Allocation loadTexture(int id) {
243         final Allocation allocation = Allocation.createFromBitmapResource(mRS, mResources, id);
244         return allocation;
245     }
246 
loadTextureARGB(int id)247     private Allocation loadTextureARGB(int id) {
248         Bitmap b = BitmapFactory.decodeResource(mResources, id, mOptionsARGB);
249         final Allocation allocation = Allocation.createFromBitmap(mRS, b);
250         return allocation;
251     }
252 
createProgramFragment()253     private void createProgramFragment() {
254         Sampler.Builder sampleBuilder = new Sampler.Builder(mRS);
255         sampleBuilder.setMinification(LINEAR);
256         sampleBuilder.setMagnification(LINEAR);
257         sampleBuilder.setWrapS(CLAMP);
258         sampleBuilder.setWrapT(CLAMP);
259         mSampler = sampleBuilder.create();
260 
261         ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS);
262         builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
263                            ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
264         mPfBackground = builder.create();
265         mPfBackground.bindSampler(mSampler, 0);
266 
267         mScript.set_g_PFBackground(mPfBackground);
268 
269         builder = new ProgramFragmentFixedFunction.Builder(mRS);
270         builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,
271                            ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
272         mPfSky = builder.create();
273         mPfSky.bindSampler(mSampler, 0);
274 
275         mScript.set_g_PFSky(mPfSky);
276     }
277 
createProgramFragmentStore()278     private void createProgramFragmentStore() {
279         ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
280         builder.setDepthFunc(ALWAYS);
281         builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
282         builder.setDitherEnabled(false);
283         builder.setDepthMaskEnabled(true);
284         mPfsBackground = builder.create();
285 
286         builder = new ProgramStore.Builder(mRS);
287         builder.setDepthFunc(ALWAYS);
288         builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
289         builder.setDitherEnabled(false);
290         builder.setDepthMaskEnabled(true);
291         mPfsLeaf = builder.create();
292 
293         mScript.set_g_PFSLeaf(mPfsLeaf);
294         mScript.set_g_PFSBackground(mPfsBackground);
295     }
296 
createProgramVertex()297     private void createProgramVertex() {
298         mPvOrthoAlloc = new ProgramVertexFixedFunction.Constants(mRS);
299         Matrix4f proj = new Matrix4f();
300         proj.loadProjectionNormalized(mWidth, mHeight);
301         mPvOrthoAlloc.setProjection(proj);
302 
303 
304         ProgramVertexFixedFunction.Builder builder = new ProgramVertexFixedFunction.Builder(mRS);
305         mPvSky = builder.create();
306         ((ProgramVertexFixedFunction)mPvSky).bindConstants(mPvOrthoAlloc);
307 
308         mScript.set_g_PVSky(mPvSky);
309 
310         mConstants = new ScriptField_Constants(mRS, 1);
311         mUniformAlloc = mConstants.getAllocation();
312 
313         ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS);
314 
315         String t = "\n" +
316                 "varying vec4 varColor;\n" +
317                 "varying vec2 varTex0;\n" +
318 
319                 "vec2 addDrop(vec4 d, vec2 pos, float dxMul) {\n" +
320                 "  vec2 ret = vec2(0.0, 0.0);\n" +
321                 "  vec2 delta = d.xy - pos;\n" +
322                 "  delta.x *= dxMul;\n" +
323                 "  float dist = length(delta);\n" +
324                 "  if (dist < d.w) { \n" +
325                 "    float amp = d.z * dist;\n" +
326                 "    amp /= d.w * d.w;\n" +
327                 "    amp *= sin(d.w - dist);\n" +
328                 "    ret = delta * amp;\n" +
329                 "  }\n" +
330                 "  return ret;\n" +
331                 "}\n" +
332 
333                 "void main() {\n" +
334                 "  vec2 pos = ATTRIB_position.xy;\n" +
335                 "  gl_Position = vec4(pos.x, pos.y, 0.0, 1.0);\n" +
336                 "  float dxMul = 1.0;\n" +
337 
338                 "  varTex0 = vec2((pos.x + 1.0), (pos.y + 1.6666));\n" +
339 
340                 "  if (UNI_Rotate < 0.9) {\n" +
341                 "    varTex0.xy *= vec2(0.25, 0.33);\n" +
342                 "    varTex0.x += UNI_Offset.x * 0.5;\n" +
343                 "    pos.x += UNI_Offset.x * 2.0;\n" +
344                 "  } else {\n" +
345                 "    varTex0.xy *= vec2(0.5, 0.3125);\n" +
346                 "    dxMul = 2.5;\n" +
347                 "  }\n" +
348 
349                 "  varColor = vec4(1.0, 1.0, 1.0, 1.0);\n" +
350                 "  pos.xy += vec2(1.0, 1.0);\n" +
351                 "  pos.xy *= vec2(25.0, 42.0);\n" +
352 
353                 "  varTex0.xy += addDrop(UNI_Drop01, pos, dxMul);\n" +
354                 "  varTex0.xy += addDrop(UNI_Drop02, pos, dxMul);\n" +
355                 "  varTex0.xy += addDrop(UNI_Drop03, pos, dxMul);\n" +
356                 "  varTex0.xy += addDrop(UNI_Drop04, pos, dxMul);\n" +
357                 "  varTex0.xy += addDrop(UNI_Drop05, pos, dxMul);\n" +
358                 "  varTex0.xy += addDrop(UNI_Drop06, pos, dxMul);\n" +
359                 "  varTex0.xy += addDrop(UNI_Drop07, pos, dxMul);\n" +
360                 "  varTex0.xy += addDrop(UNI_Drop08, pos, dxMul);\n" +
361                 "  varTex0.xy += addDrop(UNI_Drop09, pos, dxMul);\n" +
362                 "  varTex0.xy += addDrop(UNI_Drop10, pos, dxMul);\n" +
363                 "}\n";
364 
365         sb.setShader(t);
366         sb.addConstant(mUniformAlloc.getType());
367         sb.addInput(mMesh.getVertexAllocation(0).getType().getElement());
368         mPvWater = sb.create();
369         mPvWater.bindConstants(mUniformAlloc, 0);
370 
371         mScript.set_g_PVWater(mPvWater);
372 
373     }
374 
addDrop(float x, float y)375     void addDrop(float x, float y) {
376         int dropX = (int) ((x / mWidth) * mMeshWidth);
377         int dropY = (int) ((y / mHeight) * mMeshHeight);
378 
379         mScript.invoke_addDrop(dropX, dropY);
380     }
381 }
382