1/*
2 * Copyright (C) 2011 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
17package com.android.scenegraph;
18
19import java.lang.Math;
20import java.util.ArrayList;
21import java.util.HashMap;
22import java.util.Iterator;
23
24import com.android.scenegraph.Float4Param;
25import com.android.scenegraph.MatrixTransform;
26import com.android.scenegraph.SceneManager;
27import com.android.scenegraph.ShaderParam;
28import com.android.scenegraph.TransformParam;
29
30import android.content.res.Resources;
31import android.renderscript.Allocation;
32import android.renderscript.Element;
33import android.renderscript.Element.DataType;
34import android.renderscript.Matrix4f;
35import android.renderscript.Mesh;
36import android.renderscript.ProgramFragment;
37import android.renderscript.ProgramStore;
38import android.renderscript.ProgramVertex;
39import android.renderscript.RenderScriptGL;
40import android.util.Log;
41
42/**
43 * @hide
44 */
45public class Renderable extends RenderableBase {
46    HashMap<String, ShaderParam> mSourceParams;
47
48    RenderState mRenderState;
49    Transform mTransform;
50
51    String mMeshName;
52    String mMeshIndexName;
53
54    public String mMaterialName;
55
56    ScriptField_Renderable_s mField;
57    ScriptField_Renderable_s.Item mData;
58
59    public Renderable() {
60        mSourceParams = new HashMap<String, ShaderParam>();
61        mData = new ScriptField_Renderable_s.Item();
62    }
63
64    public void setCullType(int cull) {
65        mData.cullType = cull;
66    }
67
68    public void setRenderState(RenderState renderState) {
69        mRenderState = renderState;
70        if (mField != null) {
71            RenderScriptGL rs = SceneManager.getRS();
72            updateFieldItem(rs);
73            mField.set(mData, 0, true);
74        }
75    }
76
77    public void setMesh(Mesh mesh) {
78        mData.mesh = mesh;
79        if (mField != null) {
80            mField.set_mesh(0, mData.mesh, true);
81        }
82    }
83
84    public void setMesh(String mesh, String indexName) {
85        mMeshName = mesh;
86        mMeshIndexName = indexName;
87    }
88
89    public void setMaterialName(String name) {
90        mMaterialName = name;
91    }
92
93    public Transform getTransform() {
94        return mTransform;
95    }
96
97    public void setTransform(Transform t) {
98        mTransform = t;
99        if (mField != null) {
100            RenderScriptGL rs = SceneManager.getRS();
101            updateFieldItem(rs);
102            mField.set(mData, 0, true);
103        }
104    }
105
106    public void appendSourceParams(ShaderParam p) {
107        mSourceParams.put(p.getParamName(), p);
108        // Possibly lift this restriction later
109        if (mField != null) {
110            throw new RuntimeException("Can't add source params to objects that are rendering");
111        }
112    }
113
114    public void resolveMeshData(Mesh mesh) {
115        mData.mesh = mesh;
116        if (mData.mesh == null) {
117            Log.v("DRAWABLE: ", "*** NO MESH *** " + mMeshName);
118            return;
119        }
120        int subIndexCount = mData.mesh.getPrimitiveCount();
121        if (subIndexCount == 1 || mMeshIndexName == null) {
122            mData.meshIndex = 0;
123        } else {
124            for (int i = 0; i < subIndexCount; i ++) {
125                if (mData.mesh.getIndexSetAllocation(i).getName().equals(mMeshIndexName)) {
126                    mData.meshIndex = i;
127                    break;
128                }
129            }
130        }
131        if (mField != null) {
132            mField.set(mData, 0, true);
133        }
134    }
135
136    void updateTextures(RenderScriptGL rs) {
137        Iterator<ShaderParam> allParamsIter = mSourceParams.values().iterator();
138        int paramIndex = 0;
139        while (allParamsIter.hasNext()) {
140            ShaderParam sp = allParamsIter.next();
141            if (sp instanceof TextureParam) {
142                TextureParam p = (TextureParam)sp;
143                TextureBase tex = p.getTexture();
144                if (tex != null) {
145                    mData.pf_textures[paramIndex++] = tex.getRsData(false).getAllocation();
146                }
147            }
148        }
149        ProgramFragment pf = mRenderState.mFragment.mProgram;
150        mData.pf_num_textures = pf != null ? Math.min(pf.getTextureCount(), paramIndex) : 0;
151        if (mField != null) {
152            mField.set_pf_textures(0, mData.pf_textures, true);
153            mField.set_pf_num_textures(0, mData.pf_num_textures, true);
154        }
155    }
156
157    public void setVisible(boolean vis) {
158        mData.cullType = vis ? 0 : 2;
159        if (mField != null) {
160            mField.set_cullType(0, mData.cullType, true);
161        }
162    }
163
164    ScriptField_Renderable_s getRsField(RenderScriptGL rs, Resources res) {
165        if (mField != null) {
166            return mField;
167        }
168        updateFieldItem(rs);
169        updateTextures(rs);
170
171        mField = new ScriptField_Renderable_s(rs, 1);
172        mField.set(mData, 0, true);
173
174        return mField;
175    }
176
177    void updateVertexConstants(RenderScriptGL rs) {
178        Allocation pvParams = null, vertexConstants = null;
179        VertexShader pv = mRenderState.mVertex;
180        if (pv != null && pv.getObjectConstants() != null) {
181            vertexConstants = Allocation.createTyped(rs, pv.getObjectConstants());
182            Element vertexConst = vertexConstants.getType().getElement();
183            pvParams = ShaderParam.fillInParams(vertexConst, mSourceParams,
184                                                mTransform).getAllocation();
185        }
186        mData.pv_const = vertexConstants;
187        mData.pv_constParams = pvParams;
188    }
189
190    void updateFragmentConstants(RenderScriptGL rs) {
191        Allocation pfParams = null, fragmentConstants = null;
192        FragmentShader pf = mRenderState.mFragment;
193        if (pf != null && pf.getObjectConstants() != null) {
194            fragmentConstants = Allocation.createTyped(rs, pf.getObjectConstants());
195            Element fragmentConst = fragmentConstants.getType().getElement();
196            pfParams = ShaderParam.fillInParams(fragmentConst, mSourceParams,
197                                                mTransform).getAllocation();
198        }
199        mData.pf_const = fragmentConstants;
200        mData.pf_constParams = pfParams;
201    }
202
203    void updateFieldItem(RenderScriptGL rs) {
204        if (mRenderState == null) {
205            mRenderState = SceneManager.getDefaultState();
206        }
207        if (mTransform == null) {
208            mTransform = SceneManager.getDefaultTransform();
209        }
210        updateVertexConstants(rs);
211        updateFragmentConstants(rs);
212
213        mData.transformMatrix = mTransform.getRSData().getAllocation();
214
215        mData.name = getNameAlloc(rs);
216        mData.render_state = mRenderState.getRSData().getAllocation();
217        mData.bVolInitialized = 0;
218    }
219}
220
221
222
223
224
225