Home | History | Annotate | Download | only in nexus
      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.app.WallpaperManager;
     30 import android.content.res.Resources;
     31 import android.graphics.Bitmap;
     32 import android.graphics.BitmapFactory;
     33 import android.graphics.Rect;
     34 import android.os.Bundle;
     35 import android.renderscript.*;
     36 import android.renderscript.ProgramStore.BlendDstFunc;
     37 import android.renderscript.ProgramStore.BlendSrcFunc;
     38 import android.view.SurfaceHolder;
     39 
     40 import java.util.TimeZone;
     41 
     42 class NexusRS extends RenderScriptScene {
     43     private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
     44 
     45     private ProgramVertexFixedFunction.Constants mPvOrthoAlloc;
     46 
     47     private int mInitialWidth;
     48     private int mInitialHeight;
     49     private float mWorldScaleX;
     50     private float mWorldScaleY;
     51     private float mXOffset;
     52     private ScriptC_nexus mScript;
     53 
     54     public NexusRS(int width, int height) {
     55         super(width, height);
     56 
     57         mInitialWidth = width;
     58         mInitialHeight = height;
     59         mWorldScaleX = 1.0f;
     60         mWorldScaleY = 1.0f;
     61 
     62         mOptionsARGB.inScaled = false;
     63         mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
     64     }
     65 
     66     @Override
     67     public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
     68         mXOffset = xOffset;
     69         mScript.set_gXOffset(xOffset);
     70     }
     71 
     72     @Override
     73     public void start() {
     74         super.start();
     75     }
     76 
     77     @Override
     78     public void resize(int width, int height) {
     79         super.resize(width, height); // updates mWidth, mHeight
     80 
     81         // android.util.Log.d("NexusRS", String.format("resize(%d, %d)", width, height));
     82 
     83         mWorldScaleX = (float)mInitialWidth / width;
     84         mWorldScaleY = (float)mInitialHeight / height;
     85         mScript.set_gWorldScaleX(mWorldScaleX);
     86         mScript.set_gWorldScaleY(mWorldScaleY);
     87     }
     88 
     89     @Override
     90     protected ScriptC createScript() {
     91         mScript = new ScriptC_nexus(mRS, mResources, R.raw.nexus);
     92 
     93         createProgramFragmentStore();
     94         createProgramFragment();
     95         createProgramVertex();
     96         createState();
     97 
     98         mScript.set_gTBackground(loadTexture(R.drawable.pyramid_background));
     99         mScript.set_gTPulse(loadTextureARGB(R.drawable.pulse));
    100         mScript.set_gTGlow(loadTextureARGB(R.drawable.glow));
    101         mScript.setTimeZone(TimeZone.getDefault().getID());
    102         mScript.invoke_initPulses();
    103         return mScript;
    104     }
    105 
    106     private void createState() {
    107         int mode;
    108         try {
    109             mode = mResources.getInteger(R.integer.nexus_mode);
    110         } catch (Resources.NotFoundException exc) {
    111             mode = 0; // standard nexus mode
    112         }
    113 
    114         mScript.set_gIsPreview(isPreview() ? 1 : 0);
    115         mScript.set_gMode(mode);
    116         mScript.set_gXOffset(0.f);
    117         mScript.set_gWorldScaleX(mWorldScaleX);
    118         mScript.set_gWorldScaleY(mWorldScaleY);
    119     }
    120 
    121     private Allocation loadTexture(int id) {
    122         return Allocation.createFromBitmapResource(mRS, mResources, id,
    123                                            Allocation.MipmapControl.MIPMAP_NONE,
    124                                            Allocation.USAGE_GRAPHICS_TEXTURE);
    125     }
    126 
    127     private Allocation loadTextureARGB(int id) {
    128         Bitmap b = BitmapFactory.decodeResource(mResources, id, mOptionsARGB);
    129         return Allocation.createFromBitmap(mRS, b,
    130                                            Allocation.MipmapControl.MIPMAP_NONE,
    131                                            Allocation.USAGE_GRAPHICS_TEXTURE);
    132     }
    133 
    134 
    135     private void createProgramFragment() {
    136         // sampler and program fragment for pulses
    137         ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS);
    138         builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,
    139                            ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
    140         ProgramFragment pft = builder.create();
    141         pft.bindSampler(Sampler.WRAP_LINEAR(mRS), 0);
    142         mScript.set_gPFTexture(pft);
    143 
    144         // sampler and program fragment for background image
    145         builder = new ProgramFragmentFixedFunction.Builder(mRS);
    146         builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,
    147                            ProgramFragmentFixedFunction.Builder.Format.RGB, 0);
    148         ProgramFragment pft565 = builder.create();
    149         pft565.bindSampler(Sampler.CLAMP_NEAREST(mRS), 0);
    150         mScript.set_gPFTexture565(pft565);
    151     }
    152 
    153     private void createProgramFragmentStore() {
    154         ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
    155         builder.setDepthFunc(ALWAYS);
    156         builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
    157         builder.setDitherEnabled(false);
    158         ProgramStore solid = builder.create();
    159         mRS.bindProgramStore(solid);
    160 
    161         builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
    162         mScript.set_gPSBlend(builder.create());
    163     }
    164 
    165     private void createProgramVertex() {
    166         mPvOrthoAlloc = new ProgramVertexFixedFunction.Constants(mRS);
    167         Matrix4f proj = new Matrix4f();
    168         proj.loadOrthoWindow(mWidth, mHeight);
    169         mPvOrthoAlloc.setProjection(proj);
    170 
    171         ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
    172         pvb.setTextureMatrixEnable(true);
    173         ProgramVertex pv = pvb.create();
    174         ((ProgramVertexFixedFunction)pv).bindConstants(mPvOrthoAlloc);
    175         mRS.bindProgramVertex(pv);
    176     }
    177 
    178     @Override
    179     public Bundle onCommand(String action, int x, int y, int z, Bundle extras,
    180             boolean resultRequested) {
    181 
    182         if (mWidth < mHeight) {
    183             // nexus.rs ignores the xOffset when rotated; we shall endeavor to do so as well
    184             x = (int) (x + mXOffset * mWidth / mWorldScaleX);
    185         }
    186 
    187         // android.util.Log.d("NexusRS", String.format(
    188         //     "dw=%d, bw=%d, xOffset=%g, x=%d",
    189         //     dw, bw, mWorldState.xOffset, x));
    190 
    191         if (WallpaperManager.COMMAND_TAP.equals(action)
    192                 || WallpaperManager.COMMAND_SECONDARY_TAP.equals(action)
    193                 || WallpaperManager.COMMAND_DROP.equals(action)) {
    194             mScript.invoke_addTap(x, y);
    195         }
    196         return null;
    197     }
    198 }
    199