CarouselRS.java revision a9e9c4bef076e718094786edfe0290f798e1db4b
1a3ab4494b72d9daf66f45db4d7c43677d1968a55Eric Fischer/*
21866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root * Copyright (C) 2010 The Android Open Source Project
31866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root *
41866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root * Licensed under the Apache License, Version 2.0 (the "License");
51866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root * you may not use this file except in compliance with the License.
61866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root * You may obtain a copy of the License at
71866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root *
81866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root *      http://www.apache.org/licenses/LICENSE-2.0
91866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root *
101866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root * Unless required by applicable law or agreed to in writing, software
111866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root * distributed under the License is distributed on an "AS IS" BASIS,
121866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root * See the License for the specific language governing permissions and
141866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root * limitations under the License.
151866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root */
161866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root
171866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Rootpackage com.android.ex.carousel;
181866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root
191866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Rootimport android.content.res.Resources;
20a3ab4494b72d9daf66f45db4d7c43677d1968a55Eric Fischerimport android.graphics.Bitmap;
21a3ab4494b72d9daf66f45db4d7c43677d1968a55Eric Fischerimport android.renderscript.*;
22a3ab4494b72d9daf66f45db4d7c43677d1968a55Eric Fischerimport android.renderscript.RenderScript.RSMessage;
23e04cc8b826a8d77c62b4377beaa7ba8879f9551esatokimport android.renderscript.Sampler.Value;
2449761501db2bcb25673e635897b7b4dfd4b655d2Eric Fischerimport android.renderscript.ProgramRaster.CullMode;
25e04cc8b826a8d77c62b4377beaa7ba8879f9551esatokimport android.util.Log;
26566c45eddfaff94f82008fa767d262ce57885a7dEric Fischer
2774d36bc8af35422688f582b68c0526fd1ccf0afaEric Fischerimport com.android.internal.R;
2877541fc92e1d244bb21827715f159e6197c92133Eric Fischer
2977541fc92e1d244bb21827715f159e6197c92133Eric Fischerimport static android.renderscript.Element.*;
301f891474931c89bd575df70cbc06df45f8e5cfb8Eric Fischerimport static android.renderscript.Sampler.Value.LINEAR;
3107af2249bbaa59bc1cd282f6cbdc31d90b24bdd7Eric Fischerimport static android.renderscript.Sampler.Value.WRAP;
3207af2249bbaa59bc1cd282f6cbdc31d90b24bdd7Eric Fischerimport static android.renderscript.Sampler.Value.CLAMP;
335a323e65d06575ccf948a868d18578d8d749e738Eric Fischer
345a323e65d06575ccf948a868d18578d8d749e738Eric Fischer/**
35566c45eddfaff94f82008fa767d262ce57885a7dEric Fischer * This is a support class for Carousel renderscript.  It handles most of the low-level interactions
362ca4e9ae8aaae5f30147f1b96fa27ae690cb4637Eric Fischer * with Renderscript as well as dispatching events.
3780bcf30dd6dabb56076c7dc246eaa54fd43d783cEric Fischer *
3880bcf30dd6dabb56076c7dc246eaa54fd43d783cEric Fischer */
39144e97f154ef27c48ac9030980ebb6f3ae959369Eric Fischerpublic class CarouselRS  {
40482e0ef983e47f3b2958d8173fbe6dbf34a00bfeEric Fischer    private static final int DEFAULT_VISIBLE_SLOTS = 1;
411cbd8d09ddf8160f1961d4869fb900a85a385526Eric Fischer    private static final int DEFAULT_CARD_COUNT = 1;
422e66afcc107e14b6c5f9ec1d0ccfd252798c13d7Eric Fischer
432e66afcc107e14b6c5f9ec1d0ccfd252798c13d7Eric Fischer    // Client messages *** THIS LIST MUST MATCH THOSE IN carousel.rs ***
4432c465ec4d4ba4781e75b0f2fcf12b9cd2655be6Ying Wang    public static final int CMD_CARD_SELECTED = 100;
45144e97f154ef27c48ac9030980ebb6f3ae959369Eric Fischer    public static final int CMD_REQUEST_TEXTURE = 200;
46144e97f154ef27c48ac9030980ebb6f3ae959369Eric Fischer    public static final int CMD_INVALIDATE_TEXTURE = 210;
47ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer    public static final int CMD_REQUEST_GEOMETRY = 300;
48ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer    public static final int CMD_INVALIDATE_GEOMETRY = 310;
495de658603639105ce0f9cd7878868848af39cf15Eric Fischer    public static final int CMD_ANIMATION_STARTED = 400;
505de658603639105ce0f9cd7878868848af39cf15Eric Fischer    public static final int CMD_ANIMATION_FINISHED = 500;
5132c465ec4d4ba4781e75b0f2fcf12b9cd2655be6Ying Wang    public static final int CMD_REQUEST_DETAIL_TEXTURE = 600;
5232c465ec4d4ba4781e75b0f2fcf12b9cd2655be6Ying Wang    public static final int CMD_INVALIDATE_DETAIL_TEXTURE = 610;
53991a4737079f59cc973327b31bf11b46c301c62dEric Fischer    public static final int CMD_REPORT_FIRST_CARD_POSITION = 700;
542ca4e9ae8aaae5f30147f1b96fa27ae690cb4637Eric Fischer    public static final int CMD_PING = 1000; // for debugging
552ca4e9ae8aaae5f30147f1b96fa27ae690cb4637Eric Fischer
562ca4e9ae8aaae5f30147f1b96fa27ae690cb4637Eric Fischer    private static final String TAG = "CarouselRS";
572ca4e9ae8aaae5f30147f1b96fa27ae690cb4637Eric Fischer    private static final int DEFAULT_SLOT_COUNT = 10;
582ca4e9ae8aaae5f30147f1b96fa27ae690cb4637Eric Fischer    private static final boolean MIPMAP = false;
592ca4e9ae8aaae5f30147f1b96fa27ae690cb4637Eric Fischer    private static final boolean DBG = false;
6032c465ec4d4ba4781e75b0f2fcf12b9cd2655be6Ying Wang
612ca4e9ae8aaae5f30147f1b96fa27ae690cb4637Eric Fischer    private RenderScriptGL mRS;
622ca4e9ae8aaae5f30147f1b96fa27ae690cb4637Eric Fischer    private Resources mRes;
632ca4e9ae8aaae5f30147f1b96fa27ae690cb4637Eric Fischer    private ScriptC_carousel mScript;
64ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer    private ScriptField_Card mCards;
65fad6a2625b86c924f56ab8d4ac51a6ee3e76de64Eric Fischer    private ScriptField_FragmentShaderConstants_s mFSConst;
66fad6a2625b86c924f56ab8d4ac51a6ee3e76de64Eric Fischer    private ProgramStore mProgramStore;
67fad6a2625b86c924f56ab8d4ac51a6ee3e76de64Eric Fischer    private ProgramFragment mSingleTextureFragmentProgram;
6880bcf30dd6dabb56076c7dc246eaa54fd43d783cEric Fischer    private ProgramFragment mMultiTextureFragmentProgram;
695a323e65d06575ccf948a868d18578d8d749e738Eric Fischer    private ProgramVertex mVertexProgram;
705a323e65d06575ccf948a868d18578d8d749e738Eric Fischer    private ProgramRaster mRasterProgram;
715a323e65d06575ccf948a868d18578d8d749e738Eric Fischer    private CarouselCallback mCallback;
72b396ea9ede34a64437f0accc5d394640f75ffa4bEric Fischer    private float[] mEyePoint = new float[3];
735a323e65d06575ccf948a868d18578d8d749e738Eric Fischer    private float[] mAtPoint = new float[3];
745a323e65d06575ccf948a868d18578d8d749e738Eric Fischer    private float[] mUp = new float[3];
752ca4e9ae8aaae5f30147f1b96fa27ae690cb4637Eric Fischer
76bf8aa9d3489973718625206064c35fdf129c3150Eric Fischer    private static final String mSingleTextureShader = new String(
7780d6f6716ef04aa086fe96a6fff310e7c094df3dEric Fischer            "varying vec4 varTex0;" +
78af63f0663ac699926f33ea70e12c9dc72656109fEric Fischer            "void main() {" +
79af63f0663ac699926f33ea70e12c9dc72656109fEric Fischer            "vec2 t0 = varTex0.xy;" +
80d707eeceb558dcb68c30a23d644efe425601b438Eric Fischer            "vec4 col = texture2D(UNI_Tex0, t0);" +
81ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer            "gl_FragColor = col; " +
82ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer            "}");
83ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer
84ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer    private static final String mMultiTextureShader = new String(
85b396ea9ede34a64437f0accc5d394640f75ffa4bEric Fischer            "varying vec4 varTex0;" +
86b396ea9ede34a64437f0accc5d394640f75ffa4bEric Fischer            "void main() {" +
87ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer            "vec2 t0 = varTex0.xy;" +
88ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer            "vec4 col = texture2D(UNI_Tex0, t0);" +
89ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer            "vec4 col2 = texture2D(UNI_Tex1, t0);" +
90ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer            "gl_FragColor = mix(col, col2, UNI_fadeAmount);}");
91ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer
92ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer    public static interface CarouselCallback {
93ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer        /**
94ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer         * Called when a card is selected
95ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer         * @param n the id of the card
96ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer         */
972efdf6a09f9c29122f2aa8504b792c3932ca287aEric Fischer        void onCardSelected(int n);
98897d1302f5f7eada34cedb6a736a8bb268b85410Eric Fischer
99b396ea9ede34a64437f0accc5d394640f75ffa4bEric Fischer        /**
100b396ea9ede34a64437f0accc5d394640f75ffa4bEric Fischer         * Called when texture is needed for card n.  This happens when the given card becomes
101b396ea9ede34a64437f0accc5d394640f75ffa4bEric Fischer         * visible.
102b396ea9ede34a64437f0accc5d394640f75ffa4bEric Fischer         * @param n the id of the card
103b396ea9ede34a64437f0accc5d394640f75ffa4bEric Fischer         */
104b396ea9ede34a64437f0accc5d394640f75ffa4bEric Fischer        void onRequestTexture(int n);
105b396ea9ede34a64437f0accc5d394640f75ffa4bEric Fischer
1065de658603639105ce0f9cd7878868848af39cf15Eric Fischer        /**
1072ca4e9ae8aaae5f30147f1b96fa27ae690cb4637Eric Fischer         * Called when a texture is no longer needed for card n.  This happens when the card
1082ca4e9ae8aaae5f30147f1b96fa27ae690cb4637Eric Fischer         * goes out of view.
1092ca4e9ae8aaae5f30147f1b96fa27ae690cb4637Eric Fischer         * @param n the id of the card
11032c465ec4d4ba4781e75b0f2fcf12b9cd2655be6Ying Wang         */
1112ca4e9ae8aaae5f30147f1b96fa27ae690cb4637Eric Fischer        void onInvalidateTexture(int n);
11285427b3d8e25b36f8c0575d292348c861de40ed9Eric Fischer
113df4db224498035ac00eee7215026ec85a1dc6e7cEric Fischer        /**
114a953a3c137be344b73ae8918de0e5c8afd4a1a13Eric Fischer         * Called when detail texture is needed for card n.  This happens when the given card
11574d36bc8af35422688f582b68c0526fd1ccf0afaEric Fischer         * becomes visible.
11674d36bc8af35422688f582b68c0526fd1ccf0afaEric Fischer         * @param n the id of the card
11774d36bc8af35422688f582b68c0526fd1ccf0afaEric Fischer         */
11874d36bc8af35422688f582b68c0526fd1ccf0afaEric Fischer        void onRequestDetailTexture(int n);
11974d36bc8af35422688f582b68c0526fd1ccf0afaEric Fischer
12074d36bc8af35422688f582b68c0526fd1ccf0afaEric Fischer        /**
1215de658603639105ce0f9cd7878868848af39cf15Eric Fischer         * Called when a detail texture is no longer needed for card n.  This happens when the card
1221cbd8d09ddf8160f1961d4869fb900a85a385526Eric Fischer         * goes out of view.
1231866d9ec83dcbc69a2c5ba2b6129ed4ce7f9f665Kenny Root         * @param n the id of the card
124566c45eddfaff94f82008fa767d262ce57885a7dEric Fischer         */
125566c45eddfaff94f82008fa767d262ce57885a7dEric Fischer        void onInvalidateDetailTexture(int n);
126ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer
127790c77fdc5125c972b8ee7971738b31bf7e286adEric Fischer        /**
128df4db224498035ac00eee7215026ec85a1dc6e7cEric Fischer         * Called when geometry is needed for card n.
1294c4fd10d911931351ad9fb6d99015f9e3fb5f64aEric Fischer         * @param n the id of the card.
1304c4fd10d911931351ad9fb6d99015f9e3fb5f64aEric Fischer         */
131b4f5c9c08894d1e465d8dbe0b1ea9f8a3b6dfd5fEric Fischer        void onRequestGeometry(int n);
132fad6a2625b86c924f56ab8d4ac51a6ee3e76de64Eric Fischer
13319b30243d70164d3a04c3d96ab7fcc6efdbc1ec8Eric Fischer        /**
13419b30243d70164d3a04c3d96ab7fcc6efdbc1ec8Eric Fischer         * Called when geometry is no longer needed for card n. This happens when the card goes
13519b30243d70164d3a04c3d96ab7fcc6efdbc1ec8Eric Fischer         * out of view.
13619b30243d70164d3a04c3d96ab7fcc6efdbc1ec8Eric Fischer         * @param n the id of the card
13719b30243d70164d3a04c3d96ab7fcc6efdbc1ec8Eric Fischer         */
138b4f5c9c08894d1e465d8dbe0b1ea9f8a3b6dfd5fEric Fischer        void onInvalidateGeometry(int n);
139b4f5c9c08894d1e465d8dbe0b1ea9f8a3b6dfd5fEric Fischer
140b4f5c9c08894d1e465d8dbe0b1ea9f8a3b6dfd5fEric Fischer        /**
141b4f5c9c08894d1e465d8dbe0b1ea9f8a3b6dfd5fEric Fischer         * Called when card animation (e.g. a fling) has started.
142b4f5c9c08894d1e465d8dbe0b1ea9f8a3b6dfd5fEric Fischer         */
143b4f5c9c08894d1e465d8dbe0b1ea9f8a3b6dfd5fEric Fischer        void onAnimationStarted();
144b4f5c9c08894d1e465d8dbe0b1ea9f8a3b6dfd5fEric Fischer
1453b4d2725f4e677ad7307f82fa9a4ad7cec24009dEric Fischer        /**
1463b4d2725f4e677ad7307f82fa9a4ad7cec24009dEric Fischer         * Called when card animation has stopped.
1473b4d2725f4e677ad7307f82fa9a4ad7cec24009dEric Fischer         */
1483b4d2725f4e677ad7307f82fa9a4ad7cec24009dEric Fischer        void onAnimationFinished();
149ff53f0fd9788c6e57f6ba658cfc3908619592b9cEric Fischer
150d707eeceb558dcb68c30a23d644efe425601b438Eric Fischer        /**
151d707eeceb558dcb68c30a23d644efe425601b438Eric Fischer         * Called when the current position has been requested.
152a3ab4494b72d9daf66f45db4d7c43677d1968a55Eric Fischer         */
153        void onReportFirstCardPosition(int n);
154    };
155
156    private RSMessage mRsMessage = new RSMessage() {
157        public void run() {
158            if (mCallback == null) return;
159            switch (mID) {
160                case CMD_CARD_SELECTED:
161                    mCallback.onCardSelected(mData[0]);
162                    break;
163
164                case CMD_REQUEST_TEXTURE:
165                    mCallback.onRequestTexture(mData[0]);
166                    break;
167
168                case CMD_INVALIDATE_TEXTURE:
169                    setTexture(mData[0], null);
170                    mCallback.onInvalidateTexture(mData[0]);
171                    break;
172
173                case CMD_REQUEST_DETAIL_TEXTURE:
174                    mCallback.onRequestDetailTexture(mData[0]);
175                    break;
176
177                case CMD_INVALIDATE_DETAIL_TEXTURE:
178                    setDetailTexture(mData[0], 0, 0, null);
179                    mCallback.onInvalidateDetailTexture(mData[0]);
180                    break;
181
182                case CMD_REQUEST_GEOMETRY:
183                    mCallback.onRequestGeometry(mData[0]);
184                    break;
185
186                case CMD_INVALIDATE_GEOMETRY:
187                    setGeometry(mData[0], null);
188                    mCallback.onInvalidateGeometry(mData[0]);
189                    break;
190
191                case CMD_ANIMATION_STARTED:
192                    mCallback.onAnimationStarted();
193                    break;
194
195                case CMD_ANIMATION_FINISHED:
196                    mCallback.onAnimationFinished();
197                    break;
198
199                case CMD_REPORT_FIRST_CARD_POSITION:
200                    mCallback.onReportFirstCardPosition(mData[0]);
201                    break;
202
203                case CMD_PING:
204                    if (DBG) Log.v(TAG, "PING...");
205                    break;
206
207                default:
208                    Log.e(TAG, "Unknown RSMessage: " + mID);
209            }
210        }
211    };
212
213    public void init(RenderScriptGL rs, Resources res, int resId) {
214        mRS = rs;
215        mRes = res;
216
217        // create the script object
218        mScript = new ScriptC_carousel(mRS, mRes, resId, true);
219        mRS.mMessageCallback = mRsMessage;
220
221        initProgramStore();
222        initFragmentProgram();
223        initRasterProgram();
224        initVertexProgram();
225
226        setSlotCount(DEFAULT_SLOT_COUNT);
227        setVisibleSlots(DEFAULT_VISIBLE_SLOTS);
228        createCards(DEFAULT_CARD_COUNT);
229
230        setStartAngle(0.0f);
231        setRadius(1.0f);
232
233        // update the camera
234        boolean pcam = true;
235        if (pcam) {
236            float eye[] = { 20.6829f, 2.77081f, 16.7314f };
237            float at[] = { 14.7255f, -3.40001f, -1.30184f };
238            float up[] = { 0.0f, 1.0f, 0.0f };
239            setLookAt(eye, at, up);
240            setRadius(20.0f);
241            // Fov: 25
242        } else {
243            mScript.invoke_lookAt(2.5f, 2.0f, 2.5f, 0.0f, -0.75f, 0.0f,  0.0f, 1.0f, 0.0f);
244            mScript.set_cardRotation(0.0f);
245            setRadius(1.5f);
246        }
247
248        resumeRendering();
249    }
250
251    public void setLookAt(float[] eye, float[] at, float[] up) {
252        for (int i = 0; i < 3; i++) {
253            mEyePoint[i] = eye[i];
254            mAtPoint[i] = at[i];
255            mUp[i] = up[i];
256        }
257        mScript.invoke_lookAt(eye[0], eye[1], eye[2], at[0], at[1], at[2], up[0], up[1], up[2]);
258    }
259
260    public void setRadius(float radius) {
261        mScript.set_radius(radius);
262    }
263
264    public void setCardRotation(float cardRotation) {
265        mScript.set_cardRotation(cardRotation);
266    }
267
268    public void setSwaySensitivity(float swaySensitivity) {
269        mScript.set_swaySensitivity(swaySensitivity);
270    }
271
272    public void setFrictionCoefficient(float frictionCoeff) {
273        mScript.set_frictionCoeff(frictionCoeff);
274    }
275
276    public void setDragFactor(float dragFactor) {
277        mScript.set_dragFactor(dragFactor);
278    }
279
280    private void initVertexProgram() {
281        ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null);
282        mVertexProgram = pvb.create();
283        ProgramVertex.MatrixAllocation pva = new ProgramVertex.MatrixAllocation(mRS);
284        mVertexProgram.bindAllocation(pva);
285        pva.setupProjectionNormalized(1, 1);
286        mScript.set_vertexProgram(mVertexProgram);
287    }
288
289    private void initRasterProgram() {
290        ProgramRaster.Builder programRasterBuilder = new ProgramRaster.Builder(mRS);
291        mRasterProgram = programRasterBuilder.create();
292        //mRasterProgram.setCullMode(CullMode.NONE);
293        mScript.set_rasterProgram(mRasterProgram);
294    }
295
296    private void initFragmentProgram() {
297        //
298        // Single texture program
299        //
300        ProgramFragment.ShaderBuilder pfbSingle = new ProgramFragment.ShaderBuilder(mRS);
301        // Specify the resource that contains the shader string
302        pfbSingle.setShader(mSingleTextureShader);
303        // Tell the builder how many textures we have
304        pfbSingle.setTextureCount(1);
305        mSingleTextureFragmentProgram = pfbSingle.create();
306        // Bind the source of constant data
307        mSingleTextureFragmentProgram.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
308
309        //
310        // Multi texture program
311        //
312        mFSConst = new ScriptField_FragmentShaderConstants_s(mRS, 1);
313        mScript.bind_shaderConstants(mFSConst);
314        ProgramFragment.ShaderBuilder pfbMulti = new ProgramFragment.ShaderBuilder(mRS);
315        // Specify the resource that contains the shader string
316        pfbMulti.setShader(mMultiTextureShader);
317        // Tell the builder how many textures we have
318        pfbMulti.setTextureCount(2);
319        // Define the constant input layout
320        pfbMulti.addConstant(mFSConst.getAllocation().getType());
321        mMultiTextureFragmentProgram = pfbMulti.create();
322        // Bind the source of constant data
323        mMultiTextureFragmentProgram.bindConstants(mFSConst.getAllocation(), 0);
324        mMultiTextureFragmentProgram.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
325        mMultiTextureFragmentProgram.bindSampler(Sampler.CLAMP_LINEAR(mRS), 1);
326
327        mScript.set_linearClamp(Sampler.CLAMP_LINEAR(mRS));
328        mScript.set_singleTextureFragmentProgram(mSingleTextureFragmentProgram);
329        mScript.set_multiTextureFragmentProgram(mMultiTextureFragmentProgram);
330    }
331
332    private void initProgramStore() {
333        ProgramStore.Builder programStoreBuilder = new ProgramStore.Builder(mRS, null, null);
334        programStoreBuilder.setDepthFunc(ProgramStore.DepthFunc.LESS);
335        programStoreBuilder.setBlendFunc(ProgramStore.BlendSrcFunc.ONE,
336                ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA);
337        programStoreBuilder.setDitherEnable(true);
338        programStoreBuilder.setDepthMask(true);
339        mProgramStore = programStoreBuilder.create();
340        mScript.set_programStore(mProgramStore);
341    }
342
343    public void createCards(int count)
344    {
345        // Because RenderScript can't have allocations with 0 dimensions, we always create
346        // an allocation of at least one card. This relies on invoke_createCards() to keep
347        // track of when the allocation is not valid.
348        if (mCards != null) {
349            // resize the array
350            ScriptField_Card tmpcards = new ScriptField_Card(mRS, count > 0 ? count : 1);
351            mScript.bind_tmpCards(tmpcards);
352            mScript.invoke_copyCards();
353            mScript.bind_cards(tmpcards);
354            mScript.bind_tmpCards(null);
355            mCards = tmpcards;
356        } else {
357            // create array from scratch
358            mCards = new ScriptField_Card(mRS, count > 0 ? count : 1);
359            mScript.bind_cards(mCards);
360            mScript.invoke_createCards(count);
361        }
362    }
363
364    public void setVisibleSlots(int count)
365    {
366        mScript.set_visibleSlotCount(count);
367    }
368
369    public void setVisibleDetails(int count) {
370        mScript.set_visibleDetailCount(count);
371    }
372
373    public void setDrawDetailBelowCard(boolean below) {
374        mScript.set_drawDetailBelowCard(below);
375    }
376
377    public void setDrawRuler(boolean drawRuler) {
378        mScript.set_drawRuler(drawRuler);
379    }
380
381    public void setDefaultBitmap(Bitmap bitmap)
382    {
383        mScript.set_defaultTexture(allocationFromBitmap(bitmap, MIPMAP));
384    }
385
386    public void setLoadingBitmap(Bitmap bitmap)
387    {
388        mScript.set_loadingTexture(allocationFromBitmap(bitmap, MIPMAP));
389    }
390
391    public void setDefaultGeometry(Mesh mesh)
392    {
393        mScript.set_defaultGeometry(mesh);
394    }
395
396    public void setLoadingGeometry(Mesh mesh)
397    {
398        mScript.set_loadingGeometry(mesh);
399    }
400
401    public void setStartAngle(float theta)
402    {
403        mScript.set_startAngle(theta);
404    }
405
406    public void setCallback(CarouselCallback callback)
407    {
408        mCallback = callback;
409    }
410
411    private Allocation allocationFromBitmap(Bitmap bitmap, boolean mipmap)
412    {
413        if (bitmap == null) return null;
414        Allocation allocation = Allocation.createFromBitmap(mRS, bitmap,
415                elementForBitmap(bitmap, Bitmap.Config.ARGB_4444), mipmap);
416        allocation.uploadToTexture(0);
417        return allocation;
418    }
419
420    public void setTexture(int n, Bitmap bitmap)
421    {
422        if (n < 0) throw new IllegalArgumentException("Index cannot be negative");
423
424        synchronized(this) {
425            ScriptField_Card.Item item = mCards.get(n);
426            if (item == null) {
427                if (DBG) Log.v(TAG, "setTexture(): no item at index " + n);
428                item = new ScriptField_Card.Item();
429            }
430            if (bitmap != null) {
431                if (DBG) Log.v(TAG, "creating new bitmap");
432                item.texture = Allocation.createFromBitmap(mRS, bitmap,
433                        elementForBitmap(bitmap, Bitmap.Config.ARGB_4444), MIPMAP);
434                if (DBG) Log.v(TAG, "uploadToTexture(" + n + ")");
435                item.texture.uploadToTexture(0);
436                if (DBG) Log.v(TAG, "done...");
437            } else {
438                if (item.texture != null) {
439                    if (DBG) Log.v(TAG, "unloading texture " + n);
440                    // Don't wait for GC to free native memory.
441                    // Only works if textures are not shared.
442                    item.texture.destroy();
443                    item.texture = null;
444                }
445            }
446            mCards.set(item, n, false); // This is primarily used for reference counting.
447            mScript.invoke_setTexture(n, item.texture);
448        }
449    }
450
451    void setDetailTexture(int n, float offx, float offy, Bitmap bitmap)
452    {
453        if (n < 0) throw new IllegalArgumentException("Index cannot be negative");
454
455        synchronized(this) {
456            ScriptField_Card.Item item = mCards.get(n);
457            if (item == null) {
458                if (DBG) Log.v(TAG, "setDetailTexture(): no item at index " + n);
459                item = new ScriptField_Card.Item();
460            }
461            float width = 0.0f;
462            float height = 0.0f;
463            if (bitmap != null) {
464                item.detailTexture = Allocation.createFromBitmap(mRS, bitmap,
465                        elementForBitmap(bitmap, Bitmap.Config.ARGB_4444), MIPMAP);
466                item.detailTexture.uploadToTexture(0);
467                width = bitmap.getWidth();
468                height = bitmap.getHeight();
469            } else {
470                if (item.detailTexture != null) {
471                    if (DBG) Log.v(TAG, "unloading texture " + n);
472                    // Don't wait for GC to free native memory.
473                    // Only works if textures are not shared.
474                    item.detailTexture.destroy();
475                    item.detailTexture = null;
476                }
477            }
478            mCards.set(item, n, false); // This is primarily used for reference counting.
479            mScript.invoke_setDetailTexture(n, offx, offy, item.detailTexture);
480        }
481    }
482
483    public void setGeometry(int n, Mesh geometry)
484    {
485        if (n < 0) throw new IllegalArgumentException("Index cannot be negative");
486
487        synchronized(this) {
488            final boolean mipmap = false;
489            ScriptField_Card.Item item = mCards.get(n);
490            if (item == null) {
491                if (DBG) Log.v(TAG, "setGeometry(): no item at index " + n);
492                item = new ScriptField_Card.Item();
493            }
494            if (geometry != null) {
495                item.geometry = geometry;
496            } else {
497                if (DBG) Log.v(TAG, "unloading geometry " + n);
498                if (item.geometry != null) {
499                    // item.geometry.destroy();
500                    item.geometry = null;
501                }
502            }
503            mCards.set(item, n, false);
504            mScript.invoke_setGeometry(n, item.geometry);
505        }
506    }
507
508    public void setBackgroundColor(Float4 color) {
509        mScript.set_backgroundColor(color);
510    }
511
512    public void setBackgroundTexture(Bitmap bitmap) {
513        Allocation texture = null;
514        if (bitmap != null) {
515            texture = Allocation.createFromBitmap(mRS, bitmap,
516                    elementForBitmap(bitmap, Bitmap.Config.RGB_565), MIPMAP);
517            texture.uploadToTexture(0);
518        }
519        mScript.set_backgroundTexture(texture);
520    }
521
522    public void setDetailLineTexture(Bitmap bitmap) {
523        Allocation texture = null;
524        if (bitmap != null) {
525            texture = Allocation.createFromBitmap(mRS, bitmap,
526                    elementForBitmap(bitmap, Bitmap.Config.ARGB_4444), MIPMAP);
527            texture.uploadToTexture(0);
528        }
529        mScript.set_detailLineTexture(texture);
530    }
531
532    public void setDetailLoadingTexture(Bitmap bitmap) {
533        Allocation texture = null;
534        if (bitmap != null) {
535            texture = Allocation.createFromBitmap(mRS, bitmap,
536                    elementForBitmap(bitmap, Bitmap.Config.ARGB_4444), MIPMAP);
537            texture.uploadToTexture(0);
538        }
539        mScript.set_detailLoadingTexture(texture);
540    }
541
542    public void pauseRendering() {
543        // Used to update multiple states at once w/o redrawing for each.
544        mRS.contextBindRootScript(null);
545    }
546
547    public void resumeRendering() {
548        mRS.contextBindRootScript(mScript);
549    }
550
551    public void doMotion(float x, float y) {
552        mScript.invoke_doMotion(x,y);
553    }
554
555    public void doSelection(float x, float y) {
556        mScript.invoke_doSelection(x, y);
557    }
558
559    public void doStart(float x, float y) {
560        mScript.invoke_doStart(x, y);
561    }
562
563    public void doStop(float x, float y) {
564        mScript.invoke_doStop(x, y);
565    }
566
567    public void setSlotCount(int n) {
568        mScript.set_slotCount(n);
569    }
570
571    public void requestFirstCardPosition() {
572        mScript.invoke_requestFirstCardPosition();
573    }
574
575    public void setRezInCardCount(float alpha) {
576        mScript.set_rezInCardCount(alpha);
577    }
578
579    public void setFadeInDuration(long t) {
580        mScript.set_fadeInDuration((int)t); // TODO: Remove cast when RS supports exporting longs
581    }
582
583    private Element elementForBitmap(Bitmap bitmap, Bitmap.Config defaultConfig) {
584        Bitmap.Config config = bitmap.getConfig();
585        if (config == null) {
586            config = defaultConfig;
587        }
588        if (config == Bitmap.Config.ALPHA_8) {
589            return A_8(mRS);
590        } else if (config == Bitmap.Config.RGB_565) {
591            return RGB_565(mRS);
592        } else if (config == Bitmap.Config.ARGB_4444) {
593            return RGBA_4444(mRS);
594        } else if (config == Bitmap.Config.ARGB_8888) {
595            return RGBA_8888(mRS);
596        } else {
597            throw new IllegalArgumentException("Unknown configuration");
598        }
599    }
600}
601