Program.java revision e07694b24f7d12d72b084b6651356681ebd0efd6
1/*
2 * Copyright (C) 2008 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 android.renderscript;
18
19
20import java.io.IOException;
21import java.io.InputStream;
22import java.io.UnsupportedEncodingException;
23
24import android.content.res.Resources;
25import android.util.Log;
26
27
28/**
29 *
30 * Program is a base class for all the objects that modify
31 * various stages of the graphics pipeline
32 *
33 **/
34public class Program extends BaseObj {
35    static final int MAX_INPUT = 8;
36    static final int MAX_OUTPUT = 8;
37    static final int MAX_CONSTANT = 8;
38    static final int MAX_TEXTURE = 8;
39
40    /**
41     *
42     * TextureType specifies what textures are attached to Program
43     * objects
44     *
45     **/
46    public enum TextureType {
47        TEXTURE_2D (0),
48        TEXTURE_CUBE (1);
49
50        int mID;
51        TextureType(int id) {
52            mID = id;
53        }
54    }
55
56    enum ProgramParam {
57        INPUT (0),
58        OUTPUT (1),
59        CONSTANT (2),
60        TEXTURE_TYPE (3);
61
62        int mID;
63        ProgramParam(int id) {
64            mID = id;
65        }
66    };
67
68    Element mInputs[];
69    Element mOutputs[];
70    Type mConstants[];
71    TextureType mTextures[];
72    String mTextureNames[];
73    int mTextureCount;
74    String mShader;
75
76    Program(int id, RenderScript rs) {
77        super(id, rs);
78    }
79
80    /**
81     * @hide
82     */
83    public int getConstantCount() {
84        return mConstants != null ? mConstants.length : 0;
85    }
86
87    /**
88     * @hide
89     */
90    public Type getConstant(int slot) {
91        if (slot < 0 || slot >= mConstants.length) {
92            throw new IllegalArgumentException("Slot ID out of range.");
93        }
94        return mConstants[slot];
95    }
96
97    /**
98     * @hide
99     */
100    public int getTextureCount() {
101        return mTextureCount;
102    }
103
104    /**
105     * @hide
106     */
107    public TextureType getTextureType(int slot) {
108        if ((slot < 0) || (slot >= mTextureCount)) {
109            throw new IllegalArgumentException("Slot ID out of range.");
110        }
111        return mTextures[slot];
112    }
113
114    /**
115     * @hide
116     */
117    public String getTextureName(int slot) {
118        if ((slot < 0) || (slot >= mTextureCount)) {
119            throw new IllegalArgumentException("Slot ID out of range.");
120        }
121        return mTextureNames[slot];
122    }
123
124    /**
125     * Binds a constant buffer to be used as uniform inputs to the
126     * program
127     *
128     * @param a allocation containing uniform data
129     * @param slot index within the program's list of constant
130     *             buffer allocations
131     */
132    public void bindConstants(Allocation a, int slot) {
133        if (slot < 0 || slot >= mConstants.length) {
134            throw new IllegalArgumentException("Slot ID out of range.");
135        }
136        if (a != null &&
137            a.getType().getID(mRS) != mConstants[slot].getID(mRS)) {
138            throw new IllegalArgumentException("Allocation type does not match slot type.");
139        }
140        int id = a != null ? a.getID(mRS) : 0;
141        mRS.nProgramBindConstants(getID(mRS), slot, id);
142    }
143
144    /**
145     * Binds a texture to be used in the program
146     *
147     * @param va allocation containing texture data
148     * @param slot index within the program's list of textures
149     *
150     */
151    public void bindTexture(Allocation va, int slot)
152        throws IllegalArgumentException {
153        mRS.validate();
154        if ((slot < 0) || (slot >= mTextureCount)) {
155            throw new IllegalArgumentException("Slot ID out of range.");
156        }
157        if (va != null && va.getType().hasFaces() &&
158            mTextures[slot] != TextureType.TEXTURE_CUBE) {
159            throw new IllegalArgumentException("Cannot bind cubemap to 2d texture slot");
160        }
161
162        int id = va != null ? va.getID(mRS) : 0;
163        mRS.nProgramBindTexture(getID(mRS), slot, id);
164    }
165
166    /**
167     * Binds an object that describes how a texture at the
168     * corresponding location is sampled
169     *
170     * @param vs sampler for a corresponding texture
171     * @param slot index within the program's list of textures to
172     *             use the sampler on
173     *
174     */
175    public void bindSampler(Sampler vs, int slot)
176        throws IllegalArgumentException {
177        mRS.validate();
178        if ((slot < 0) || (slot >= mTextureCount)) {
179            throw new IllegalArgumentException("Slot ID out of range.");
180        }
181
182        int id = vs != null ? vs.getID(mRS) : 0;
183        mRS.nProgramBindSampler(getID(mRS), slot, id);
184    }
185
186
187    public static class BaseProgramBuilder {
188        RenderScript mRS;
189        Element mInputs[];
190        Element mOutputs[];
191        Type mConstants[];
192        Type mTextures[];
193        TextureType mTextureTypes[];
194        String mTextureNames[];
195        int mInputCount;
196        int mOutputCount;
197        int mConstantCount;
198        int mTextureCount;
199        String mShader;
200
201
202        protected BaseProgramBuilder(RenderScript rs) {
203            mRS = rs;
204            mInputs = new Element[MAX_INPUT];
205            mOutputs = new Element[MAX_OUTPUT];
206            mConstants = new Type[MAX_CONSTANT];
207            mInputCount = 0;
208            mOutputCount = 0;
209            mConstantCount = 0;
210            mTextureCount = 0;
211            mTextureTypes = new TextureType[MAX_TEXTURE];
212            mTextureNames = new String[MAX_TEXTURE];
213        }
214
215        /**
216         * Sets the GLSL shader code to be used in the program
217         *
218         * @param s GLSL shader string
219         * @return  self
220         */
221        public BaseProgramBuilder setShader(String s) {
222            mShader = s;
223            return this;
224        }
225
226        /**
227         * Sets the GLSL shader code to be used in the program
228         *
229         * @param resources application resources
230         * @param resourceID id of the file containing GLSL shader code
231         *
232         * @return  self
233         */
234        public BaseProgramBuilder setShader(Resources resources, int resourceID) {
235            byte[] str;
236            int strLength;
237            InputStream is = resources.openRawResource(resourceID);
238            try {
239                try {
240                    str = new byte[1024];
241                    strLength = 0;
242                    while(true) {
243                        int bytesLeft = str.length - strLength;
244                        if (bytesLeft == 0) {
245                            byte[] buf2 = new byte[str.length * 2];
246                            System.arraycopy(str, 0, buf2, 0, str.length);
247                            str = buf2;
248                            bytesLeft = str.length - strLength;
249                        }
250                        int bytesRead = is.read(str, strLength, bytesLeft);
251                        if (bytesRead <= 0) {
252                            break;
253                        }
254                        strLength += bytesRead;
255                    }
256                } finally {
257                    is.close();
258                }
259            } catch(IOException e) {
260                throw new Resources.NotFoundException();
261            }
262
263            try {
264                mShader = new String(str, 0, strLength, "UTF-8");
265            } catch (UnsupportedEncodingException e) {
266                Log.e("Renderscript shader creation", "Could not decode shader string");
267            }
268
269            return this;
270        }
271
272        /**
273         * Queries the index of the last added constant buffer type
274         *
275         */
276        public int getCurrentConstantIndex() {
277            return mConstantCount - 1;
278        }
279
280        /**
281         * Queries the index of the last added texture type
282         *
283         */
284        public int getCurrentTextureIndex() {
285            return mTextureCount - 1;
286        }
287
288        /**
289         * Adds constant (uniform) inputs to the program
290         *
291         * @param t Type that describes the layout of the Allocation
292         *          object to be used as constant inputs to the Program
293         * @return  self
294         */
295        public BaseProgramBuilder addConstant(Type t) throws IllegalStateException {
296            // Should check for consistant and non-conflicting names...
297            if(mConstantCount >= MAX_CONSTANT) {
298                throw new RSIllegalArgumentException("Max input count exceeded.");
299            }
300            if (t.getElement().isComplex()) {
301                throw new RSIllegalArgumentException("Complex elements not allowed.");
302            }
303            mConstants[mConstantCount] = t;
304            mConstantCount++;
305            return this;
306        }
307
308        /**
309         * Adds a texture input to the Program
310         *
311         * @param texType describes that the texture to append it (2D,
312         *                Cubemap, etc.)
313         * @return  self
314         */
315        public BaseProgramBuilder addTexture(TextureType texType) throws IllegalArgumentException {
316            addTexture(texType, "Tex" + mTextureCount);
317            return this;
318        }
319
320        /**
321         * @hide
322         * Adds a texture input to the Program
323         *
324         * @param texType describes that the texture to append it (2D,
325         *                Cubemap, etc.)
326         * @param texName what the texture should be called in the
327         *                shader
328         * @return  self
329         */
330        public BaseProgramBuilder addTexture(TextureType texType, String texName)
331            throws IllegalArgumentException {
332            if(mTextureCount >= MAX_TEXTURE) {
333                throw new IllegalArgumentException("Max texture count exceeded.");
334            }
335            mTextureTypes[mTextureCount] = texType;
336            mTextureNames[mTextureCount] = texName;
337            mTextureCount ++;
338            return this;
339        }
340
341        protected void initProgram(Program p) {
342            p.mInputs = new Element[mInputCount];
343            System.arraycopy(mInputs, 0, p.mInputs, 0, mInputCount);
344            p.mOutputs = new Element[mOutputCount];
345            System.arraycopy(mOutputs, 0, p.mOutputs, 0, mOutputCount);
346            p.mConstants = new Type[mConstantCount];
347            System.arraycopy(mConstants, 0, p.mConstants, 0, mConstantCount);
348            p.mTextureCount = mTextureCount;
349            p.mTextures = new TextureType[mTextureCount];
350            System.arraycopy(mTextureTypes, 0, p.mTextures, 0, mTextureCount);
351            p.mTextureNames = new String[mTextureCount];
352            System.arraycopy(mTextureNames, 0, p.mTextureNames, 0, mTextureCount);
353        }
354    }
355
356}
357
358
359