Renderable.java revision be5bdeb9471c4a04905edd34e6d3560315293427
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.ShaderParam;
26import com.android.scenegraph.TransformParam;
27
28import android.content.res.Resources;
29import android.renderscript.Allocation;
30import android.renderscript.Element;
31import android.renderscript.Element.DataType;
32import android.renderscript.Matrix4f;
33import android.renderscript.Mesh;
34import android.renderscript.ProgramFragment;
35import android.renderscript.ProgramStore;
36import android.renderscript.ProgramVertex;
37import android.renderscript.RenderScriptGL;
38import android.util.Log;
39
40/**
41 * @hide
42 */
43public class Renderable extends RenderableBase {
44    Allocation mVertexConstants;
45    Allocation mVertexParams;
46    Allocation mFragmentConstants;
47    Allocation mFragmentParams;
48    ArrayList<Allocation> mFragmentTextures;
49
50    HashMap<String, ShaderParam> mSourceParams;
51
52    ArrayList<ShaderParam> mVertexParamList;
53    ArrayList<ShaderParam> mFragmentParamList;
54
55    Mesh mMesh;
56    int mMeshIndex;
57
58    int mCullType;
59
60    RenderState mRenderState;
61
62    Transform mTransform;
63
64    String mMeshName;
65    String mMeshIndexName;
66
67    public String mMaterialName;
68
69    // quick hack to prototype
70    int sceneIndex;
71
72    ScriptField_Renderable_s mRsField;
73    ScriptField_Renderable_s.Item mRsFieldItem;
74
75    public Renderable() {
76        mSourceParams = new HashMap<String, ShaderParam>();
77        mVertexParamList = new ArrayList<ShaderParam>();
78        mFragmentParamList = new ArrayList<ShaderParam>();
79    }
80
81    public void setCullType(int cull) {
82        mCullType = cull;
83    }
84
85    public void setRenderState(RenderState renderState) {
86        mRenderState = renderState;
87    }
88
89    public void setMesh(Mesh mesh) {
90        mMesh = mesh;
91    }
92
93    public void setMesh(String mesh, String indexName) {
94        mMeshName = mesh;
95        mMeshIndexName = indexName;
96    }
97
98    public void setMaterialName(String name) {
99        mMaterialName = name;
100    }
101
102    public void setTransform(Transform t) {
103        mTransform = t;
104    }
105
106    public void appendSourceParams(ShaderParam p) {
107        mSourceParams.put(p.getParamName(), p);
108    }
109
110    public void resolveMeshData(Mesh mMesh) {
111        mMesh = mMesh;
112        if (mMesh == null) {
113            Log.v("DRAWABLE: ", "*** NO MESH *** " + mMeshName);
114            return;
115        }
116        int subIndexCount = mMesh.getPrimitiveCount();
117        if (subIndexCount == 1 || mMeshIndexName == null) {
118            mMeshIndex = 0;
119        } else {
120            for (int i = 0; i < subIndexCount; i ++) {
121                if (mMesh.getIndexSetAllocation(i).getName().equals(mMeshIndexName)) {
122                    mMeshIndex = i;
123                    break;
124                }
125            }
126        }
127
128        mRsFieldItem.mesh = mMesh;
129        mRsFieldItem.meshIndex = mMeshIndex;
130
131        mRsField.set(mRsFieldItem, 0, true);
132    }
133
134    void updateTextures(RenderScriptGL rs, Resources res) {
135        Iterator<ShaderParam> allParamsIter = mSourceParams.values().iterator();
136        int paramIndex = 0;
137        while (allParamsIter.hasNext()) {
138            ShaderParam sp = allParamsIter.next();
139            if (sp instanceof TextureParam) {
140                TextureParam p = (TextureParam)sp;
141                mRsFieldItem.pf_textures[paramIndex++] = p.getTexture().getRsData(rs, res);
142            }
143        }
144        ProgramFragment pf = mRenderState.mFragment;
145        mRsFieldItem.pf_num_textures = pf != null ? Math.min(pf.getTextureCount(), paramIndex) : 0;
146        mRsField.set(mRsFieldItem, 0, true);
147    }
148
149    void updateTextures(RenderScriptGL rs, Allocation a, int slot) {
150        getRsFieldItem(rs, null);
151        mRsFieldItem.pf_textures[slot] = a;
152    }
153
154    void setVisible(RenderScriptGL rs, boolean vis) {
155        getRsField(rs, null);
156        mRsFieldItem.cullType = vis ? 0 : 2;
157        mRsField.set(mRsFieldItem, 0, true);
158    }
159
160    ShaderParam findParamByName(String name) {
161        return mSourceParams.get(name);
162    }
163
164    void fillInParams(Element constantElem, ArrayList<ShaderParam> paramList) {
165        int subElemCount = constantElem.getSubElementCount();
166        for (int i = 0; i < subElemCount; i ++) {
167            String inputName = constantElem.getSubElementName(i);
168            int offset = constantElem.getSubElementOffsetBytes(i);
169            ShaderParam matchingParam = findParamByName(inputName);
170            // Make one if it's not there
171            if (matchingParam == null) {
172                Element subElem = constantElem.getSubElement(i);
173                if (subElem.getDataType() == Element.DataType.FLOAT_32) {
174                    Float4Param fParam = new Float4Param(inputName);
175                    fParam.setVecSize(subElem.getVectorSize());
176                    matchingParam = fParam;
177                } else if (subElem.getDataType() == Element.DataType.MATRIX_4X4) {
178                    TransformParam trParam = new TransformParam(inputName);
179                    trParam.setTransform(mTransform);
180                    matchingParam = trParam;
181                }
182            }
183            matchingParam.setOffset(offset);
184            paramList.add(matchingParam);
185        }
186    }
187
188    void linkConstants() {
189        // Assign all the fragment params
190        if (mFragmentConstants != null) {
191            Element fragmentConst = mFragmentConstants.getType().getElement();
192            fillInParams(fragmentConst, mFragmentParamList);
193        }
194
195        // Assign all the vertex params
196        if (mVertexConstants != null) {
197            Element vertexConst = mVertexConstants.getType().getElement();
198            fillInParams(vertexConst, mVertexParamList);
199        }
200    }
201
202    ScriptField_Renderable_s getRsField(RenderScriptGL rs, Resources res) {
203        if (mRsField != null) {
204            return mRsField;
205        }
206        getRsFieldItem(rs, res);
207
208        mRsField = new ScriptField_Renderable_s(rs, 1);
209        mRsField.set(mRsFieldItem, 0, true);
210
211        return mRsField;
212    }
213
214    void getRsFieldItem(RenderScriptGL rs, Resources res) {
215        if (mRsFieldItem != null) {
216            return;
217        }
218
219        ProgramVertex pv = mRenderState.mVertex;
220        if (pv != null && pv.getConstantCount() > 0) {
221            mVertexConstants = Allocation.createTyped(rs, pv.getConstant(0));
222        }
223        ProgramFragment pf = mRenderState.mFragment;
224        if (pf != null && pf.getConstantCount() > 0) {
225            mFragmentConstants = Allocation.createTyped(rs, pf.getConstant(0));
226        }
227
228        // Very important step that links available inputs and the constants vertex and
229        // fragment shader request
230        linkConstants();
231
232        ScriptField_ShaderParam_s pvParams = null, pfParams = null;
233        int paramCount = mVertexParamList.size();
234        if (paramCount != 0) {
235            pvParams = new ScriptField_ShaderParam_s(rs, paramCount);
236            for (int i = 0; i < paramCount; i++) {
237                pvParams.set(mVertexParamList.get(i).getRSData(rs), i, false);
238            }
239            pvParams.copyAll();
240        }
241
242        paramCount = mFragmentParamList.size();
243        if (paramCount != 0) {
244            pfParams = new ScriptField_ShaderParam_s(rs, paramCount);
245            for (int i = 0; i < paramCount; i++) {
246                pfParams.set(mFragmentParamList.get(i).getRSData(rs), i, false);
247            }
248            pfParams.copyAll();
249        }
250
251        mRsFieldItem = new ScriptField_Renderable_s.Item();
252        mRsFieldItem.mesh = mMesh;
253        mRsFieldItem.meshIndex = mMeshIndex;
254        mRsFieldItem.pv_const = mVertexConstants;
255        mRsFieldItem.pv_constParams = pvParams != null ? pvParams.getAllocation() : null;
256        mRsFieldItem.pf_const = mFragmentConstants;
257        mRsFieldItem.pf_constParams = pfParams != null ? pfParams.getAllocation() : null;
258        if (mTransform != null) {
259            mRsFieldItem.transformMatrix = mTransform.getRSData(rs).getAllocation();
260        }
261        mRsFieldItem.name = getStringAsAllocation(rs, getName());
262        mRsFieldItem.render_state = mRenderState.getRSData(rs).getAllocation();
263        mRsFieldItem.bVolInitialized = 0;
264        mRsFieldItem.cullType = mCullType;
265    }
266}
267
268
269
270
271
272