165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/*
265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Copyright (C) 2011 The Android Open Source Project
365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Licensed under the Apache License, Version 2.0 (the "License");
565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * you may not use this file except in compliance with the License.
665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * You may obtain a copy of the License at
765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *      http://www.apache.org/licenses/LICENSE-2.0
965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn *
1065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unless required by applicable law or agreed to in writing, software
1165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * distributed under the License is distributed on an "AS IS" BASIS,
1265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * See the License for the specific language governing permissions and
1465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * limitations under the License.
1565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
1665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
1865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpackage android.filterfw.core;
1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.Frame;
2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.NativeAllocatorTag;
2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.Program;
2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.StopWatchMap;
2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.VertexFrame;
2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.geometry.Quad;
2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.opengl.GLES20;
2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/**
2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * @hide
3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */
3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpublic class ShaderProgram extends Program {
3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private int shaderProgramId;
3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private int mMaxTileSize = 0;
3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // Keep a reference to the GL environment, so that it does not get deallocated while there
3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // are still programs living in it.
3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private GLEnvironment mGLEnvironment;
4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private StopWatchMap mTimer = null;
4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private void setTimer() {
4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mTimer = new StopWatchMap();
4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    // Used from native layer for creating empty wrapper only!
4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private ShaderProgram() {
4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private ShaderProgram(NativeAllocatorTag tag) {
5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public ShaderProgram(FilterContext context, String fragmentShader) {
5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mGLEnvironment = getGLEnvironment(context);
5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        allocate(mGLEnvironment, null, fragmentShader);
5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!compileAndLink()) {
5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not compile and link shader!");
5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        this.setTimer();
6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public ShaderProgram(FilterContext context, String vertexShader, String fragmentShader) {
6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mGLEnvironment = getGLEnvironment(context);
6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        allocate(mGLEnvironment, vertexShader, fragmentShader);
6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!compileAndLink()) {
6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not compile and link shader!");
6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        this.setTimer();
7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public static ShaderProgram createIdentity(FilterContext context) {
7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        ShaderProgram program = nativeCreateIdentity(getGLEnvironment(context));
7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        program.setTimer();
7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return program;
7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    protected void finalize() throws Throwable {
8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        deallocate();
8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public GLEnvironment getGLEnvironment() {
8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return mGLEnvironment;
8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void process(Frame[] inputs, Frame output) {
8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mTimer.LOG_MFF_RUNNING_TIMES) {
9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          mTimer.start("glFinish");
9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          GLES20.glFinish();
9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          mTimer.stop("glFinish");
9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Get the GL input frames
9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // TODO: We do the same in the NativeProgram... can we find a better way?!
9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        GLFrame[] glInputs = new GLFrame[inputs.length];
9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        for (int i = 0; i < inputs.length; ++i) {
9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            if (inputs[i] instanceof GLFrame) {
10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                glInputs[i] = (GLFrame)inputs[i];
10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            } else {
10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                throw new RuntimeException("ShaderProgram got non-GL frame as input " + i + "!");
10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            }
10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Get the GL output frame
10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        GLFrame glOutput = null;
10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (output instanceof GLFrame) {
10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            glOutput = (GLFrame)output;
11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        } else {
11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("ShaderProgram got non-GL output frame!");
11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Adjust tiles to meet maximum tile size requirement
11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mMaxTileSize > 0) {
11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            int xTiles = (output.getFormat().getWidth() + mMaxTileSize - 1) / mMaxTileSize;
11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            int yTiles = (output.getFormat().getHeight() + mMaxTileSize - 1) / mMaxTileSize;
11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            setShaderTileCounts(xTiles, yTiles);
11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        // Process!
12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!shaderProcess(glInputs, glOutput)) {
12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Error executing ShaderProgram!");
12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (mTimer.LOG_MFF_RUNNING_TIMES) {
12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn          GLES20.glFinish();
12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setHostValue(String variableName, Object value) {
13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!setUniformValue(variableName, value)) {
13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Error setting uniform value for variable '" +
13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                       variableName + "'!");
13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    @Override
14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public Object getHostValue(String variableName) {
14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return getUniformValue(variableName);
14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setAttributeValues(String attributeName, float[] data, int componentCount) {
14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!setShaderAttributeValues(attributeName, data, componentCount)) {
14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Error setting attribute value for attribute '" +
14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                       attributeName + "'!");
14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setAttributeValues(String attributeName,
15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                   VertexFrame vertexData,
15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                   int type,
15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                   int componentCount,
15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                   int strideInBytes,
15665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                   int offsetInBytes,
15765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                   boolean normalize) {
15865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!setShaderAttributeVertexFrame(attributeName,
15965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                           vertexData,
16065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                           type,
16165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                           componentCount,
16265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                           strideInBytes,
16365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                           offsetInBytes,
16465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                           normalize)) {
16565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Error setting attribute value for attribute '" +
16665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                       attributeName + "'!");
16765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
16865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
16965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
17065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setSourceRegion(Quad region) {
17165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        setSourceRegion(region.p0.x, region.p0.y,
17265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                        region.p1.x, region.p1.y,
17365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                        region.p2.x, region.p2.y,
17465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                        region.p3.x, region.p3.y);
17565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
17665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
17765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setTargetRegion(Quad region) {
17865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        setTargetRegion(region.p0.x, region.p0.y,
17965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                        region.p1.x, region.p1.y,
18065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                        region.p2.x, region.p2.y,
18165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                        region.p3.x, region.p3.y);
18265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
18365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
18465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setSourceRect(float x, float y, float width, float height) {
18565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        setSourceRegion(x, y, x + width, y, x, y + height, x + width, y + height);
18665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
18765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
18865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setTargetRect(float x, float y, float width, float height) {
18965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        setTargetRegion(x, y, x + width, y, x, y + height, x + width, y + height);
19065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
19165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
19265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setClearsOutput(boolean clears) {
19365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!setShaderClearsOutput(clears)) {
19465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not set clears-output flag to " + clears + "!");
19565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
19665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
19765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
19865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setClearColor(float r, float g, float b) {
19965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!setShaderClearColor(r, g, b)) {
20065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not set clear color to " + r + "," + g + "," + b + "!");
20165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
20265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
20365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
20465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setBlendEnabled(boolean enable) {
20565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!setShaderBlendEnabled(enable)) {
20665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not set Blending " + enable + "!");
20765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
20865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
20965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
21065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setBlendFunc(int sfactor, int dfactor) {
21165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!setShaderBlendFunc(sfactor, dfactor)) {
21265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not set BlendFunc " + sfactor +","+ dfactor + "!");
21365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
21465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
21565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
21665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setDrawMode(int drawMode) {
21765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!setShaderDrawMode(drawMode)) {
21865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not set GL draw-mode to " + drawMode + "!");
21965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
22065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
22165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
22265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setVertexCount(int count) {
22365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!setShaderVertexCount(count)) {
22465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not set GL vertex count to " + count + "!");
22565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
22665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
22765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
22865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void setMaximumTileSize(int size) {
22965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        mMaxTileSize = size;
23065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
23165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public void beginDrawing() {
23365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (!beginShaderDrawing()) {
23465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new RuntimeException("Could not prepare shader-program for drawing!");
23565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
23665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
23765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
23865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private static GLEnvironment getGLEnvironment(FilterContext context) {
23965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        GLEnvironment result = context != null ? context.getGLEnvironment() : null;
24065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        if (result == null) {
24165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn            throw new NullPointerException("Attempting to create ShaderProgram with no GL "
24265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                + "environment in place!");
24365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        }
24465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        return result;
24565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
24665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
24765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    static {
24865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn        System.loadLibrary("filterfw");
24965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    }
25065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
25165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean allocate(GLEnvironment glEnv,
25265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                    String vertexShader,
25365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                    String fragmentShader);
25465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
25565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean deallocate();
25665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
25765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean compileAndLink();
25865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
25965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean shaderProcess(GLFrame[] inputs, GLFrame output);
26065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
26165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean setUniformValue(String name, Object value);
26265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
26365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native Object getUniformValue(String name);
26465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
26565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    public native boolean setSourceRegion(float x0, float y0, float x1, float y1,
26665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                          float x2, float y2, float x3, float y3);
26765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
26865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean setTargetRegion(float x0, float y0, float x1, float y1,
26965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                           float x2, float y2, float x3, float y3);
27065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
27165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private static native ShaderProgram nativeCreateIdentity(GLEnvironment glEnv);
27265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
27365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean setShaderClearsOutput(boolean clears);
27465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
27565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean setShaderBlendEnabled(boolean enable);
27665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
27765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean setShaderBlendFunc(int sfactor, int dfactor);
27865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
27965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean setShaderClearColor(float r, float g, float b);
28065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
28165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean setShaderDrawMode(int drawMode);
28265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
28365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean setShaderTileCounts(int xCount, int yCount);
28465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
28565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean setShaderVertexCount(int vertexCount);
28665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
28765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean beginShaderDrawing();
28865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
28965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean setShaderAttributeValues(String attributeName,
29065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                    float[] data,
29165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                    int componentCount);
29265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
29365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn    private native boolean setShaderAttributeVertexFrame(String attributeName,
29465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                         VertexFrame vertexData,
29565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                         int type,
29665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                         int componentCount,
29765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                         int strideInBytes,
29865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                         int offsetInBytes,
29965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn                                                         boolean normalize);
30065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn
30165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn}
302