2 * Copyright (C) 2009 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.wallpaper.galaxy;
19 import android.renderscript.ScriptC;
20 import android.renderscript.ProgramFragment;
21 import android.renderscript.ProgramStore;
22 import android.renderscript.ProgramVertex;
23 import android.renderscript.ProgramRaster;
24 import android.renderscript.Allocation;
25 import android.renderscript.Sampler;
26 import android.renderscript.Element;
27 import android.renderscript.SimpleMesh;
28 import android.renderscript.Primitive;
29 import android.renderscript.Type;
30 import static android.renderscript.Sampler.Value.LINEAR;
31 import static android.renderscript.Sampler.Value.NEAREST;
32 import static android.renderscript.Sampler.Value.WRAP;
33 import static android.renderscript.ProgramStore.DepthFunc.*;
34 import static android.renderscript.ProgramStore.BlendDstFunc;
35 import static android.renderscript.ProgramStore.BlendSrcFunc;
36 import static android.renderscript.Element.*;
37 import android.graphics.Bitmap;
38 import android.graphics.BitmapFactory;
40 import java.util.TimeZone;
42 import com.android.wallpaper.R;
43 import com.android.wallpaper.RenderScriptScene;
45 class GalaxyRS extends RenderScriptScene {
46 private static final int GALAXY_RADIUS = 300;
47 private static final int PARTICLES_COUNT = 12000;
49 private static final int RSID_STATE = 0;
50 private static final int RSID_PARTICLES_BUFFER = 1;
52 private static final int TEXTURES_COUNT = 3;
53 private static final int RSID_TEXTURE_SPACE = 0;
54 private static final int RSID_TEXTURE_LIGHT1 = 1;
55 private static final int RSID_TEXTURE_FLARES = 2;
57 private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
59 @SuppressWarnings({"FieldCanBeLocal"})
60 private ProgramFragment mPfBackground;
61 @SuppressWarnings({"FieldCanBeLocal"})
62 private ProgramFragment mPfStars;
63 @SuppressWarnings({"FieldCanBeLocal"})
64 private ProgramStore mPfsBackground;
65 @SuppressWarnings({"FieldCanBeLocal"})
66 private ProgramStore mPfsLights;
67 @SuppressWarnings({"FieldCanBeLocal"})
68 private ProgramVertex mPvBkOrtho;
69 @SuppressWarnings({"FieldCanBeLocal"})
70 private ProgramVertex mPvBkProj;
71 @SuppressWarnings({"FieldCanBeLocal"})
72 private ProgramVertex mPvStars;
73 @SuppressWarnings({"FieldCanBeLocal"})
74 private Sampler mSampler;
75 @SuppressWarnings({"FieldCanBeLocal"})
76 private Sampler mStarSampler;
77 @SuppressWarnings({"FieldCanBeLocal"})
78 private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
79 @SuppressWarnings({"FieldCanBeLocal"})
80 private ProgramVertex.MatrixAllocation mPvProjectionAlloc;
81 @SuppressWarnings({"FieldCanBeLocal"})
82 private Allocation[] mTextures;
84 private GalaxyState mGalaxyState;
85 private Type mStateType;
86 private Allocation mState;
87 private Allocation mParticlesBuffer;
88 @SuppressWarnings({"FieldCanBeLocal"})
89 private SimpleMesh mParticlesMesh;
90 private ScriptC.Invokable mInitParticles;
92 GalaxyRS(int width, int height) {
95 mOptionsARGB.inScaled = false;
96 mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
100 protected ScriptC createScript() {
101 createScriptStructures();
102 createProgramVertex();
103 createProgramRaster();
104 createProgramFragmentStore();
105 createProgramFragment();
108 ScriptC.Builder sb = new ScriptC.Builder(mRS);
109 sb.setType(mStateType, "State", RSID_STATE);
110 sb.setType(mParticlesMesh.getVertexType(0), "Particles", RSID_PARTICLES_BUFFER);
111 mInitParticles = sb.addInvokable("initParticles");
112 sb.setScript(mResources, R.raw.galaxy);
115 ScriptC script = sb.create();
116 script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
117 script.setTimeZone(TimeZone.getDefault().getID());
119 script.bindAllocation(mState, RSID_STATE);
120 script.bindAllocation(mParticlesBuffer, RSID_PARTICLES_BUFFER);
121 mInitParticles.execute();
126 private void createScriptStructures() {
128 createParticlesMesh();
131 private void createParticlesMesh() {
132 final Builder elementBuilder = new Builder(mRS);
133 elementBuilder.add(Element.createAttrib(mRS, Element.DataType.UNSIGNED_8,
134 Element.DataKind.USER, 4), "color");
135 elementBuilder.add(Element.createAttrib(mRS, Element.DataType.FLOAT_32,
136 Element.DataKind.USER, 3), "position");
137 final Element vertexElement = elementBuilder.create();
139 final SimpleMesh.Builder meshBuilder = new SimpleMesh.Builder(mRS);
140 final int vertexSlot = meshBuilder.addVertexType(vertexElement, PARTICLES_COUNT);
141 meshBuilder.setPrimitive(Primitive.POINT);
142 mParticlesMesh = meshBuilder.create();
143 mParticlesMesh.setName("ParticlesMesh");
145 mParticlesBuffer = mParticlesMesh.createVertexAllocation(vertexSlot);
146 mParticlesBuffer.setName("ParticlesBuffer");
147 mParticlesMesh.bindVertexAllocation(mParticlesBuffer, 0);
151 public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
152 mGalaxyState.xOffset = xOffset;
153 mState.data(mGalaxyState);
157 public void resize(int width, int height) {
158 super.resize(width, height);
160 mGalaxyState.width = width;
161 mGalaxyState.height = height;
162 mGalaxyState.scale = width > height ? 1 : 0;
163 mState.data(mGalaxyState);
165 mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
166 mPvProjectionAlloc.setupProjectionNormalized(mWidth, mHeight);
168 mInitParticles.execute();
171 static class GalaxyState {
174 public int particlesCount;
175 public int galaxyRadius;
176 public float xOffset;
177 public int isPreview;
181 private void createState() {
182 boolean isPreview = isPreview();
184 mGalaxyState = new GalaxyState();
185 mGalaxyState.width = mWidth;
186 mGalaxyState.height = mHeight;
187 mGalaxyState.scale = mWidth > mHeight ? 1 : 0;
188 mGalaxyState.particlesCount = PARTICLES_COUNT;
189 mGalaxyState.galaxyRadius = GALAXY_RADIUS;
190 mGalaxyState.isPreview = isPreview ? 1 : 0;
192 mGalaxyState.xOffset = 0.5f;
195 mStateType = Type.createFromClass(mRS, GalaxyState.class, 1, "GalaxyState");
196 mState = Allocation.createTyped(mRS, mStateType);
197 mState.data(mGalaxyState);
200 private void loadTextures() {
201 mTextures = new Allocation[TEXTURES_COUNT];
203 final Allocation[] textures = mTextures;
204 textures[RSID_TEXTURE_SPACE] = loadTexture(R.drawable.space, "TSpace");
205 textures[RSID_TEXTURE_LIGHT1] = loadTexture(R.drawable.light1, "TLight1");
206 textures[RSID_TEXTURE_FLARES] = loadTextureARGB(R.drawable.flares, "TFlares");
208 final int count = textures.length;
209 for (int i = 0; i < count; i++) {
210 textures[i].uploadToTexture(0);
214 private Allocation loadTexture(int id, String name) {
215 final Allocation allocation = Allocation.createFromBitmapResource(mRS, mResources,
216 id, RGB_565(mRS), false);
217 allocation.setName(name);
221 // TODO: Fix Allocation.createFromBitmapResource() to do this when RGBA_8888 is specified
222 private Allocation loadTextureARGB(int id, String name) {
223 Bitmap b = BitmapFactory.decodeResource(mResources, id, mOptionsARGB);
224 final Allocation allocation = Allocation.createFromBitmap(mRS, b, RGBA_8888(mRS), false);
225 allocation.setName(name);
229 private void createProgramFragment() {
230 Sampler.Builder samplerBuilder = new Sampler.Builder(mRS);
231 samplerBuilder.setMin(NEAREST);
232 samplerBuilder.setMag(NEAREST);
233 samplerBuilder.setWrapS(WRAP);
234 samplerBuilder.setWrapT(WRAP);
235 mSampler = samplerBuilder.create();
237 ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS);
238 builder.setTexture(ProgramFragment.Builder.EnvMode.REPLACE,
239 ProgramFragment.Builder.Format.RGB, 0);
240 mPfBackground = builder.create();
241 mPfBackground.setName("PFBackground");
242 mPfBackground.bindSampler(mSampler, 0);
244 samplerBuilder = new Sampler.Builder(mRS);
245 samplerBuilder.setMin(LINEAR);
246 samplerBuilder.setMag(LINEAR);
247 samplerBuilder.setWrapS(WRAP);
248 samplerBuilder.setWrapT(WRAP);
249 mStarSampler = samplerBuilder.create();
251 builder = new ProgramFragment.Builder(mRS);
252 builder.setPointSpriteTexCoordinateReplacement(true);
253 builder.setTexture(ProgramFragment.Builder.EnvMode.MODULATE,
254 ProgramFragment.Builder.Format.RGBA, 0);
255 mPfStars = builder.create();
256 mPfStars.setName("PFStars");
257 mPfBackground.bindSampler(mStarSampler, 0);
260 private void createProgramFragmentStore() {
261 ProgramStore.Builder builder = new ProgramStore.Builder(mRS, null, null);
262 builder.setDepthFunc(ALWAYS);
263 builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
264 builder.setDitherEnable(false);
265 builder.setDepthMask(false);
266 mPfsBackground = builder.create();
267 mPfsBackground.setName("PFSBackground");
269 builder = new ProgramStore.Builder(mRS, null, null);
270 builder.setDepthFunc(ALWAYS);
271 builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
272 builder.setDitherEnable(false);
273 mPfsLights = builder.create();
274 mPfsLights.setName("PFSLights");
277 private void createProgramVertex() {
278 mPvOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS);
279 mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
281 ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS, null, null);
282 mPvBkOrtho = builder.create();
283 mPvBkOrtho.bindAllocation(mPvOrthoAlloc);
284 mPvBkOrtho.setName("PVBkOrtho");
286 mPvProjectionAlloc = new ProgramVertex.MatrixAllocation(mRS);
287 mPvProjectionAlloc.setupProjectionNormalized(mWidth, mHeight);
289 builder = new ProgramVertex.Builder(mRS, null, null);
290 mPvBkProj = builder.create();
291 mPvBkProj.bindAllocation(mPvProjectionAlloc);
292 mPvBkProj.setName("PVBkProj");
294 ProgramVertex.ShaderBuilder sb = new ProgramVertex.ShaderBuilder(mRS);
295 String t = "void main() {\n" +
296 " float dist = ATTRIB_position.y;\n" +
297 " float angle = ATTRIB_position.x;\n" +
298 " float x = dist * sin(angle);\n" +
299 " float y = dist * cos(angle) * 0.892;\n" +
300 " float p = dist * 5.5;\n" +
301 " float s = cos(p);\n" +
302 " float t = sin(p);\n" +
304 " pos.x = t * x + s * y;\n" +
305 " pos.y = s * x - t * y;\n" +
306 " pos.z = ATTRIB_position.z;\n" +
308 " gl_Position = UNI_MVP * pos;\n" +
309 " gl_PointSize = ATTRIB_color.a * 10.0;\n" +
310 " varColor.rgb = ATTRIB_color.rgb;\n" +
311 " varColor.a = 1.0;\n" +
314 sb.addInput(mParticlesMesh.getVertexType(0).getElement());
315 mPvStars = sb.create();
316 mPvStars.bindAllocation(mPvProjectionAlloc);
317 mPvStars.setName("PVStars");
320 private void createProgramRaster() {
321 ProgramRaster.Builder b = new ProgramRaster.Builder(mRS, null, null);
322 b.setPointSmoothEnable(true);
323 b.setPointSpriteEnable(true);
324 mRS.contextBindProgramRaster(b.create());