• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 
18 package android.filterfw.core;
19 
20 import android.filterfw.core.Frame;
21 import android.filterfw.core.NativeAllocatorTag;
22 import android.filterfw.core.Program;
23 import android.filterfw.core.StopWatchMap;
24 import android.filterfw.core.VertexFrame;
25 import android.filterfw.geometry.Quad;
26 import android.opengl.GLES20;
27 
28 /**
29  * @hide
30  */
31 public class ShaderProgram extends Program {
32 
33     private int shaderProgramId;
34 
35     private int mMaxTileSize = 0;
36 
37     // Keep a reference to the GL environment, so that it does not get deallocated while there
38     // are still programs living in it.
39     private GLEnvironment mGLEnvironment;
40 
41     private StopWatchMap mTimer = null;
42 
setTimer()43     private void setTimer() {
44         mTimer = new StopWatchMap();
45     }
46 
47     // Used from native layer for creating empty wrapper only!
ShaderProgram()48     private ShaderProgram() {
49     }
50 
ShaderProgram(NativeAllocatorTag tag)51     private ShaderProgram(NativeAllocatorTag tag) {
52     }
53 
ShaderProgram(FilterContext context, String fragmentShader)54     public ShaderProgram(FilterContext context, String fragmentShader) {
55         mGLEnvironment = getGLEnvironment(context);
56         allocate(mGLEnvironment, null, fragmentShader);
57         if (!compileAndLink()) {
58             throw new RuntimeException("Could not compile and link shader!");
59         }
60         this.setTimer();
61     }
62 
ShaderProgram(FilterContext context, String vertexShader, String fragmentShader)63     public ShaderProgram(FilterContext context, String vertexShader, String fragmentShader) {
64         mGLEnvironment = getGLEnvironment(context);
65         allocate(mGLEnvironment, vertexShader, fragmentShader);
66         if (!compileAndLink()) {
67             throw new RuntimeException("Could not compile and link shader!");
68         }
69         this.setTimer();
70     }
71 
createIdentity(FilterContext context)72     public static ShaderProgram createIdentity(FilterContext context) {
73         ShaderProgram program = nativeCreateIdentity(getGLEnvironment(context));
74         program.setTimer();
75         return program;
76     }
77 
78     @Override
finalize()79     protected void finalize() throws Throwable {
80         deallocate();
81     }
82 
getGLEnvironment()83     public GLEnvironment getGLEnvironment() {
84         return mGLEnvironment;
85     }
86 
87     @Override
process(Frame[] inputs, Frame output)88     public void process(Frame[] inputs, Frame output) {
89         if (mTimer.LOG_MFF_RUNNING_TIMES) {
90           mTimer.start("glFinish");
91           GLES20.glFinish();
92           mTimer.stop("glFinish");
93         }
94 
95         // Get the GL input frames
96         // TODO: We do the same in the NativeProgram... can we find a better way?!
97         GLFrame[] glInputs = new GLFrame[inputs.length];
98         for (int i = 0; i < inputs.length; ++i) {
99             if (inputs[i] instanceof GLFrame) {
100                 glInputs[i] = (GLFrame)inputs[i];
101             } else {
102                 throw new RuntimeException("ShaderProgram got non-GL frame as input " + i + "!");
103             }
104         }
105 
106         // Get the GL output frame
107         GLFrame glOutput = null;
108         if (output instanceof GLFrame) {
109             glOutput = (GLFrame)output;
110         } else {
111             throw new RuntimeException("ShaderProgram got non-GL output frame!");
112         }
113 
114         // Adjust tiles to meet maximum tile size requirement
115         if (mMaxTileSize > 0) {
116             int xTiles = (output.getFormat().getWidth() + mMaxTileSize - 1) / mMaxTileSize;
117             int yTiles = (output.getFormat().getHeight() + mMaxTileSize - 1) / mMaxTileSize;
118             setShaderTileCounts(xTiles, yTiles);
119         }
120 
121         // Process!
122         if (!shaderProcess(glInputs, glOutput)) {
123             throw new RuntimeException("Error executing ShaderProgram!");
124         }
125 
126         if (mTimer.LOG_MFF_RUNNING_TIMES) {
127           GLES20.glFinish();
128         }
129     }
130 
131     @Override
setHostValue(String variableName, Object value)132     public void setHostValue(String variableName, Object value) {
133         if (!setUniformValue(variableName, value)) {
134             throw new RuntimeException("Error setting uniform value for variable '" +
135                                        variableName + "'!");
136         }
137     }
138 
139     @Override
getHostValue(String variableName)140     public Object getHostValue(String variableName) {
141         return getUniformValue(variableName);
142     }
143 
setAttributeValues(String attributeName, float[] data, int componentCount)144     public void setAttributeValues(String attributeName, float[] data, int componentCount) {
145         if (!setShaderAttributeValues(attributeName, data, componentCount)) {
146             throw new RuntimeException("Error setting attribute value for attribute '" +
147                                        attributeName + "'!");
148         }
149     }
150 
setAttributeValues(String attributeName, VertexFrame vertexData, int type, int componentCount, int strideInBytes, int offsetInBytes, boolean normalize)151     public void setAttributeValues(String attributeName,
152                                    VertexFrame vertexData,
153                                    int type,
154                                    int componentCount,
155                                    int strideInBytes,
156                                    int offsetInBytes,
157                                    boolean normalize) {
158         if (!setShaderAttributeVertexFrame(attributeName,
159                                            vertexData,
160                                            type,
161                                            componentCount,
162                                            strideInBytes,
163                                            offsetInBytes,
164                                            normalize)) {
165             throw new RuntimeException("Error setting attribute value for attribute '" +
166                                        attributeName + "'!");
167         }
168     }
169 
setSourceRegion(Quad region)170     public void setSourceRegion(Quad region) {
171         setSourceRegion(region.p0.x, region.p0.y,
172                         region.p1.x, region.p1.y,
173                         region.p2.x, region.p2.y,
174                         region.p3.x, region.p3.y);
175     }
176 
setTargetRegion(Quad region)177     public void setTargetRegion(Quad region) {
178         setTargetRegion(region.p0.x, region.p0.y,
179                         region.p1.x, region.p1.y,
180                         region.p2.x, region.p2.y,
181                         region.p3.x, region.p3.y);
182     }
183 
setSourceRect(float x, float y, float width, float height)184     public void setSourceRect(float x, float y, float width, float height) {
185         setSourceRegion(x, y, x + width, y, x, y + height, x + width, y + height);
186     }
187 
setTargetRect(float x, float y, float width, float height)188     public void setTargetRect(float x, float y, float width, float height) {
189         setTargetRegion(x, y, x + width, y, x, y + height, x + width, y + height);
190     }
191 
setClearsOutput(boolean clears)192     public void setClearsOutput(boolean clears) {
193         if (!setShaderClearsOutput(clears)) {
194             throw new RuntimeException("Could not set clears-output flag to " + clears + "!");
195         }
196     }
197 
setClearColor(float r, float g, float b)198     public void setClearColor(float r, float g, float b) {
199         if (!setShaderClearColor(r, g, b)) {
200             throw new RuntimeException("Could not set clear color to " + r + "," + g + "," + b + "!");
201         }
202     }
203 
setBlendEnabled(boolean enable)204     public void setBlendEnabled(boolean enable) {
205         if (!setShaderBlendEnabled(enable)) {
206             throw new RuntimeException("Could not set Blending " + enable + "!");
207         }
208     }
209 
setBlendFunc(int sfactor, int dfactor)210     public void setBlendFunc(int sfactor, int dfactor) {
211         if (!setShaderBlendFunc(sfactor, dfactor)) {
212             throw new RuntimeException("Could not set BlendFunc " + sfactor +","+ dfactor + "!");
213         }
214     }
215 
setDrawMode(int drawMode)216     public void setDrawMode(int drawMode) {
217         if (!setShaderDrawMode(drawMode)) {
218             throw new RuntimeException("Could not set GL draw-mode to " + drawMode + "!");
219         }
220     }
221 
setVertexCount(int count)222     public void setVertexCount(int count) {
223         if (!setShaderVertexCount(count)) {
224             throw new RuntimeException("Could not set GL vertex count to " + count + "!");
225         }
226     }
227 
setMaximumTileSize(int size)228     public void setMaximumTileSize(int size) {
229         mMaxTileSize = size;
230     }
231 
beginDrawing()232     public void beginDrawing() {
233         if (!beginShaderDrawing()) {
234             throw new RuntimeException("Could not prepare shader-program for drawing!");
235         }
236     }
237 
getGLEnvironment(FilterContext context)238     private static GLEnvironment getGLEnvironment(FilterContext context) {
239         GLEnvironment result = context != null ? context.getGLEnvironment() : null;
240         if (result == null) {
241             throw new NullPointerException("Attempting to create ShaderProgram with no GL "
242                 + "environment in place!");
243         }
244         return result;
245     }
246 
247     static {
248         System.loadLibrary("filterfw");
249     }
250 
allocate(GLEnvironment glEnv, String vertexShader, String fragmentShader)251     private native boolean allocate(GLEnvironment glEnv,
252                                     String vertexShader,
253                                     String fragmentShader);
254 
deallocate()255     private native boolean deallocate();
256 
compileAndLink()257     private native boolean compileAndLink();
258 
shaderProcess(GLFrame[] inputs, GLFrame output)259     private native boolean shaderProcess(GLFrame[] inputs, GLFrame output);
260 
setUniformValue(String name, Object value)261     private native boolean setUniformValue(String name, Object value);
262 
getUniformValue(String name)263     private native Object getUniformValue(String name);
264 
setSourceRegion(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)265     public native boolean setSourceRegion(float x0, float y0, float x1, float y1,
266                                           float x2, float y2, float x3, float y3);
267 
setTargetRegion(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)268     private native boolean setTargetRegion(float x0, float y0, float x1, float y1,
269                                            float x2, float y2, float x3, float y3);
270 
nativeCreateIdentity(GLEnvironment glEnv)271     private static native ShaderProgram nativeCreateIdentity(GLEnvironment glEnv);
272 
setShaderClearsOutput(boolean clears)273     private native boolean setShaderClearsOutput(boolean clears);
274 
setShaderBlendEnabled(boolean enable)275     private native boolean setShaderBlendEnabled(boolean enable);
276 
setShaderBlendFunc(int sfactor, int dfactor)277     private native boolean setShaderBlendFunc(int sfactor, int dfactor);
278 
setShaderClearColor(float r, float g, float b)279     private native boolean setShaderClearColor(float r, float g, float b);
280 
setShaderDrawMode(int drawMode)281     private native boolean setShaderDrawMode(int drawMode);
282 
setShaderTileCounts(int xCount, int yCount)283     private native boolean setShaderTileCounts(int xCount, int yCount);
284 
setShaderVertexCount(int vertexCount)285     private native boolean setShaderVertexCount(int vertexCount);
286 
beginShaderDrawing()287     private native boolean beginShaderDrawing();
288 
setShaderAttributeValues(String attributeName, float[] data, int componentCount)289     private native boolean setShaderAttributeValues(String attributeName,
290                                                     float[] data,
291                                                     int componentCount);
292 
setShaderAttributeVertexFrame(String attributeName, VertexFrame vertexData, int type, int componentCount, int strideInBytes, int offsetInBytes, boolean normalize)293     private native boolean setShaderAttributeVertexFrame(String attributeName,
294                                                          VertexFrame vertexData,
295                                                          int type,
296                                                          int componentCount,
297                                                          int strideInBytes,
298                                                          int offsetInBytes,
299                                                          boolean normalize);
300 
301 }
302