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