1af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron/*
2af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron * Copyright (C) 2009 The Android Open Source Project
3af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron *
4af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron * Licensed under the Apache License, Version 2.0 (the "License");
5af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron * you may not use this file except in compliance with the License.
6af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron * You may obtain a copy of the License at
7af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron *
8af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron *      http://www.apache.org/licenses/LICENSE-2.0
9af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron *
10af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron * Unless required by applicable law or agreed to in writing, software
11af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron * distributed under the License is distributed on an "AS IS" BASIS,
12af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron * See the License for the specific language governing permissions and
14af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron * limitations under the License.
15af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron */
16af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
17af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronpackage com.android.wallpaper.nexus;
18af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
19af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronimport static android.renderscript.Element.RGBA_8888;
20af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronimport static android.renderscript.Element.RGB_565;
21af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronimport static android.renderscript.ProgramStore.DepthFunc.ALWAYS;
22af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronimport static android.renderscript.Sampler.Value.LINEAR;
236a500a1d5e15bd5a563995f31d0796552cc13640Jason Samsimport static android.renderscript.Sampler.Value.CLAMP;
24af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronimport static android.renderscript.Sampler.Value.WRAP;
25af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
26af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronimport com.android.wallpaper.R;
27af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronimport com.android.wallpaper.RenderScriptScene;
28af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
29843c77f4841670c95284c7243d61f5d77f6e5ff7Jeff Brownimport android.app.WallpaperManager;
306a500a1d5e15bd5a563995f31d0796552cc13640Jason Samsimport android.content.res.Resources;
31af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronimport android.graphics.Bitmap;
32af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronimport android.graphics.BitmapFactory;
33af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronimport android.graphics.Rect;
34af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronimport android.os.Bundle;
3576faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchoukimport android.renderscript.*;
36af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronimport android.renderscript.ProgramStore.BlendDstFunc;
37af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronimport android.renderscript.ProgramStore.BlendSrcFunc;
38af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronimport android.view.SurfaceHolder;
39af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
40af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronimport java.util.TimeZone;
41af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
42af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleronclass NexusRS extends RenderScriptScene {
43af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
44af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
4576faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchouk    private ProgramVertexFixedFunction.Constants mPvOrthoAlloc;
46af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
478aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams    private float mXOffset;
485f5044f59065ac339b175bb8a47ea6be861f925cStephen Hines    private ScriptC_nexus mScript;
49c27d65349acd38f6ee8fd74bb01518062b0c0b0dJason Sams
50af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    public NexusRS(int width, int height) {
51af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron        super(width, height);
52af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
53af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron        mOptionsARGB.inScaled = false;
54af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron        mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
55af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    }
56af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
57af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    @Override
58af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
598aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        mXOffset = xOffset;
608aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        mScript.set_gXOffset(xOffset);
61af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    }
62c27d65349acd38f6ee8fd74bb01518062b0c0b0dJason Sams
63af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    @Override
64af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    public void start() {
65af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron        super.start();
66af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    }
67af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
68af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    @Override
69af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    public void resize(int width, int height) {
7012290bd7369db1e81b2dd67be67ef0d4b292b412Daniel Sandler        super.resize(width, height); // updates mWidth, mHeight
7112290bd7369db1e81b2dd67be67ef0d4b292b412Daniel Sandler
7212290bd7369db1e81b2dd67be67ef0d4b292b412Daniel Sandler        // android.util.Log.d("NexusRS", String.format("resize(%d, %d)", width, height));
73af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    }
74af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
75af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    @Override
76af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    protected ScriptC createScript() {
7776469b31f1bda22057330a0146d9296df92b9094Jason Sams        mScript = new ScriptC_nexus(mRS, mResources, R.raw.nexus);
788aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams
79af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron        createProgramFragmentStore();
80af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron        createProgramFragment();
818aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        createProgramVertex();
82af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron        createState();
83af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
848aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        mScript.set_gTBackground(loadTexture(R.drawable.pyramid_background));
858aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        mScript.set_gTPulse(loadTextureARGB(R.drawable.pulse));
868aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        mScript.set_gTGlow(loadTextureARGB(R.drawable.glow));
878aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        mScript.setTimeZone(TimeZone.getDefault().getID());
88bf23d3de3fa86c24f382723f861863d4c274dc3bJason Sams        mScript.invoke_initPulses();
898aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        return mScript;
90af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    }
91af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
92af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    private void createState() {
938aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        int mode;
946a500a1d5e15bd5a563995f31d0796552cc13640Jason Sams        try {
958aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams            mode = mResources.getInteger(R.integer.nexus_mode);
966a500a1d5e15bd5a563995f31d0796552cc13640Jason Sams        } catch (Resources.NotFoundException exc) {
978aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams            mode = 0; // standard nexus mode
986a500a1d5e15bd5a563995f31d0796552cc13640Jason Sams        }
996a500a1d5e15bd5a563995f31d0796552cc13640Jason Sams
1008aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        mScript.set_gIsPreview(isPreview() ? 1 : 0);
1018aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        mScript.set_gMode(mode);
1028aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        mScript.set_gXOffset(0.f);
103af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    }
104af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
1058aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams    private Allocation loadTexture(int id) {
106bbcb547467bd09da372a15ac235e239c6557289bJason Sams        return Allocation.createFromBitmapResource(mRS, mResources, id);
107af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    }
108af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
1098aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams    private Allocation loadTextureARGB(int id) {
110af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron        Bitmap b = BitmapFactory.decodeResource(mResources, id, mOptionsARGB);
111bbcb547467bd09da372a15ac235e239c6557289bJason Sams        return Allocation.createFromBitmap(mRS, b);
112af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    }
113af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
1148aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams
115af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    private void createProgramFragment() {
1166a500a1d5e15bd5a563995f31d0796552cc13640Jason Sams        // sampler and program fragment for pulses
11776faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchouk        ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS);
11876faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchouk        builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,
11976faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchouk                           ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
1208aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        ProgramFragment pft = builder.create();
1218aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        pft.bindSampler(Sampler.WRAP_LINEAR(mRS), 0);
1228aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        mScript.set_gPFTexture(pft);
1236a500a1d5e15bd5a563995f31d0796552cc13640Jason Sams
1246a500a1d5e15bd5a563995f31d0796552cc13640Jason Sams        // sampler and program fragment for background image
12576faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchouk        builder = new ProgramFragmentFixedFunction.Builder(mRS);
12676faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchouk        builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,
12776faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchouk                           ProgramFragmentFixedFunction.Builder.Format.RGB, 0);
1288aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        ProgramFragment pft565 = builder.create();
1298aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        pft565.bindSampler(Sampler.CLAMP_NEAREST(mRS), 0);
1308aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        mScript.set_gPFTexture565(pft565);
131af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    }
132af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
133af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    private void createProgramFragmentStore() {
13476faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchouk        ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
135af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron        builder.setDepthFunc(ALWAYS);
136af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron        builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
13776faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchouk        builder.setDitherEnabled(false);
1388aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        ProgramStore solid = builder.create();
13976469b31f1bda22057330a0146d9296df92b9094Jason Sams        mRS.bindProgramStore(solid);
140c27d65349acd38f6ee8fd74bb01518062b0c0b0dJason Sams
141af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron        builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
1428aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        mScript.set_gPSBlend(builder.create());
143af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    }
144af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
145af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    private void createProgramVertex() {
14676faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchouk        mPvOrthoAlloc = new ProgramVertexFixedFunction.Constants(mRS);
14776faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchouk        Matrix4f proj = new Matrix4f();
14876faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchouk        proj.loadOrthoWindow(mWidth, mHeight);
14976faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchouk        mPvOrthoAlloc.setProjection(proj);
150af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
15176faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchouk        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
152af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron        pvb.setTextureMatrixEnable(true);
1534096cf704d7234a647ccdad128654c9500044677Jason Sams        ProgramVertex pv = pvb.create();
15476faca88c5c6c0e75cf05dc139f33c07df96366fAlex Sakhartchouk        ((ProgramVertexFixedFunction)pv).bindConstants(mPvOrthoAlloc);
15576469b31f1bda22057330a0146d9296df92b9094Jason Sams        mRS.bindProgramVertex(pv);
156af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    }
157af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
158af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    @Override
159af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    public Bundle onCommand(String action, int x, int y, int z, Bundle extras,
160af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron            boolean resultRequested) {
161af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron
1628aeb9839d8b2ed85ab5a580d1b10554866add28aJason Sams        if (mWidth < mHeight) {
16312290bd7369db1e81b2dd67be67ef0d4b292b412Daniel Sandler            // nexus.rs ignores the xOffset when rotated; we shall endeavor to do so as well
164eb99a676984f9a946c53de6fc5b42db7e61e312aMichael Jurka            x = (int) (x + mXOffset * mWidth);
16512290bd7369db1e81b2dd67be67ef0d4b292b412Daniel Sandler        }
16612290bd7369db1e81b2dd67be67ef0d4b292b412Daniel Sandler
16712290bd7369db1e81b2dd67be67ef0d4b292b412Daniel Sandler        // android.util.Log.d("NexusRS", String.format(
16812290bd7369db1e81b2dd67be67ef0d4b292b412Daniel Sandler        //     "dw=%d, bw=%d, xOffset=%g, x=%d",
16912290bd7369db1e81b2dd67be67ef0d4b292b412Daniel Sandler        //     dw, bw, mWorldState.xOffset, x));
170c27d65349acd38f6ee8fd74bb01518062b0c0b0dJason Sams
171843c77f4841670c95284c7243d61f5d77f6e5ff7Jeff Brown        if (WallpaperManager.COMMAND_TAP.equals(action)
172843c77f4841670c95284c7243d61f5d77f6e5ff7Jeff Brown                || WallpaperManager.COMMAND_SECONDARY_TAP.equals(action)
173843c77f4841670c95284c7243d61f5d77f6e5ff7Jeff Brown                || WallpaperManager.COMMAND_DROP.equals(action)) {
174bf23d3de3fa86c24f382723f861863d4c274dc3bJason Sams            mScript.invoke_addTap(x, y);
175af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron        }
176af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron        return null;
177af45d444c61a510f2f477a2a7ec01b2bdce25910Mike Cleron    }
1786a500a1d5e15bd5a563995f31d0796552cc13640Jason Sams}
179