Home | History | Annotate | Download | only in galaxy
      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.galaxy;
     18 
     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;
     39 
     40 import java.util.TimeZone;
     41 
     42 import com.android.wallpaper.R;
     43 import com.android.wallpaper.RenderScriptScene;
     44 
     45 class GalaxyRS extends RenderScriptScene {
     46     private static final int GALAXY_RADIUS = 300;
     47     private static final int PARTICLES_COUNT = 12000;
     48 
     49     private static final int RSID_STATE = 0;
     50     private static final int RSID_PARTICLES_BUFFER = 1;
     51 
     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;
     56 
     57     private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
     58 
     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;
     83 
     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;
     91 
     92     GalaxyRS(int width, int height) {
     93         super(width, height);
     94 
     95         mOptionsARGB.inScaled = false;
     96         mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
     97     }
     98 
     99     @Override
    100     protected ScriptC createScript() {
    101         createScriptStructures();
    102         createProgramVertex();
    103         createProgramRaster();
    104         createProgramFragmentStore();
    105         createProgramFragment();
    106         loadTextures();
    107 
    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);
    113         sb.setRoot(true);
    114 
    115         ScriptC script = sb.create();
    116         script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    117         script.setTimeZone(TimeZone.getDefault().getID());
    118 
    119         script.bindAllocation(mState, RSID_STATE);
    120         script.bindAllocation(mParticlesBuffer, RSID_PARTICLES_BUFFER);
    121         mInitParticles.execute();
    122 
    123         return script;
    124     }
    125 
    126     private void createScriptStructures() {
    127         createState();
    128         createParticlesMesh();
    129     }
    130 
    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();
    138 
    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");
    144 
    145         mParticlesBuffer = mParticlesMesh.createVertexAllocation(vertexSlot);
    146         mParticlesBuffer.setName("ParticlesBuffer");
    147         mParticlesMesh.bindVertexAllocation(mParticlesBuffer, 0);
    148     }
    149 
    150     @Override
    151     public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
    152         mGalaxyState.xOffset = xOffset;
    153         mState.data(mGalaxyState);
    154     }
    155 
    156     @Override
    157     public void resize(int width, int height) {
    158         super.resize(width, height);
    159 
    160         mGalaxyState.width = width;
    161         mGalaxyState.height = height;
    162         mGalaxyState.scale = width > height ? 1 : 0;
    163         mState.data(mGalaxyState);
    164 
    165         mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
    166         mPvProjectionAlloc.setupProjectionNormalized(mWidth, mHeight);
    167 
    168         mInitParticles.execute();
    169     }
    170 
    171     static class GalaxyState {
    172         public int width;
    173         public int height;
    174         public int particlesCount;
    175         public int galaxyRadius;
    176         public float xOffset;
    177         public int isPreview;
    178         public int scale;
    179     }
    180 
    181     private void createState() {
    182         boolean isPreview = isPreview();
    183 
    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;
    191         if (isPreview) {
    192             mGalaxyState.xOffset = 0.5f;
    193         }
    194 
    195         mStateType = Type.createFromClass(mRS, GalaxyState.class, 1, "GalaxyState");
    196         mState = Allocation.createTyped(mRS, mStateType);
    197         mState.data(mGalaxyState);
    198     }
    199 
    200     private void loadTextures() {
    201         mTextures = new Allocation[TEXTURES_COUNT];
    202 
    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");
    207 
    208         final int count = textures.length;
    209         for (int i = 0; i < count; i++) {
    210             textures[i].uploadToTexture(0);
    211         }
    212     }
    213 
    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);
    218         return allocation;
    219     }
    220 
    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);
    226         return allocation;
    227     }
    228 
    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();
    236 
    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);
    243 
    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();
    250 
    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);
    258     }
    259 
    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");
    268 
    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");
    275     }
    276 
    277     private void createProgramVertex() {
    278         mPvOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS);
    279         mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
    280 
    281         ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS, null, null);
    282         mPvBkOrtho = builder.create();
    283         mPvBkOrtho.bindAllocation(mPvOrthoAlloc);
    284         mPvBkOrtho.setName("PVBkOrtho");
    285 
    286         mPvProjectionAlloc = new ProgramVertex.MatrixAllocation(mRS);
    287         mPvProjectionAlloc.setupProjectionNormalized(mWidth, mHeight);
    288 
    289         builder = new ProgramVertex.Builder(mRS, null, null);
    290         mPvBkProj = builder.create();
    291         mPvBkProj.bindAllocation(mPvProjectionAlloc);
    292         mPvBkProj.setName("PVBkProj");
    293 
    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" +
    303                     "  vec4 pos;\n" +
    304                     "  pos.x = t * x + s * y;\n" +
    305                     "  pos.y = s * x - t * y;\n" +
    306                     "  pos.z = ATTRIB_position.z;\n" +
    307                     "  pos.w = 1.0;\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" +
    312                     "}\n";
    313         sb.setShader(t);
    314         sb.addInput(mParticlesMesh.getVertexType(0).getElement());
    315         mPvStars = sb.create();
    316         mPvStars.bindAllocation(mPvProjectionAlloc);
    317         mPvStars.setName("PVStars");
    318     }
    319 
    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());
    325     }
    326 
    327 }
    328