• 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.nexus;
18 
19 import static android.renderscript.Element.RGBA_8888;
20 import static android.renderscript.Element.RGB_565;
21 import static android.renderscript.ProgramStore.DepthFunc.ALWAYS;
22 import static android.renderscript.Sampler.Value.LINEAR;
23 import static android.renderscript.Sampler.Value.CLAMP;
24 import static android.renderscript.Sampler.Value.WRAP;
25 
26 import com.android.wallpaper.R;
27 import com.android.wallpaper.RenderScriptScene;
28 
29 import android.content.res.Resources;
30 import android.graphics.Bitmap;
31 import android.graphics.BitmapFactory;
32 import android.graphics.Rect;
33 import android.os.Bundle;
34 import android.renderscript.Allocation;
35 import android.renderscript.ProgramFragment;
36 import android.renderscript.ProgramStore;
37 import android.renderscript.ProgramVertex;
38 import android.renderscript.Sampler;
39 import android.renderscript.Script;
40 import android.renderscript.ScriptC;
41 import android.renderscript.Type;
42 import android.renderscript.ProgramStore.BlendDstFunc;
43 import android.renderscript.ProgramStore.BlendSrcFunc;
44 import android.view.SurfaceHolder;
45 
46 import java.util.TimeZone;
47 
48 class NexusRS extends RenderScriptScene {
49 
50     private static final int RSID_STATE = 0;
51 
52     private static final int RSID_COMMAND = 1;
53 
54     private static final int TEXTURES_COUNT = 4;
55 
56     private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
57 
58     private ProgramFragment mPfTexture;
59     private ProgramFragment mPfTexture565;
60 
61     private ProgramFragment mPfColor;
62 
63     private ProgramStore mPsSolid;
64 
65     private ProgramStore mPsBlend;
66 
67     private ProgramVertex mPvOrtho;
68 
69     private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
70 
71     private Sampler mClampSampler;
72     private Sampler mWrapSampler;
73 
74     private Allocation mState;
75 
76     private Type mStateType;
77 
78     private WorldState mWorldState;
79 
80     private Allocation mCommandAllocation;
81 
82     private Type mCommandType;
83 
84     private CommandState mCommand;
85 
86     private Allocation[] mTextures = new Allocation[TEXTURES_COUNT];
87 
NexusRS(int width, int height)88     public NexusRS(int width, int height) {
89         super(width, height);
90 
91         mOptionsARGB.inScaled = false;
92         mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
93     }
94 
95     @Override
setOffset(float xOffset, float yOffset, int xPixels, int yPixels)96     public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
97         mWorldState.xOffset = xOffset;
98         mState.data(mWorldState);
99     }
100 
101     @Override
start()102     public void start() {
103         super.start();
104     }
105 
106     @Override
resize(int width, int height)107     public void resize(int width, int height) {
108         super.resize(width, height); // updates mWidth, mHeight
109 
110         // android.util.Log.d("NexusRS", String.format("resize(%d, %d)", width, height));
111 
112         mWorldState.width = width;
113         mWorldState.height = height;
114         mWorldState.rotate = width > height ? 1 : 0;
115         mState.data(mWorldState);
116 
117         mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
118     }
119 
120     @Override
createScript()121     protected ScriptC createScript() {
122         createProgramVertex();
123         createProgramFragmentStore();
124         createProgramFragment();
125         createState();
126         loadTextures();
127 
128         ScriptC.Builder sb = new ScriptC.Builder(mRS);
129         sb.setType(mStateType, "State", RSID_STATE);
130         sb.setType(mCommandType, "Command", RSID_COMMAND);
131         sb.setScript(mResources, R.raw.nexus);
132         Script.Invokable invokable = sb.addInvokable("initPulses");
133         sb.setRoot(true);
134 
135         ScriptC script = sb.create();
136         script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
137         script.setTimeZone(TimeZone.getDefault().getID());
138 
139         script.bindAllocation(mState, RSID_STATE);
140         script.bindAllocation(mCommandAllocation, RSID_COMMAND);
141 
142         invokable.execute();
143 
144         return script;
145     }
146 
147     static class WorldState {
148         public int width;
149         public int height;
150         public float glWidth;
151         public float glHeight;
152         public int rotate;
153         public int isPreview;
154         public float xOffset;
155         public int mode;
156     }
157 
158     static class CommandState {
159         public int x;
160         public int y;
161         public int command;
162     }
163 
createState()164     private void createState() {
165         mWorldState = new WorldState();
166         mWorldState.width = mWidth;
167         mWorldState.height = mHeight;
168         mWorldState.rotate = mWidth > mHeight ? 1 : 0;
169         mWorldState.isPreview = isPreview() ? 1 : 0;
170 
171         try {
172             mWorldState.mode = mResources.getInteger(R.integer.nexus_mode);
173         } catch (Resources.NotFoundException exc) {
174             mWorldState.mode = 0; // standard nexus mode
175         }
176 
177         mStateType = Type.createFromClass(mRS, WorldState.class, 1, "WorldState");
178         mState = Allocation.createTyped(mRS, mStateType);
179         mState.data(mWorldState);
180 
181         mCommand = new CommandState();
182         mCommand.x = -1;
183         mCommand.y = -1;
184         mCommand.command = 0;
185 
186         mCommandType = Type.createFromClass(mRS, CommandState.class, 1, "DropState");
187         mCommandAllocation = Allocation.createTyped(mRS, mCommandType);
188         mCommandAllocation.data(mCommand);
189     }
190 
loadTextures()191     private void loadTextures() {
192         mTextures[0] = loadTextureARGB(R.drawable.pyramid_background, "TBackground");
193         mTextures[1] = loadTextureARGB(R.drawable.pulse, "TPulse");
194         mTextures[2] = loadTextureARGB(R.drawable.pulse_vert, "TPulseVert");
195         mTextures[3] = loadTextureARGB(R.drawable.glow, "TGlow");
196 
197         final int count = mTextures.length;
198         for (int i = 0; i < count; i++) {
199             mTextures[i].uploadToTexture(0);
200         }
201     }
202 
loadTexture(int id, String name)203     private Allocation loadTexture(int id, String name) {
204         final Allocation allocation = Allocation.createFromBitmapResource(mRS, mResources,
205                 id, RGB_565(mRS), false);
206         allocation.setName(name);
207         return allocation;
208     }
209 
loadTextureARGB(int id, String name)210     private Allocation loadTextureARGB(int id, String name) {
211         Bitmap b = BitmapFactory.decodeResource(mResources, id, mOptionsARGB);
212         final Allocation allocation = Allocation.createFromBitmap(mRS, b, RGBA_8888(mRS), false);
213         allocation.setName(name);
214         return allocation;
215     }
216 
createProgramFragment()217     private void createProgramFragment() {
218         // sampler and program fragment for pulses
219         Sampler.Builder sampleBuilder = new Sampler.Builder(mRS);
220         sampleBuilder.setMin(LINEAR);
221         sampleBuilder.setMag(LINEAR);
222         sampleBuilder.setWrapS(CLAMP);
223         sampleBuilder.setWrapT(CLAMP);
224         mWrapSampler = sampleBuilder.create();
225         ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS);
226         builder.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
227                            ProgramFragment.Builder.Format.RGBA, 0);
228         mPfTexture = builder.create();
229         mPfTexture.setName("PFTexture");
230         mPfTexture.bindSampler(mWrapSampler, 0);
231 
232         builder = new ProgramFragment.Builder(mRS);
233         mPfColor = builder.create();
234         mPfColor.setName("PFColor");
235         mPfColor.bindSampler(mWrapSampler, 0);
236 
237         // sampler and program fragment for background image
238         sampleBuilder.setWrapS(CLAMP);
239         sampleBuilder.setWrapT(CLAMP);
240         mClampSampler = sampleBuilder.create();
241         builder = new ProgramFragment.Builder(mRS);
242         builder.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
243                            ProgramFragment.Builder.Format.RGB, 0);
244         mPfTexture565 = builder.create();
245         mPfTexture565.setName("PFTextureBG");
246         mPfTexture565.bindSampler(mClampSampler, 0);
247     }
248 
createProgramFragmentStore()249     private void createProgramFragmentStore() {
250         ProgramStore.Builder builder = new ProgramStore.Builder(mRS, null, null);
251         builder.setDepthFunc(ALWAYS);
252         builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
253         builder.setDitherEnable(false);
254         builder.setDepthMask(true);
255         mPsSolid = builder.create();
256         mPsSolid.setName("PSSolid");
257 
258         builder = new ProgramStore.Builder(mRS, null, null);
259         builder.setDepthFunc(ALWAYS);
260        //  builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
261         builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
262 
263         builder.setDitherEnable(false);
264         builder.setDepthMask(true);
265         mPsBlend = builder.create();
266         mPsBlend.setName("PSBlend");
267     }
268 
createProgramVertex()269     private void createProgramVertex() {
270         mPvOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS);
271         mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
272 
273         ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
274         pvb.setTextureMatrixEnable(true);
275         mPvOrtho = pvb.create();
276         mPvOrtho.bindAllocation(mPvOrthoAlloc);
277         mPvOrtho.setName("PVOrtho");
278     }
279 
280     @Override
onCommand(String action, int x, int y, int z, Bundle extras, boolean resultRequested)281     public Bundle onCommand(String action, int x, int y, int z, Bundle extras,
282             boolean resultRequested) {
283 
284         final int dw = mWorldState.width;
285         final int bw = 960; // XXX: hardcoded width of background texture
286         if (mWorldState.rotate == 0) {
287             // nexus.rs ignores the xOffset when rotated; we shall endeavor to do so as well
288             x = (int) (x + mWorldState.xOffset * (bw-dw));
289         }
290 
291         // android.util.Log.d("NexusRS", String.format(
292         //     "dw=%d, bw=%d, xOffset=%g, x=%d",
293         //     dw, bw, mWorldState.xOffset, x));
294 
295         if ("android.wallpaper.tap".equals(action)) {
296             sendCommand(1, x, y);
297         } else if ("android.home.drop".equals(action)) {
298             sendCommand(2, x, y);
299         }
300         return null;
301     }
302 
sendCommand(int command, int x, int y)303     private void sendCommand(int command, int x, int y) {
304         mCommand.x = x;
305         mCommand.y = y;
306         mCommand.command = command;
307         mCommandAllocation.data(mCommand);
308     }
309 }
310