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.shaderstest;
18
19import android.content.res.Resources;
20import android.renderscript.Allocation;
21import android.renderscript.Element;
22import android.renderscript.Element.DataKind;
23import android.renderscript.Element.DataType;
24import android.renderscript.FileA3D;
25import android.renderscript.Mesh;
26import android.renderscript.Program;
27import android.renderscript.ProgramFragment;
28import android.renderscript.ProgramFragmentFixedFunction;
29import android.renderscript.ProgramStore;
30import android.renderscript.ProgramStore.DepthFunc;
31import android.renderscript.ProgramVertex;
32import android.renderscript.ProgramVertexFixedFunction;
33import android.renderscript.RSRuntimeException;
34import android.renderscript.RenderScriptGL;
35import android.renderscript.Sampler;
36import android.renderscript.Type.Builder;
37
38@SuppressWarnings({"FieldCanBeLocal"})
39public class ShadersTestRS {
40    public ShadersTestRS() {
41    }
42
43    public void init(RenderScriptGL rs, Resources res) {
44        mRS = rs;
45        mRes = res;
46        initRS();
47    }
48
49    public void surfaceChanged() {
50        initBuffers(mRS.getWidth(), mRS.getHeight());
51    }
52
53    private Resources mRes;
54    private RenderScriptGL mRS;
55    private Sampler mLinearClamp;
56    private Sampler mNearestClamp;
57    private ProgramStore mPSBackground;
58    private ProgramFragment mPFBackground;
59    private ProgramVertex mPVBackground;
60    private ProgramVertexFixedFunction.Constants mPVA;
61
62    private ProgramFragment mPFVignette;
63    private ScriptField_VignetteConstants_s mFSVignetteConst;
64
65    private Allocation mMeshTexture;
66    private Allocation mScreen;
67    private Allocation mScreenDepth;
68
69    private ScriptField_MeshInfo mMeshes;
70    private ScriptC_shaderstest mScript;
71
72
73    public void onActionDown(float x, float y) {
74        mScript.invoke_onActionDown(x, y);
75    }
76
77    public void onActionScale(float scale) {
78        mScript.invoke_onActionScale(scale);
79    }
80
81    public void onActionMove(float x, float y) {
82        mScript.invoke_onActionMove(x, y);
83    }
84
85    private void initPFS() {
86        ProgramStore.Builder b = new ProgramStore.Builder(mRS);
87
88        b.setDepthFunc(DepthFunc.LESS);
89        b.setDitherEnabled(false);
90        b.setDepthMaskEnabled(true);
91        mPSBackground = b.create();
92
93        mScript.set_gPFSBackground(mPSBackground);
94    }
95
96    private void initPF() {
97        mLinearClamp = Sampler.CLAMP_LINEAR(mRS);
98        mScript.set_gLinear(mLinearClamp);
99
100        mNearestClamp = Sampler.CLAMP_NEAREST(mRS);
101        mScript.set_gNearest(mNearestClamp);
102
103        ProgramFragmentFixedFunction.Builder b = new ProgramFragmentFixedFunction.Builder(mRS);
104        b.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
105                     ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
106        mPFBackground = b.create();
107        mPFBackground.bindSampler(mLinearClamp, 0);
108        mScript.set_gPFBackground(mPFBackground);
109
110        mFSVignetteConst = new ScriptField_VignetteConstants_s(mRS, 1);
111        mScript.bind_gFSVignetteConstants(mFSVignetteConst);
112
113        ProgramFragment.Builder fs;
114
115        fs = new ProgramFragment.Builder(mRS);
116        fs.setShader(mRes, R.raw.vignette_fs);
117        fs.addConstant(mFSVignetteConst.getAllocation().getType());
118        fs.addTexture(Program.TextureType.TEXTURE_2D);
119        mPFVignette = fs.create();
120        mPFVignette.bindConstants(mFSVignetteConst.getAllocation(), 0);
121        mScript.set_gPFVignette(mPFVignette);
122    }
123
124    private void initPV() {
125        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
126        mPVBackground = pvb.create();
127
128        mPVA = new ProgramVertexFixedFunction.Constants(mRS);
129        ((ProgramVertexFixedFunction) mPVBackground).bindConstants(mPVA);
130
131        mScript.set_gPVBackground(mPVBackground);
132    }
133
134    private void loadImage() {
135        mMeshTexture = Allocation.createFromBitmapResource(mRS, mRes, R.drawable.robot,
136                Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
137                Allocation.USAGE_GRAPHICS_TEXTURE);
138        mScript.set_gTMesh(mMeshTexture);
139    }
140
141    private void initMeshes(FileA3D model) {
142        int numEntries = model.getIndexEntryCount();
143        int numMeshes = 0;
144        for (int i = 0; i < numEntries; i ++) {
145            FileA3D.IndexEntry entry = model.getIndexEntry(i);
146            if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) {
147                numMeshes ++;
148            }
149        }
150
151        if (numMeshes > 0) {
152            mMeshes = new ScriptField_MeshInfo(mRS, numMeshes);
153
154            for (int i = 0; i < numEntries; i ++) {
155                FileA3D.IndexEntry entry = model.getIndexEntry(i);
156                if (entry != null && entry.getEntryType() == FileA3D.EntryType.MESH) {
157                    Mesh mesh = entry.getMesh();
158                    mMeshes.set_mMesh(i, mesh, false);
159                    mMeshes.set_mNumIndexSets(i, mesh.getPrimitiveCount(), false);
160                }
161            }
162            mMeshes.copyAll();
163        } else {
164            throw new RSRuntimeException("No valid meshes in file");
165        }
166
167        mScript.bind_gMeshes(mMeshes);
168        mScript.invoke_updateMeshInfo();
169    }
170
171    private void initRS() {
172        mScript = new ScriptC_shaderstest(mRS, mRes, R.raw.shaderstest);
173
174        initPFS();
175        initPF();
176        initPV();
177
178        loadImage();
179
180        initBuffers(1, 1);
181
182        FileA3D model = FileA3D.createFromResource(mRS, mRes, R.raw.robot);
183        initMeshes(model);
184
185        mRS.bindRootScript(mScript);
186    }
187
188    private void initBuffers(int width, int height) {
189        Builder b;
190        b = new Builder(mRS, Element.RGBA_8888(mRS));
191        b.setX(width).setY(height);
192        mScreen = Allocation.createTyped(mRS, b.create(),
193                Allocation.USAGE_GRAPHICS_TEXTURE | Allocation.USAGE_GRAPHICS_RENDER_TARGET);
194        mScript.set_gScreen(mScreen);
195
196        b = new Builder(mRS, Element.createPixel(mRS, DataType.UNSIGNED_16, DataKind.PIXEL_DEPTH));
197        b.setX(width).setY(height);
198        mScreenDepth = Allocation.createTyped(mRS, b.create(),
199                Allocation.USAGE_GRAPHICS_RENDER_TARGET);
200        mScript.set_gScreenDepth(mScreenDepth);
201    }
202}
203