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;
21
22import com.android.scenegraph.TextureBase;
23
24import android.content.res.Resources;
25import android.renderscript.*;
26import android.renderscript.ProgramFragment.Builder;
27import android.util.Log;
28
29/**
30 * @hide
31 */
32public class FragmentShader extends Shader {
33    ProgramFragment mProgram;
34    ScriptField_FragmentShader_s mField;
35
36    public static class Builder {
37
38        FragmentShader mShader;
39        ProgramFragment.Builder mBuilder;
40
41        public Builder(RenderScriptGL rs) {
42            mShader = new FragmentShader();
43            mBuilder = new ProgramFragment.Builder(rs);
44        }
45
46        public Builder setShader(Resources resources, int resourceID) {
47            mBuilder.setShader(resources, resourceID);
48            return this;
49        }
50
51        public Builder setShader(String code) {
52            mBuilder.setShader(code);
53            return this;
54        }
55
56        public Builder setObjectConst(Type type) {
57            mShader.mPerObjConstants = type;
58            return this;
59        }
60
61        public Builder setShaderConst(Type type) {
62            mShader.mPerShaderConstants = type;
63            return this;
64        }
65
66        public Builder addShaderTexture(Program.TextureType texType, String name) {
67            mShader.mShaderTextureNames.add(name);
68            mShader.mShaderTextureTypes.add(texType);
69            return this;
70        }
71
72        public Builder addTexture(Program.TextureType texType, String name) {
73            mShader.mTextureNames.add(name);
74            mShader.mTextureTypes.add(texType);
75            return this;
76        }
77
78        public FragmentShader create() {
79            if (mShader.mPerShaderConstants != null) {
80                mBuilder.addConstant(mShader.mPerShaderConstants);
81            }
82            if (mShader.mPerObjConstants != null) {
83                mBuilder.addConstant(mShader.mPerObjConstants);
84            }
85            for (int i = 0; i < mShader.mTextureTypes.size(); i ++) {
86                mBuilder.addTexture(mShader.mTextureTypes.get(i),
87                                    mShader.mTextureNames.get(i));
88            }
89            for (int i = 0; i < mShader.mShaderTextureTypes.size(); i ++) {
90                mBuilder.addTexture(mShader.mShaderTextureTypes.get(i),
91                                    mShader.mShaderTextureNames.get(i));
92            }
93
94            mShader.mProgram = mBuilder.create();
95            return mShader;
96        }
97    }
98
99    public ProgramFragment getProgram() {
100        return mProgram;
101    }
102
103    ScriptField_ShaderParam_s getTextureParams() {
104        RenderScriptGL rs = SceneManager.getRS();
105        Resources res = SceneManager.getRes();
106        if (rs == null || res == null) {
107            return null;
108        }
109
110        ArrayList<ScriptField_ShaderParam_s.Item> paramList;
111        paramList = new ArrayList<ScriptField_ShaderParam_s.Item>();
112
113        int shaderTextureStart = mTextureTypes.size();
114        for (int i = 0; i < mShaderTextureNames.size(); i ++) {
115            ShaderParam sp = mSourceParams.get(mShaderTextureNames.get(i));
116            if (sp != null && sp instanceof TextureParam) {
117                TextureParam p = (TextureParam)sp;
118                ScriptField_ShaderParam_s.Item paramRS = new ScriptField_ShaderParam_s.Item();
119                paramRS.bufferOffset = shaderTextureStart + i;
120                paramRS.transformTimestamp = 0;
121                paramRS.dataTimestamp = 0;
122                paramRS.data = p.getRSData().getAllocation();
123                paramList.add(paramRS);
124            }
125        }
126
127        ScriptField_ShaderParam_s rsParams = null;
128        int paramCount = paramList.size();
129        if (paramCount != 0) {
130            rsParams = new ScriptField_ShaderParam_s(rs, paramCount);
131            for (int i = 0; i < paramCount; i++) {
132                rsParams.set(paramList.get(i), i, false);
133            }
134            rsParams.copyAll();
135        }
136        return rsParams;
137    }
138
139    ScriptField_FragmentShader_s getRSData() {
140        if (mField != null) {
141            return mField;
142        }
143
144        RenderScriptGL rs = SceneManager.getRS();
145        Resources res = SceneManager.getRes();
146        if (rs == null || res == null) {
147            return null;
148        }
149
150        ScriptField_FragmentShader_s.Item item = new ScriptField_FragmentShader_s.Item();
151        item.program = mProgram;
152
153        ScriptField_ShaderParam_s texParams = getTextureParams();
154        if (texParams != null) {
155            item.shaderTextureParams = texParams.getAllocation();
156        }
157
158        linkConstants(rs);
159        if (mPerShaderConstants != null) {
160            item.shaderConst = mConstantBuffer;
161            item.shaderConstParams = mConstantBufferParams.getAllocation();
162            mProgram.bindConstants(item.shaderConst, 0);
163        }
164
165        item.objectConstIndex = -1;
166        if (mPerObjConstants != null) {
167            item.objectConstIndex = mPerShaderConstants != null ? 1 : 0;
168        }
169
170        mField = new ScriptField_FragmentShader_s(rs, 1);
171        mField.set(item, 0, true);
172        return mField;
173    }
174}
175