From: Marius Renn Date: Mon, 18 Jul 2011 18:26:18 +0000 (-0700) Subject: Fixes to GL related classes. X-Git-Tag: android-x86-7.1-r1~888^2 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=511360e61650864ea22a171159efe073c80d0cdb;p=android-x86%2Fsystem-media.git Fixes to GL related classes. Patch: Java keeps reference to GLEnvironment to make sure it does not get deallocated before all its objects are deallocated. Change-Id: Ic3dffb84b2592cafc4df27331f63a44c221b19bd --- diff --git a/mca/filterfw/java/android/filterfw/MffEnvironment.java b/mca/filterfw/java/android/filterfw/MffEnvironment.java index a879bb67..1ab416a7 100644 --- a/mca/filterfw/java/android/filterfw/MffEnvironment.java +++ b/mca/filterfw/java/android/filterfw/MffEnvironment.java @@ -64,7 +64,7 @@ public class MffEnvironment { * the environment. */ public void setGLEnvironment(GLEnvironment glEnvironment) { - mContext.setGLEnvironment(glEnvironment); + mContext.initGLEnvironment(glEnvironment); } /** diff --git a/mca/filterfw/java/android/filterfw/basefilters/RetargetFilter.java b/mca/filterfw/java/android/filterfw/basefilters/RetargetFilter.java index c1db6557..254167a1 100644 --- a/mca/filterfw/java/android/filterfw/basefilters/RetargetFilter.java +++ b/mca/filterfw/java/android/filterfw/basefilters/RetargetFilter.java @@ -53,11 +53,7 @@ public class RetargetFilter extends Filter { @Override public FrameFormat getOutputFormat(String portName, FrameFormat inputFormat) { - return getRetargetedFormat(inputFormat); - } - - public FrameFormat getRetargetedFormat(FrameFormat format) { - MutableFrameFormat retargeted = format.mutableCopy(); + MutableFrameFormat retargeted = inputFormat.mutableCopy(); retargeted.setTarget(mTarget); return retargeted; } @@ -68,11 +64,7 @@ public class RetargetFilter extends Filter { Frame input = pullInput("frame"); // Create output frame - FrameFormat outFormat = getRetargetedFormat(input.getFormat()); - Frame output = context.getFrameManager().newFrame(outFormat); - - // Process - output.setDataFromFrame(input); + Frame output = context.getFrameManager().duplicateFrameToTarget(input, mTarget); // Push output pushOutput("frame", output); diff --git a/mca/filterfw/java/android/filterfw/core/FilterContext.java b/mca/filterfw/java/android/filterfw/core/FilterContext.java index e2592fc0..08bae553 100644 --- a/mca/filterfw/java/android/filterfw/core/FilterContext.java +++ b/mca/filterfw/java/android/filterfw/core/FilterContext.java @@ -52,15 +52,28 @@ public class FilterContext { } public void setFrameManager(FrameManager manager) { - mFrameManager = manager; + if (manager == null) { + throw new NullPointerException("Attempting to set null FrameManager!"); + } else if (manager.getContext() != null) { + throw new IllegalArgumentException("Attempting to set FrameManager which is already " + + "bound to another FilterContext!"); + } else { + mFrameManager = manager; + mFrameManager.setContext(this); + } } public GLEnvironment getGLEnvironment() { return mGLEnvironment; } - public void setGLEnvironment(GLEnvironment environment) { - mGLEnvironment = environment; + public void initGLEnvironment(GLEnvironment environment) { + if (mGLEnvironment == null) { + mGLEnvironment = environment; + } else { + throw new RuntimeException("Attempting to re-initialize GL Environment for " + + "FilterContext!"); + } } public interface OnFrameReceivedListener { diff --git a/mca/filterfw/java/android/filterfw/core/FilterPort.java b/mca/filterfw/java/android/filterfw/core/FilterPort.java index 7dd54082..9734b899 100644 --- a/mca/filterfw/java/android/filterfw/core/FilterPort.java +++ b/mca/filterfw/java/android/filterfw/core/FilterPort.java @@ -123,5 +123,12 @@ public abstract class FilterPort { + "Expected " + mPortFormat + " but got " + frame.getFormat()); } } + + protected void checkFrameManager(Frame frame, FilterContext context) { + if (frame.getFrameManager() != null + && frame.getFrameManager() != context.getFrameManager()) { + throw new RuntimeException("Frame " + frame + " is managed by foreign FrameManager! "); + } + } } diff --git a/mca/filterfw/java/android/filterfw/core/Frame.java b/mca/filterfw/java/android/filterfw/core/Frame.java index 257bbbaa..d891300a 100644 --- a/mca/filterfw/java/android/filterfw/core/Frame.java +++ b/mca/filterfw/java/android/filterfw/core/Frame.java @@ -149,6 +149,10 @@ public abstract class Frame { } } + public FrameManager getFrameManager() { + return mFrameManager; + } + protected void assertFrameMutable() { if (isReadOnly()) { throw new RuntimeException("Attempting to modify read-only frame!"); diff --git a/mca/filterfw/java/android/filterfw/core/FrameManager.java b/mca/filterfw/java/android/filterfw/core/FrameManager.java index 70fd4267..225c32c5 100644 --- a/mca/filterfw/java/android/filterfw/core/FrameManager.java +++ b/mca/filterfw/java/android/filterfw/core/FrameManager.java @@ -26,6 +26,8 @@ import android.filterfw.core.MutableFrameFormat; */ public abstract class FrameManager { + private FilterContext mContext; + public abstract Frame newFrame(FrameFormat format); public abstract Frame newBoundFrame(FrameFormat format, int bindingType, long bindingId); @@ -47,4 +49,16 @@ public abstract class FrameManager { public abstract Frame retainFrame(Frame frame); public abstract Frame releaseFrame(Frame frame); + + public FilterContext getContext() { + return mContext; + } + + public GLEnvironment getGLEnvironment() { + return mContext != null ? mContext.getGLEnvironment() : null; + } + + void setContext(FilterContext context) { + mContext = context; + } } diff --git a/mca/filterfw/java/android/filterfw/core/GLEnvironment.java b/mca/filterfw/java/android/filterfw/core/GLEnvironment.java index bcd14162..cd7fc98f 100644 --- a/mca/filterfw/java/android/filterfw/core/GLEnvironment.java +++ b/mca/filterfw/java/android/filterfw/core/GLEnvironment.java @@ -19,6 +19,8 @@ package android.filterfw.core; import android.filterfw.core.NativeAllocatorTag; import android.graphics.SurfaceTexture; +import android.os.Looper; +import android.util.Log; import android.view.Surface; /** @@ -40,10 +42,6 @@ public class GLEnvironment { nativeDeallocate(); } - public static GLEnvironment activeEnvironment() { - return nativeActiveEnvironment(); - } - public void initWithNewContext() { if (!nativeInitWithNewContext()) { throw new RuntimeException("Could not initialize GLEnvironment with new context!"); @@ -61,6 +59,9 @@ public class GLEnvironment { } public void activate() { + if (Looper.myLooper() != null && Looper.myLooper().equals(Looper.getMainLooper())) { + Log.e("GLEnvironment", "Activating GL context in UI thread!"); + } if (!nativeActivate()) { throw new RuntimeException("Could not activate GLEnvironment!"); } @@ -116,8 +117,6 @@ public class GLEnvironment { System.loadLibrary("filterfw"); } - private native static GLEnvironment nativeActiveEnvironment(); - private native boolean nativeInitWithNewContext(); private native boolean nativeInitWithCurrentContext(); diff --git a/mca/filterfw/java/android/filterfw/core/GLFrame.java b/mca/filterfw/java/android/filterfw/core/GLFrame.java index 85b9d261..8f5b401e 100644 --- a/mca/filterfw/java/android/filterfw/core/GLFrame.java +++ b/mca/filterfw/java/android/filterfw/core/GLFrame.java @@ -55,6 +55,10 @@ public class GLFrame extends Frame { private int glFrameId; + // Keep a reference to the GL environment, so that it does not get deallocated while there + // are still frames living in it. + private GLEnvironment mGLEnvironment; + GLFrame(FrameFormat format, FrameManager frameManager) { super(format, frameManager); } @@ -63,8 +67,9 @@ public class GLFrame extends Frame { super(format, frameManager, bindingType, bindingId); } - void init() { + void init(GLEnvironment glEnv) { FrameFormat format = getFormat(); + mGLEnvironment = glEnv; // Check that we have a valid format if (format.getBytesPerSample() != 4) { @@ -99,11 +104,11 @@ public class GLFrame extends Frame { private void initNew(boolean isExternal) { if (isExternal) { - if (!allocateExternal()) { + if (!allocateExternal(mGLEnvironment)) { throw new RuntimeException("Could not allocate external GL frame!"); } } else { - if (!allocate(getFormat().getWidth(), getFormat().getHeight())) { + if (!allocate(mGLEnvironment, getFormat().getWidth(), getFormat().getHeight())) { throw new RuntimeException("Could not allocate GL frame!"); } } @@ -112,7 +117,7 @@ public class GLFrame extends Frame { private void initWithTexture(int texId, boolean isNew) { int width = getFormat().getWidth(); int height = getFormat().getHeight(); - if (!allocateWithTexture(texId, width, height, isNew, isNew)) { + if (!allocateWithTexture(mGLEnvironment, texId, width, height, isNew, isNew)) { throw new RuntimeException("Could not allocate texture backed GL frame!"); } setReusable(isNew); @@ -121,7 +126,7 @@ public class GLFrame extends Frame { private void initWithFbo(int fboId, boolean isNew) { int width = getFormat().getWidth(); int height = getFormat().getHeight(); - if (!allocateWithFbo(fboId, width, height, isNew, isNew)) { + if (!allocateWithFbo(mGLEnvironment, fboId, width, height, isNew, isNew)) { throw new RuntimeException("Could not allocate FBO backed GL frame!"); } setReusable(isNew); @@ -141,6 +146,10 @@ public class GLFrame extends Frame { deallocate(); } + public GLEnvironment getGLEnvironment() { + return mGLEnvironment; + } + @Override public Object getObjectValue() { return ByteBuffer.wrap(getNativeData()); @@ -287,21 +296,23 @@ public class GLFrame extends Frame { System.loadLibrary("filterfw"); } - private native boolean allocate(int width, int height); + private native boolean allocate(GLEnvironment env, int width, int height); - private native boolean allocateWithTexture(int textureId, + private native boolean allocateWithTexture(GLEnvironment env, + int textureId, int width, int height, boolean owns, boolean create); - private native boolean allocateWithFbo(int fboId, + private native boolean allocateWithFbo(GLEnvironment env, + int fboId, int width, int height, boolean owns, boolean create); - private native boolean allocateExternal(); + private native boolean allocateExternal(GLEnvironment env); private native boolean deallocate(); diff --git a/mca/filterfw/java/android/filterfw/core/InputPort.java b/mca/filterfw/java/android/filterfw/core/InputPort.java index 12d19371..53e84422 100644 --- a/mca/filterfw/java/android/filterfw/core/InputPort.java +++ b/mca/filterfw/java/android/filterfw/core/InputPort.java @@ -77,6 +77,5 @@ public abstract class InputPort extends FilterPort { return !hasFrame(); } - public void transfer(FilterContext context) { - } + public abstract void transfer(FilterContext context); } diff --git a/mca/filterfw/java/android/filterfw/core/ShaderProgram.java b/mca/filterfw/java/android/filterfw/core/ShaderProgram.java index 0ebd4917..bed04b35 100644 --- a/mca/filterfw/java/android/filterfw/core/ShaderProgram.java +++ b/mca/filterfw/java/android/filterfw/core/ShaderProgram.java @@ -31,6 +31,11 @@ import android.opengl.GLES20; public class ShaderProgram extends Program { private int shaderProgramId; + + // Keep a reference to the GL environment, so that it does not get deallocated while there + // are still programs living in it. + private GLEnvironment mGLEnvironment; + private StopWatchMap mTimer = null; private void setTimer() { @@ -44,24 +49,26 @@ public class ShaderProgram extends Program { private ShaderProgram(NativeAllocatorTag tag) { } - public ShaderProgram(String fragmentShader) { - allocate(null, fragmentShader); + public ShaderProgram(FilterContext context, String fragmentShader) { + mGLEnvironment = getGLEnvironment(context); + allocate(mGLEnvironment, null, fragmentShader); if (!compileAndLink()) { throw new RuntimeException("Could not compile and link shader!"); } this.setTimer(); } - public ShaderProgram(String vertexShader, String fragmentShader) { - allocate(vertexShader, fragmentShader); + public ShaderProgram(FilterContext context, String vertexShader, String fragmentShader) { + mGLEnvironment = getGLEnvironment(context); + allocate(mGLEnvironment, vertexShader, fragmentShader); if (!compileAndLink()) { throw new RuntimeException("Could not compile and link shader!"); } this.setTimer(); } - public static ShaderProgram createIdentity() { - ShaderProgram program = nativeCreateIdentity(); + public static ShaderProgram createIdentity(FilterContext context) { + ShaderProgram program = nativeCreateIdentity(getGLEnvironment(context)); program.setTimer(); return program; } @@ -71,6 +78,10 @@ public class ShaderProgram extends Program { deallocate(); } + public GLEnvironment getGLEnvironment() { + return mGLEnvironment; + } + @Override public void process(Frame[] inputs, Frame output) { if (mTimer.LOG_MFF_RUNNING_TIMES) { @@ -211,11 +222,22 @@ public class ShaderProgram extends Program { } } + private static GLEnvironment getGLEnvironment(FilterContext context) { + GLEnvironment result = context != null ? context.getGLEnvironment() : null; + if (result == null) { + throw new NullPointerException("Attempting to create ShaderProgram with no GL " + + "environment in place!"); + } + return result; + } + static { System.loadLibrary("filterfw"); } - private native boolean allocate(String vertexShader, String fragmentShader); + private native boolean allocate(GLEnvironment glEnv, + String vertexShader, + String fragmentShader); private native boolean deallocate(); @@ -233,7 +255,7 @@ public class ShaderProgram extends Program { private native boolean setShaderTargetRegion(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3); - private static native ShaderProgram nativeCreateIdentity(); + private static native ShaderProgram nativeCreateIdentity(GLEnvironment glEnv); private native boolean setShaderClearsOutput(boolean clears); diff --git a/mca/filterfw/java/android/filterfw/core/SimpleFrameManager.java b/mca/filterfw/java/android/filterfw/core/SimpleFrameManager.java index 5b85dd55..32877e4b 100644 --- a/mca/filterfw/java/android/filterfw/core/SimpleFrameManager.java +++ b/mca/filterfw/java/android/filterfw/core/SimpleFrameManager.java @@ -46,7 +46,7 @@ public class SimpleFrameManager extends FrameManager { switch(format.getTarget()) { case FrameFormat.TARGET_GPU: { GLFrame glFrame = new GLFrame(format, this, bindingType, bindingId); - glFrame.init(); + glFrame.init(getGLEnvironment()); result = glFrame; break; } @@ -71,7 +71,7 @@ public class SimpleFrameManager extends FrameManager { case FrameFormat.TARGET_GPU: { GLFrame glFrame = new GLFrame(format, this); - glFrame.init(); + glFrame.init(getGLEnvironment()); result = glFrame; break; } diff --git a/mca/filterfw/java/android/filterfw/core/StreamPort.java b/mca/filterfw/java/android/filterfw/core/StreamPort.java index c6035954..0866b00a 100644 --- a/mca/filterfw/java/android/filterfw/core/StreamPort.java +++ b/mca/filterfw/java/android/filterfw/core/StreamPort.java @@ -90,4 +90,11 @@ public class StreamPort extends InputPort { public String toString() { return "input " + super.toString(); } + + @Override + public void transfer(FilterContext context) { + if (mFrame != null) { + checkFrameManager(mFrame, context); + } + } } diff --git a/mca/filterfw/jni/jni_gl_environment.cpp b/mca/filterfw/jni/jni_gl_environment.cpp index 329be644..f7ccc71e 100644 --- a/mca/filterfw/jni/jni_gl_environment.cpp +++ b/mca/filterfw/jni/jni_gl_environment.cpp @@ -85,12 +85,6 @@ jboolean Java_android_filterfw_core_GLEnvironment_nativeDeactivate(JNIEnv* env, return gl_env ? ToJBool(gl_env->Deactivate()) : JNI_FALSE; } -jobject Java_android_filterfw_core_GLEnvironment_nativeActiveEnvironment(JNIEnv* env, - jclass clazz) { - GLEnv* active = GLEnv::ActiveEnv(); - return active ? WrapNewObjectInJava(active, env, false) : NULL; -} - jboolean Java_android_filterfw_core_GLEnvironment_nativeSwapBuffers(JNIEnv* env, jobject thiz) { GLEnv* gl_env = ConvertFromJava(env, thiz); return gl_env ? ToJBool(gl_env->SwapBuffers()) : JNI_FALSE; diff --git a/mca/filterfw/jni/jni_gl_environment.h b/mca/filterfw/jni/jni_gl_environment.h index 33691a11..9c46c6a6 100644 --- a/mca/filterfw/jni/jni_gl_environment.h +++ b/mca/filterfw/jni/jni_gl_environment.h @@ -44,9 +44,6 @@ Java_android_filterfw_core_GLEnvironment_nativeActivate(JNIEnv* env, jobject thi JNIEXPORT jboolean JNICALL Java_android_filterfw_core_GLEnvironment_nativeDeactivate(JNIEnv* env, jobject thiz); -JNIEXPORT jobject JNICALL -Java_android_filterfw_core_GLEnvironment_nativeActiveEnvironment(JNIEnv* env, jclass clazz); - JNIEXPORT jboolean JNICALL Java_android_filterfw_core_GLEnvironment_nativeSwapBuffers(JNIEnv* env, jobject thiz); diff --git a/mca/filterfw/jni/jni_gl_frame.cpp b/mca/filterfw/jni/jni_gl_frame.cpp index 5e45391a..8e3139e5 100644 --- a/mca/filterfw/jni/jni_gl_frame.cpp +++ b/mca/filterfw/jni/jni_gl_frame.cpp @@ -19,9 +19,11 @@ #include "jni/jni_gl_frame.h" #include "jni/jni_util.h" +#include "native/core/gl_env.h" #include "native/core/gl_frame.h" #include "native/core/native_frame.h" +using android::filterfw::GLEnv; using android::filterfw::GLFrame; using android::filterfw::NativeFrame; @@ -41,9 +43,12 @@ void ConvertRGBAToFloats(const uint8_t* rgba, int length, float* result) { // GLFrame JNI implementation ////////////////////////////////////////////////////////////////////// jboolean Java_android_filterfw_core_GLFrame_allocate(JNIEnv* env, jobject thiz, + jobject gl_env, jint width, jint height) { - GLFrame* frame = new GLFrame(); + GLEnv* gl_env_ptr = ConvertFromJava(env, gl_env); + if (!gl_env_ptr) return JNI_FALSE; + GLFrame* frame = new GLFrame(gl_env_ptr); if (frame->Init(width, height)) { return ToJBool(WrapObjectInJava(frame, env, thiz, true)); } else { @@ -54,12 +59,15 @@ jboolean Java_android_filterfw_core_GLFrame_allocate(JNIEnv* env, jboolean Java_android_filterfw_core_GLFrame_allocateWithTexture(JNIEnv* env, jobject thiz, + jobject gl_env, jint tex_id, jint width, jint height, jboolean owns, jboolean create) { - GLFrame* frame = new GLFrame(); + GLEnv* gl_env_ptr = ConvertFromJava(env, gl_env); + if (!gl_env_ptr) return JNI_FALSE; + GLFrame* frame = new GLFrame(gl_env_ptr); if (frame->InitWithTexture(tex_id, width, height, ToCppBool(owns), ToCppBool(create))) { return ToJBool(WrapObjectInJava(frame, env, thiz, true)); } else { @@ -70,12 +78,15 @@ jboolean Java_android_filterfw_core_GLFrame_allocateWithTexture(JNIEnv* env, jboolean Java_android_filterfw_core_GLFrame_allocateWithFbo(JNIEnv* env, jobject thiz, + jobject gl_env, jint fbo_id, jint width, jint height, jboolean owns, jboolean create) { - GLFrame* frame = new GLFrame(); + GLEnv* gl_env_ptr = ConvertFromJava(env, gl_env); + if (!gl_env_ptr) return JNI_FALSE; + GLFrame* frame = new GLFrame(gl_env_ptr); if (frame->InitWithFbo(fbo_id, width, height, ToCppBool(owns), ToCppBool(create))) { return ToJBool(WrapObjectInJava(frame, env, thiz, true)); } else { @@ -84,8 +95,12 @@ jboolean Java_android_filterfw_core_GLFrame_allocateWithFbo(JNIEnv* env, } } -jboolean Java_android_filterfw_core_GLFrame_allocateExternal(JNIEnv* env, jobject thiz) { - GLFrame* frame = new GLFrame(); +jboolean Java_android_filterfw_core_GLFrame_allocateExternal(JNIEnv* env, + jobject thiz, + jobject gl_env) { + GLEnv* gl_env_ptr = ConvertFromJava(env, gl_env); + if (!gl_env_ptr) return JNI_FALSE; + GLFrame* frame = new GLFrame(gl_env_ptr); if (frame->InitWithExternalTexture()) { return ToJBool(WrapObjectInJava(frame, env, thiz, true)); } else { diff --git a/mca/filterfw/jni/jni_gl_frame.h b/mca/filterfw/jni/jni_gl_frame.h index 7c95f857..29d307fe 100644 --- a/mca/filterfw/jni/jni_gl_frame.h +++ b/mca/filterfw/jni/jni_gl_frame.h @@ -24,11 +24,16 @@ extern "C" { #endif JNIEXPORT jboolean JNICALL -Java_android_filterfw_core_GLFrame_allocate(JNIEnv* env, jobject thiz, jint width, jint height); +Java_android_filterfw_core_GLFrame_allocate(JNIEnv* env, + jobject thiz, + jobject gl_env, + jint width, + jint height); JNIEXPORT jboolean JNICALL Java_android_filterfw_core_GLFrame_allocateWithTexture(JNIEnv* env, jobject thiz, + jobject gl_env, jint tex_id, jint width, jint height, @@ -38,6 +43,7 @@ Java_android_filterfw_core_GLFrame_allocateWithTexture(JNIEnv* env, JNIEXPORT jboolean JNICALL Java_android_filterfw_core_GLFrame_allocateWithFbo(JNIEnv* env, jobject thiz, + jobject gl_env, jint fbo_id, jint width, jint height, @@ -45,7 +51,7 @@ Java_android_filterfw_core_GLFrame_allocateWithFbo(JNIEnv* env, jboolean create); JNIEXPORT jboolean JNICALL -Java_android_filterfw_core_GLFrame_allocateExternal(JNIEnv* env, jobject thiz); +Java_android_filterfw_core_GLFrame_allocateExternal(JNIEnv* env, jobject thiz, jobject gl_env); JNIEXPORT jboolean JNICALL Java_android_filterfw_core_GLFrame_deallocate(JNIEnv* env, jobject thiz); diff --git a/mca/filterfw/jni/jni_shader_program.cpp b/mca/filterfw/jni/jni_shader_program.cpp index 978abbae..89f6e2be 100644 --- a/mca/filterfw/jni/jni_shader_program.cpp +++ b/mca/filterfw/jni/jni_shader_program.cpp @@ -22,10 +22,12 @@ #include "native/base/logging.h" #include "native/core/geometry.h" +#include "native/core/gl_env.h" #include "native/core/gl_frame.h" #include "native/core/shader_program.h" #include "native/core/vertex_frame.h" +using android::filterfw::GLEnv; using android::filterfw::GLFrame; using android::filterfw::Point; using android::filterfw::ProgramVar; @@ -35,21 +37,30 @@ using android::filterfw::VertexFrame; jboolean Java_android_filterfw_core_ShaderProgram_allocate(JNIEnv* env, jobject thiz, + jobject gl_env, jstring vertex_shader, jstring fragment_shader) { - if (!fragment_shader) + // Get the GLEnv pointer + GLEnv* gl_env_ptr = ConvertFromJava(env, gl_env); + + // Create the shader + if (!fragment_shader || !gl_env_ptr) return false; else if (!vertex_shader) - return ToJBool(WrapObjectInJava(new ShaderProgram(ToCppString(env, fragment_shader)), - env, - thiz, - true)); + return ToJBool(WrapObjectInJava(new ShaderProgram( + gl_env_ptr, + ToCppString(env, fragment_shader)), + env, + thiz, + true)); else - return ToJBool(WrapObjectInJava(new ShaderProgram(ToCppString(env, vertex_shader), - ToCppString(env, fragment_shader)), - env, - thiz, - true)); + return ToJBool(WrapObjectInJava(new ShaderProgram( + gl_env_ptr, + ToCppString(env, vertex_shader), + ToCppString(env, fragment_shader)), + env, + thiz, + true)); } jboolean Java_android_filterfw_core_ShaderProgram_deallocate(JNIEnv* env, jobject thiz) { @@ -121,9 +132,12 @@ jboolean Java_android_filterfw_core_ShaderProgram_shaderProcess(JNIEnv* env, return JNI_FALSE; } -jobject Java_android_filterfw_core_ShaderProgram_nativeCreateIdentity(JNIEnv* env, jclass) { - ShaderProgram* program = ShaderProgram::CreateIdentity(); - return program ? WrapNewObjectInJava(program, env, true) : NULL; +jobject Java_android_filterfw_core_ShaderProgram_nativeCreateIdentity(JNIEnv* env, + jclass, + jobject gl_env) { + GLEnv* gl_env_ptr = ConvertFromJava(env, gl_env); + ShaderProgram* program = gl_env_ptr ? ShaderProgram::CreateIdentity(gl_env_ptr) : NULL; + return program ? WrapNewObjectInJava(program, env, false) : NULL; } jboolean Java_android_filterfw_core_ShaderProgram_setShaderSourceRegion(JNIEnv* env, diff --git a/mca/filterfw/jni/jni_shader_program.h b/mca/filterfw/jni/jni_shader_program.h index debf4e0e..af1c02d7 100644 --- a/mca/filterfw/jni/jni_shader_program.h +++ b/mca/filterfw/jni/jni_shader_program.h @@ -28,6 +28,7 @@ extern "C" { JNIEXPORT jboolean JNICALL Java_android_filterfw_core_ShaderProgram_allocate(JNIEnv* env, jobject thiz, + jobject gl_env, jstring vertex_shader, jstring fragment_shader); @@ -55,7 +56,9 @@ Java_android_filterfw_core_ShaderProgram_shaderProcess(JNIEnv* env, jobject output); JNIEXPORT jobject JNICALL -Java_android_filterfw_core_ShaderProgram_nativeCreateIdentity(JNIEnv* env, jclass clazz); +Java_android_filterfw_core_ShaderProgram_nativeCreateIdentity(JNIEnv* env, + jclass clazz, + jobject gl_env); JNIEXPORT jboolean JNICALL Java_android_filterfw_core_ShaderProgram_setShaderSourceRegion(JNIEnv* env, diff --git a/mca/filterfw/native/core/gl_env.cpp b/mca/filterfw/native/core/gl_env.cpp index a78f7935..63e33977 100644 --- a/mca/filterfw/native/core/gl_env.cpp +++ b/mca/filterfw/native/core/gl_env.cpp @@ -15,7 +15,10 @@ */ #include "base/logging.h" +#include "base/utilities.h" #include "core/gl_env.h" +#include "core/shader_program.h" +#include "core/vertex_frame.h" #include "system/window.h" #include @@ -24,7 +27,6 @@ namespace android { namespace filterfw { -GLEnv* GLEnv::active_env_ = NULL; int GLEnv::max_id_ = 0; GLEnv::GLEnv() @@ -39,10 +41,6 @@ GLEnv::GLEnv() } GLEnv::~GLEnv() { - // We are no longer active if torn down - if (active_env_ == this) - active_env_ = NULL; - // Destroy surfaces for (std::map::iterator it = surfaces_.begin(); it != surfaces_.end(); @@ -64,6 +62,10 @@ GLEnv::~GLEnv() { eglDestroyContext(display(), it->second); } + // Destroy attached shaders and frames + STLDeleteValues(&attached_shaders_); + STLDeleteValues(&attached_vframes_); + // Destroy display if (initialized_) eglTerminate(display()); @@ -80,14 +82,12 @@ bool GLEnv::IsInitialized() const { } bool GLEnv::Deactivate() { - active_env_ = NULL; eglMakeCurrent(display(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); return !CheckEGLError("eglMakeCurrent"); } bool GLEnv::Activate() { - if (active_env_ != this || - display() != eglGetCurrentDisplay() || + if (display() != eglGetCurrentDisplay() || context() != eglGetCurrentContext() || surface() != eglGetCurrentSurface(EGL_DRAW)) { // Make sure we are initialized @@ -97,15 +97,7 @@ bool GLEnv::Activate() { // Make our context current eglMakeCurrent(display(), surface(), surface(), context()); - // We are no longer active now - active_env_ = NULL; - - // Set active env to new environment if there was no error - if (!CheckEGLError("eglMakeCurrent")) { - active_env_ = this; - return true; - } - return false; + return !CheckEGLMakeCurrentError(); } return true; } @@ -123,13 +115,9 @@ bool GLEnv::InitWithCurrentContext() { contexts_[0] = eglGetCurrentContext(); surfaces_[0] = SurfaceWindowPair(eglGetCurrentSurface(EGL_DRAW), NULL); - if ((context() != EGL_NO_CONTEXT) && - (display() != EGL_NO_DISPLAY) && - (surface() != EGL_NO_SURFACE)) { - active_env_ = this; - return true; - } - return false; + return (context() != EGL_NO_CONTEXT) && + (display() != EGL_NO_DISPLAY) && + (surface() != EGL_NO_SURFACE); } bool GLEnv::InitWithNewContext() { @@ -215,7 +203,7 @@ bool GLEnv::ReleaseSurfaceId(int surface_id) { const SurfaceWindowPair* surface = FindOrNull(surfaces_, surface_id); if (surface) { surfaces_.erase(surface_id); - if (surface_id_ == surface_id && ActiveEnv() == this) + if (surface_id_ == surface_id && IsActive()) SwitchToSurfaceId(0); eglDestroySurface(display(), surface->first); if (surface->second) { @@ -277,7 +265,7 @@ void GLEnv::ReleaseContextId(int context_id) { const EGLContext* context = FindOrNull(contexts_, context_id); if (context) { contexts_.erase(context_id); - if (context_id_ == context_id && ActiveEnv() == this) + if (context_id_ == context_id && IsActive()) SwitchToContextId(0); eglDestroyContext(display(), *context); } @@ -308,6 +296,31 @@ bool GLEnv::CheckEGLError(const std::string& op) { return err; } +bool GLEnv::CheckEGLMakeCurrentError() { + bool err = false; + for (EGLint error = eglGetError(); + error != EGL_SUCCESS; + error = eglGetError()) { + switch (error) { + case EGL_BAD_DISPLAY: + LOGE("EGL Error: Attempting to activate context with bad display!"); + break; + case EGL_BAD_SURFACE: + LOGE("EGL Error: Attempting to activate context with bad surface!"); + break; + case EGL_BAD_ACCESS: + LOGE("EGL Error: Attempting to activate context, which is " + "already active in another thread!"); + break; + default: + LOGE("EGL Error: Making EGL rendering context current caused " + "error: 0x%x\n", error); + } + err = true; + } + return err; +} + GLuint GLEnv::GetCurrentProgram() { GLint result; glGetIntegerv(GL_CURRENT_PROGRAM, &result); @@ -347,5 +360,27 @@ int GLEnv::NumberOfComponents(GLenum type) { } } +void GLEnv::AttachShader(int key, ShaderProgram* shader) { + ShaderProgram* existingShader = ShaderWithKey(key); + if (existingShader) + delete existingShader; + attached_shaders_[key] = shader; +} + +void GLEnv::AttachVertexFrame(int key, VertexFrame* frame) { + VertexFrame* existingFrame = VertexFrameWithKey(key); + if (existingFrame) + delete existingFrame; + attached_vframes_[key] = frame; +} + +ShaderProgram* GLEnv::ShaderWithKey(int key) { + return FindPtrOrNull(attached_shaders_, key); +} + +VertexFrame* GLEnv::VertexFrameWithKey(int key) { + return FindPtrOrNull(attached_vframes_, key); +} + } // namespace filterfw } // namespace android diff --git a/mca/filterfw/native/core/gl_env.h b/mca/filterfw/native/core/gl_env.h index 5784238d..13d40483 100644 --- a/mca/filterfw/native/core/gl_env.h +++ b/mca/filterfw/native/core/gl_env.h @@ -26,10 +26,14 @@ #include #include +#include namespace android { namespace filterfw { +class ShaderProgram; +class VertexFrame; + class WindowHandle { public: virtual ~WindowHandle() { @@ -62,12 +66,6 @@ class GLEnv { // by this instance. ~GLEnv(); - // Returns the currently active GL environment, which was activated using - // Activate(). - static GLEnv* ActiveEnv() { - return active_env_; - } - // Returns a globally unique id of this environment. int id() const { return id_; @@ -164,9 +162,27 @@ class GLEnv { } // Inspecting the environment ////////////////////////////////////////////// - // Returns true if the environment is the active (current) environment. + // Returns true if the environment is active in the current thread. bool IsActive() const; + // Attaching GL objects //////////////////////////////////////////////////// + + // Attach a shader to the environment. The environment takes ownership of + // the shader. + void AttachShader(int key, ShaderProgram* shader); + + // Attach a vertex frame to the environment. The environment takes ownership + // of the frame. + void AttachVertexFrame(int key, VertexFrame* frame); + + // Return the shader with the specified key, or NULL if there is no such + // shader attached to this environment. + ShaderProgram* ShaderWithKey(int key); + + // Return the vertex frame with the specified key, or NULL if there is no + // such frame attached to this environment. + VertexFrame* VertexFrameWithKey(int key); + // Static methods ////////////////////////////////////////////////////////// // These operate on the currently active environment! @@ -200,8 +216,9 @@ class GLEnv { // instance. bool IsInitialized() const; - // (Weak) pointer to active environment. Managed by the GLEnv instances. - static GLEnv* active_env_; + // Outputs error messages specific to the operation eglMakeCurrent(). + // Returns true if there was at least one error. + static bool CheckEGLMakeCurrentError(); // The maximum id assigned to a GLEnv instance. static int max_id_; @@ -224,54 +241,13 @@ class GLEnv { bool created_surface_; bool initialized_; - DISALLOW_COPY_AND_ASSIGN(GLEnv); -}; - -// Helper class for variables that are GL related, and thus bound to the active -// environment. When setting a value, it will be bound to the currently active -// GL environment. Getting a value will result in whatever value was set in -// the current environment, or NULL if no value was set in that environment. -// Note: We rely on the unique ID of the environment to determine the -// association with any one particular GL environment. There may be a conflict -// of IDs when the current process relaunches (and the static max_id_ resets), -// however, in this case all dependant variables have been deallocated anyway -// and will be reinitialized. -template -class GLBoundVariable { - public: - // Set the value of this variable in the context of the currently active - // GL environment. - void SetValue(T* value); + // Attachments that GL objects can add to the environment. + std::map attached_shaders_; + std::map attached_vframes_; - // Get the value of this variable in the context of the currently active - // GL environment. Returns NULL if the variable was not set in this - // environment. - T* Value(); - - private: - typedef std::map GLVarMap; - GLVarMap variables_; + DISALLOW_COPY_AND_ASSIGN(GLEnv); }; -// GLBoundVariable implementation ////////////////////////////////////////////// -template -void GLBoundVariable::SetValue(T* value) { - if (GLEnv::ActiveEnv()) - variables_[GLEnv::ActiveEnv()->id()] = value; - else - LOGE("Attempting to set GL bound variable without an active context!"); -} - -template -T* GLBoundVariable::Value() { - if (GLEnv::ActiveEnv()) { - return FindPtrOrNull(variables_, GLEnv::ActiveEnv()->id()); - } else { - LOGE("Attempting to get GL bound variable without an active context!"); - return NULL; - } -} - } // namespace filterfw } // namespace android diff --git a/mca/filterfw/native/core/gl_frame.cpp b/mca/filterfw/native/core/gl_frame.cpp index 66e1640e..e3e7b82d 100644 --- a/mca/filterfw/native/core/gl_frame.cpp +++ b/mca/filterfw/native/core/gl_frame.cpp @@ -25,6 +25,8 @@ namespace android { namespace filterfw { +static const int kIdentityShaderKey = 1; + // // A GLFrame stores pixel data on the GPU. It uses two kinds of GL data // containers for this: Textures and Frame Buffer Objects (FBOs). Textures are @@ -33,8 +35,9 @@ namespace filterfw { // target for shaders. // -GLFrame::GLFrame() - : width_(0), +GLFrame::GLFrame(GLEnv* gl_env) + : gl_env_(gl_env), + width_(0), height_(0), vp_x_(0), vp_y_(0), @@ -45,8 +48,7 @@ GLFrame::GLFrame() texture_target_(GL_TEXTURE_2D), texture_state_(kStateUninitialized), fbo_state_(kStateUninitialized), - owns_(false), - identity_cache_(NULL) { + owns_(false) { } bool GLFrame::Init(int width, int height) { @@ -96,7 +98,6 @@ GLFrame::~GLFrame() { glDeleteTextures(1, &texture_id_); glDeleteFramebuffers(1, &fbo_id_); } - delete identity_cache_; } bool GLFrame::GenerateMipMap() { @@ -146,7 +147,7 @@ bool GLFrame::SetViewport(int x, int y, int width, int height) { } GLFrame* GLFrame::Clone() const { - GLFrame* target = new GLFrame(); + GLFrame* target = new GLFrame(gl_env_); target->Init(width_, height_); target->CopyPixelsFrom(this); return target; @@ -169,9 +170,12 @@ int GLFrame::Size() const { } ShaderProgram* GLFrame::GetIdentity() const { - if (!identity_cache_) - identity_cache_ = ShaderProgram::CreateIdentity(); - return identity_cache_; + ShaderProgram* stored_shader = gl_env_->ShaderWithKey(kIdentityShaderKey); + if (!stored_shader) { + stored_shader = ShaderProgram::CreateIdentity(gl_env_); + gl_env_->AttachShader(kIdentityShaderKey, stored_shader); + } + return stored_shader; } bool GLFrame::BindFrameBuffer() const { @@ -300,7 +304,7 @@ bool GLFrame::ReadTexturePixels(uint8_t* pixels) const { sources.push_back(this); // Create target frame - GLFrame target; + GLFrame target(gl_env_); target.Init(width_, height_); // Render the texture to the target diff --git a/mca/filterfw/native/core/gl_frame.h b/mca/filterfw/native/core/gl_frame.h index 0807dfe7..fd1831fd 100644 --- a/mca/filterfw/native/core/gl_frame.h +++ b/mca/filterfw/native/core/gl_frame.h @@ -24,6 +24,7 @@ namespace android { namespace filterfw { +class GLEnv; class ShaderProgram; // A GLFrame stores pixel data on the GPU. While pixel data may be uploaded to @@ -32,8 +33,10 @@ class ShaderProgram; // processing from one GLFrame to another. class GLFrame : public GLBufferHandle { public: - // Create an empty GL frame. - GLFrame(); + // Create an empty GL frame in the specified GL environment. Note, that the GLFrame does NOT + // take ownership. The caller must make sure the GLEnv stays valid as long as the GLFrame is + // alive. + GLFrame(GLEnv* gl_env); // Deallocate a GL frame. ~GLFrame(); @@ -145,6 +148,9 @@ class GLFrame : public GLBufferHandle { // Get the (cached) identity shader. ShaderProgram* GetIdentity() const; + // The GL environment this frame belongs to + GLEnv* gl_env_; + // The width, height and format of the frame int width_; int height_; @@ -168,9 +174,6 @@ class GLFrame : public GLBufferHandle { // Flag whether frame owns the texture and FBO bool owns_; - - // The identity shader (cache). - mutable ShaderProgram* identity_cache_; }; } // namespace filterfw diff --git a/mca/filterfw/native/core/shader_program.cpp b/mca/filterfw/native/core/shader_program.cpp index 85c5d3c0..41225f1d 100644 --- a/mca/filterfw/native/core/shader_program.cpp +++ b/mca/filterfw/native/core/shader_program.cpp @@ -30,8 +30,8 @@ namespace android { namespace filterfw { -// Statics ///////////////////////////////////////////////////////////////////// -GLBoundVariable ShaderProgram::s_default_vbo_; +// VBO attachment keys +static const int kDefaultVboKey = 1; // The default vertices for our shader program. This assumes the draw primitive // GL_TRIANGLE_STRIP. @@ -67,12 +67,13 @@ ShaderProgram::VertexAttrib::VertexAttrib() } // ShaderProgram implementation //////////////////////////////////////////////// -ShaderProgram::ShaderProgram(const std::string& fragment_shader) +ShaderProgram::ShaderProgram(GLEnv* gl_env, const std::string& fragment_shader) : fragment_shader_source_(fragment_shader), vertex_shader_source_(s_default_vertex_shader_source_), fragment_shader_(0), vertex_shader_(0), program_(0), + gl_env_(gl_env), base_texture_unit_(GL_TEXTURE0), vertex_data_(NULL), vertex_count_(4), @@ -83,13 +84,15 @@ ShaderProgram::ShaderProgram(const std::string& fragment_shader) dfactor_(GL_ONE_MINUS_SRC_ALPHA) { } -ShaderProgram::ShaderProgram(const std::string& vertex_shader, +ShaderProgram::ShaderProgram(GLEnv* gl_env, + const std::string& vertex_shader, const std::string& fragment_shader) : fragment_shader_source_(fragment_shader), vertex_shader_source_(vertex_shader), fragment_shader_(0), vertex_shader_(0), program_(0), + gl_env_(gl_env), base_texture_unit_(GL_TEXTURE0), vertex_data_(NULL), vertex_count_(4), @@ -113,16 +116,15 @@ ShaderProgram::~ShaderProgram() { } } -ShaderProgram* ShaderProgram::CreateIdentity() { - static const char* s_id_fragment_shader = +ShaderProgram* ShaderProgram::CreateIdentity(GLEnv* gl_env) { + const char* s_id_fragment_shader = "precision mediump float;\n" "uniform sampler2D tex_sampler_0;\n" "varying vec2 v_texcoord;\n" "void main() {\n" " gl_FragColor = texture2D(tex_sampler_0, v_texcoord);\n" "}\n"; - - ShaderProgram* result = new ShaderProgram(s_id_fragment_shader); + ShaderProgram* result = new ShaderProgram(gl_env, s_id_fragment_shader); result->CompileAndLink(); return result; } @@ -350,16 +352,17 @@ GLuint ShaderProgram::LinkProgram(GLuint* shaders, GLuint count) { } VertexFrame* ShaderProgram::DefaultVertexBuffer() { - LOGI("In ShaderProgram::DefaultVertexBuffer()!"); - if (!s_default_vbo_.Value()) { + VertexFrame* storedFrame = gl_env_->VertexFrameWithKey(kDefaultVboKey); + if (!storedFrame) { LOGI("Uploading Data to VBO!"); - s_default_vbo_.SetValue(new VertexFrame(sizeof(s_default_vertices_))); - s_default_vbo_.Value()->WriteData( + storedFrame = new VertexFrame(sizeof(s_default_vertices_)); + storedFrame->WriteData( reinterpret_cast(s_default_vertices_), sizeof(s_default_vertices_) ); + gl_env_->AttachVertexFrame(kDefaultVboKey, storedFrame); } - return s_default_vbo_.Value(); + return storedFrame; } bool ShaderProgram::BindVertexValues(const std::string& varname, diff --git a/mca/filterfw/native/core/shader_program.h b/mca/filterfw/native/core/shader_program.h index f10e8a8f..758d22fa 100644 --- a/mca/filterfw/native/core/shader_program.h +++ b/mca/filterfw/native/core/shader_program.h @@ -31,8 +31,9 @@ namespace android { namespace filterfw { -class GLTextureHandle; +class GLFrame; class GLFrameBufferHandle; +class GLTextureHandle; class Quad; class VertexFrame; @@ -73,12 +74,20 @@ class ShaderProgram { // (and related) functions below. // This program will not be executable until you have compiled and linked // it. - explicit ShaderProgram(const std::string& fragment_shader); + // Note, that the ShaderProgram does NOT take ownership of the GLEnv. The + // caller must make sure the GLEnv stays valid as long as the GLFrame is + // alive. + explicit ShaderProgram(GLEnv* gl_env, const std::string& fragment_shader); // Create a new shader program with the given fragment and vertex shader // source code. This program will not be executable until you have compiled // and linked it. - ShaderProgram(const std::string& vertex_shader, const std::string& fragment_shader); + // Note, that the ShaderProgram does NOT take ownership of the GLEnv. The + // caller must make sure the GLEnv stays valid as long as the GLFrame is + // alive. + ShaderProgram(GLEnv* gl_env, + const std::string& vertex_shader, + const std::string& fragment_shader); // Destructor. ~ShaderProgram(); @@ -111,7 +120,7 @@ class ShaderProgram { // input to the output. Note that transformations may be applied to achieve // effects such as cropping, scaling or rotation. // The caller takes ownership of the result! - static ShaderProgram* CreateIdentity(); + static ShaderProgram* CreateIdentity(GLEnv* env); // Geometry //////////////////////////////////////////////////////////////// // These functions modify the source and target regions used during @@ -420,7 +429,7 @@ class ShaderProgram { }; // Gets or creates the default vertex data. - static VertexFrame* DefaultVertexBuffer(); + VertexFrame* DefaultVertexBuffer(); // Binds the given input textures. bool BindInputTextures(const std::vector& textures, @@ -469,6 +478,9 @@ class ShaderProgram { GLuint vertex_shader_; GLuint program_; + // The GL environment this shader lives in. + GLEnv* gl_env_; + // The lowest texture unit this program will use GLuint base_texture_unit_; @@ -496,12 +508,6 @@ class ShaderProgram { bool blending_; int sfactor_; int dfactor_; - - // The default vertex data used by ShaderPrograms - static GLBoundVariable s_default_vbo_; - - // Built-in shaders - static GLBoundVariable s_identity_; }; } // namespace filterfw diff --git a/mca/filterpacks/imageproc/java/AlphaBlendFilter.java b/mca/filterpacks/imageproc/java/AlphaBlendFilter.java index 3783c692..473369cd 100644 --- a/mca/filterpacks/imageproc/java/AlphaBlendFilter.java +++ b/mca/filterpacks/imageproc/java/AlphaBlendFilter.java @@ -54,13 +54,13 @@ public class AlphaBlendFilter extends ImageCombineFilter { } @Override - protected Program getNativeProgram() { + protected Program getNativeProgram(FilterContext context) { throw new RuntimeException("TODO: Write native implementation for AlphaBlend!"); } @Override - protected Program getShaderProgram() { - return new ShaderProgram(mAlphaBlendShader); + protected Program getShaderProgram(FilterContext context) { + return new ShaderProgram(context, mAlphaBlendShader); } } diff --git a/mca/filterpacks/imageproc/java/BlendFilter.java b/mca/filterpacks/imageproc/java/BlendFilter.java index ea07f61b..d1090027 100644 --- a/mca/filterpacks/imageproc/java/BlendFilter.java +++ b/mca/filterpacks/imageproc/java/BlendFilter.java @@ -52,13 +52,13 @@ public class BlendFilter extends ImageCombineFilter { } @Override - protected Program getNativeProgram() { + protected Program getNativeProgram(FilterContext context) { throw new RuntimeException("TODO: Write native implementation for AlphaBlend!"); } @Override - protected Program getShaderProgram() { - return new ShaderProgram(mBlendShader); + protected Program getShaderProgram(FilterContext context) { + return new ShaderProgram(context, mBlendShader); } } diff --git a/mca/filterpacks/imageproc/java/BrightnessFilter.java b/mca/filterpacks/imageproc/java/BrightnessFilter.java index 0e020271..046e69d4 100644 --- a/mca/filterpacks/imageproc/java/BrightnessFilter.java +++ b/mca/filterpacks/imageproc/java/BrightnessFilter.java @@ -47,13 +47,13 @@ public class BrightnessFilter extends SimpleImageFilter { } @Override - protected Program getNativeProgram() { + protected Program getNativeProgram(FilterContext context) { return new NativeProgram("filterpack_imageproc", "brightness"); } @Override - protected Program getShaderProgram() { - return new ShaderProgram(mBrightnessShader); + protected Program getShaderProgram(FilterContext context) { + return new ShaderProgram(context, mBrightnessShader); } } diff --git a/mca/filterpacks/imageproc/java/ContrastFilter.java b/mca/filterpacks/imageproc/java/ContrastFilter.java index 612df675..70e987f9 100644 --- a/mca/filterpacks/imageproc/java/ContrastFilter.java +++ b/mca/filterpacks/imageproc/java/ContrastFilter.java @@ -52,13 +52,13 @@ public class ContrastFilter extends SimpleImageFilter { } @Override - protected Program getNativeProgram() { + protected Program getNativeProgram(FilterContext context) { return new NativeProgram("filterpack_imageproc", "contrast"); } @Override - protected Program getShaderProgram() { - return new ShaderProgram(mContrastShader); + protected Program getShaderProgram(FilterContext context) { + return new ShaderProgram(context, mContrastShader); } } diff --git a/mca/filterpacks/imageproc/java/CropFilter.java b/mca/filterpacks/imageproc/java/CropFilter.java index 5b32a19b..506fd90c 100644 --- a/mca/filterpacks/imageproc/java/CropFilter.java +++ b/mca/filterpacks/imageproc/java/CropFilter.java @@ -69,11 +69,11 @@ public class CropFilter extends Filter { } @Override - public void prepare(FilterContext env) { + public void prepare(FilterContext context) { // TODO: Add CPU version switch (getInputFormat("image").getTarget()) { case FrameFormat.TARGET_GPU: - mProgram = ShaderProgram.createIdentity(); + mProgram = ShaderProgram.createIdentity(context); break; } if (mProgram == null) { diff --git a/mca/filterpacks/imageproc/java/DrawOverlayFilter.java b/mca/filterpacks/imageproc/java/DrawOverlayFilter.java index ddf5ca6a..e947cf3d 100644 --- a/mca/filterpacks/imageproc/java/DrawOverlayFilter.java +++ b/mca/filterpacks/imageproc/java/DrawOverlayFilter.java @@ -59,8 +59,8 @@ public class DrawOverlayFilter extends Filter { } @Override - public void prepare(FilterContext env) { - mProgram = ShaderProgram.createIdentity(); + public void prepare(FilterContext context) { + mProgram = ShaderProgram.createIdentity(context); } @Override diff --git a/mca/filterpacks/imageproc/java/DrawRectFilter.java b/mca/filterpacks/imageproc/java/DrawRectFilter.java index 0084b413..3d00310c 100644 --- a/mca/filterpacks/imageproc/java/DrawRectFilter.java +++ b/mca/filterpacks/imageproc/java/DrawRectFilter.java @@ -81,8 +81,8 @@ public class DrawRectFilter extends Filter { } @Override - public void prepare(FilterContext env) { - mProgram = new ShaderProgram(mVertexShader, mFixedColorFragmentShader); + public void prepare(FilterContext context) { + mProgram = new ShaderProgram(context, mVertexShader, mFixedColorFragmentShader); } @Override diff --git a/mca/filterpacks/imageproc/java/FisheyeFilter.java b/mca/filterpacks/imageproc/java/FisheyeFilter.java index b2ddf577..9128c838 100644 --- a/mca/filterpacks/imageproc/java/FisheyeFilter.java +++ b/mca/filterpacks/imageproc/java/FisheyeFilter.java @@ -90,10 +90,10 @@ public class FisheyeFilter extends Filter { return inputFormat; } - public void initProgram(int target) { + public void initProgram(FilterContext context, int target) { switch (target) { case FrameFormat.TARGET_GPU: - mProgram = new ShaderProgram(mFisheyeShader); + mProgram = new ShaderProgram(context, mFisheyeShader); break; default: @@ -114,7 +114,7 @@ public class FisheyeFilter extends Filter { // Create program if not created already if (mProgram == null || inputFormat.getTarget() != mTarget) { - initProgram(inputFormat.getTarget()); + initProgram(context, inputFormat.getTarget()); } // Check if the frame size has changed diff --git a/mca/filterpacks/imageproc/java/ImageCombineFilter.java b/mca/filterpacks/imageproc/java/ImageCombineFilter.java index ba7ccb27..e4b289e9 100644 --- a/mca/filterpacks/imageproc/java/ImageCombineFilter.java +++ b/mca/filterpacks/imageproc/java/ImageCombineFilter.java @@ -113,11 +113,11 @@ public abstract class ImageCombineFilter extends Filter { if (target != mCurrentTarget) { switch (target) { case FrameFormat.TARGET_NATIVE: - mProgram = getNativeProgram(); + mProgram = getNativeProgram(context); break; case FrameFormat.TARGET_GPU: - mProgram = getShaderProgram(); + mProgram = getShaderProgram(context); break; default: @@ -135,7 +135,7 @@ public abstract class ImageCombineFilter extends Filter { } } - protected abstract Program getNativeProgram(); + protected abstract Program getNativeProgram(FilterContext context); - protected abstract Program getShaderProgram(); + protected abstract Program getShaderProgram(FilterContext context); } diff --git a/mca/filterpacks/imageproc/java/Invert.java b/mca/filterpacks/imageproc/java/Invert.java index f576aa29..400fd5da 100644 --- a/mca/filterpacks/imageproc/java/Invert.java +++ b/mca/filterpacks/imageproc/java/Invert.java @@ -48,13 +48,13 @@ public class Invert extends SimpleImageFilter { } @Override - protected Program getNativeProgram() { + protected Program getNativeProgram(FilterContext context) { return new NativeProgram("filterpack_imageproc", "invert"); } @Override - protected Program getShaderProgram() { - return new ShaderProgram(mInvertShader); + protected Program getShaderProgram(FilterContext context) { + return new ShaderProgram(context, mInvertShader); } } diff --git a/mca/filterpacks/imageproc/java/ResizeFilter.java b/mca/filterpacks/imageproc/java/ResizeFilter.java index cb108058..e8f195ce 100644 --- a/mca/filterpacks/imageproc/java/ResizeFilter.java +++ b/mca/filterpacks/imageproc/java/ResizeFilter.java @@ -67,14 +67,14 @@ public class ResizeFilter extends Filter { } @Override - protected void prepare(FilterContext environment) { + protected void prepare(FilterContext context) { switch (getInputFormat("image").getTarget()) { case FrameFormat.TARGET_NATIVE: throw new RuntimeException("Native ResizeFilter not implemented yet!"); case FrameFormat.TARGET_GPU: - ShaderProgram prog = ShaderProgram.createIdentity(); + ShaderProgram prog = ShaderProgram.createIdentity(context); mProgram = prog; break; diff --git a/mca/filterpacks/imageproc/java/SimpleImageFilter.java b/mca/filterpacks/imageproc/java/SimpleImageFilter.java index 38105360..8df7334b 100644 --- a/mca/filterpacks/imageproc/java/SimpleImageFilter.java +++ b/mca/filterpacks/imageproc/java/SimpleImageFilter.java @@ -91,11 +91,11 @@ public abstract class SimpleImageFilter extends Filter { if (target != mCurrentTarget) { switch (target) { case FrameFormat.TARGET_NATIVE: - mProgram = getNativeProgram(); + mProgram = getNativeProgram(context); break; case FrameFormat.TARGET_GPU: - mProgram = getShaderProgram(); + mProgram = getShaderProgram(context); break; default: @@ -112,7 +112,7 @@ public abstract class SimpleImageFilter extends Filter { } } - protected abstract Program getNativeProgram(); + protected abstract Program getNativeProgram(FilterContext context); - protected abstract Program getShaderProgram(); + protected abstract Program getShaderProgram(FilterContext context); } diff --git a/mca/filterpacks/imageproc/java/ToGrayFilter.java b/mca/filterpacks/imageproc/java/ToGrayFilter.java index d6fb17ae..ac58db21 100644 --- a/mca/filterpacks/imageproc/java/ToGrayFilter.java +++ b/mca/filterpacks/imageproc/java/ToGrayFilter.java @@ -66,18 +66,18 @@ public class ToGrayFilter extends SimpleImageFilter { } @Override - protected Program getNativeProgram() { + protected Program getNativeProgram(FilterContext context) { throw new RuntimeException("Native toGray not implemented yet!"); } @Override - protected Program getShaderProgram() { + protected Program getShaderProgram(FilterContext context) { int inputChannels = getInputFormat("image").getBytesPerSample(); if (inputChannels != 4) { throw new RuntimeException("Unsupported GL input channels: " + inputChannels + "! Channels must be 4!"); } - ShaderProgram program = new ShaderProgram(mColorToGray4Shader); + ShaderProgram program = new ShaderProgram(context, mColorToGray4Shader); if (mInvertSource) program.setSourceRect(0.0f, 1.0f, 1.0f, -1.0f); return program; diff --git a/mca/filterpacks/imageproc/java/ToPackedGrayFilter.java b/mca/filterpacks/imageproc/java/ToPackedGrayFilter.java index e6b7314a..16b3e0b8 100644 --- a/mca/filterpacks/imageproc/java/ToPackedGrayFilter.java +++ b/mca/filterpacks/imageproc/java/ToPackedGrayFilter.java @@ -99,7 +99,7 @@ public class ToPackedGrayFilter extends Filter { @Override public void prepare(FilterContext context) { - mProgram = new ShaderProgram(mColorToPackedGrayShader); + mProgram = new ShaderProgram(context, mColorToPackedGrayShader); } @Override diff --git a/mca/filterpacks/ui/java/SurfaceRenderFilter.java b/mca/filterpacks/ui/java/SurfaceRenderFilter.java index b623ad92..3e512ee8 100644 --- a/mca/filterpacks/ui/java/SurfaceRenderFilter.java +++ b/mca/filterpacks/ui/java/SurfaceRenderFilter.java @@ -123,7 +123,7 @@ public class SurfaceRenderFilter extends Filter implements FilterSurfaceRenderer public void prepare(FilterContext context) { // Create identity shader to render, and make sure to render upside-down, as textures // are stored internally bottom-to-top. - mProgram = ShaderProgram.createIdentity(); + mProgram = ShaderProgram.createIdentity(context); mProgram.setSourceRect(0, 1, 1, -1); mProgram.setClearsOutput(true); mProgram.setClearColor(0.0f, 0.0f, 0.0f); diff --git a/mca/filterpacks/videosrc/java/CameraSource.java b/mca/filterpacks/videosrc/java/CameraSource.java index 1d050c52..d766c3bf 100644 --- a/mca/filterpacks/videosrc/java/CameraSource.java +++ b/mca/filterpacks/videosrc/java/CameraSource.java @@ -122,7 +122,7 @@ public class CameraSource extends Filter { public void prepare(FilterContext context) { if (mLogVerbose) Log.v(TAG, "Preparing"); // Compile shader TODO: Move to onGLEnvSomething? - mFrameExtractor = new ShaderProgram(mFrameShader); + mFrameExtractor = new ShaderProgram(context, mFrameShader); // SurfaceTexture defines (0,0) to be bottom-left. The filter framework defines // (0,0) as top-left, so do the flip here. mFrameExtractor.setSourceRect(0, 1, 1, -1); diff --git a/mca/filterpacks/videosrc/java/MediaSource.java b/mca/filterpacks/videosrc/java/MediaSource.java index 5a162fec..57de0f8a 100644 --- a/mca/filterpacks/videosrc/java/MediaSource.java +++ b/mca/filterpacks/videosrc/java/MediaSource.java @@ -125,7 +125,7 @@ public class MediaSource extends Filter { protected void prepare(FilterContext context) { if (mLogVerbose) Log.v(TAG, "Preparing MediaSource"); - mFrameExtractor = new ShaderProgram(mFrameShader); + mFrameExtractor = new ShaderProgram(context, mFrameShader); // SurfaceTexture defines (0,0) to be bottom-left. The filter framework // defines (0,0) as top-left, so do the flip here. mFrameExtractor.setSourceRect(0, 1, 1, -1); diff --git a/mca/filterpacks/videosrc/java/SurfaceTextureSource.java b/mca/filterpacks/videosrc/java/SurfaceTextureSource.java index 5ba5a597..60193195 100644 --- a/mca/filterpacks/videosrc/java/SurfaceTextureSource.java +++ b/mca/filterpacks/videosrc/java/SurfaceTextureSource.java @@ -161,7 +161,7 @@ public class SurfaceTextureSource extends Filter { 0); // Prepare output - mFrameExtractor = new ShaderProgram(mRenderShader); + mFrameExtractor = new ShaderProgram(context, mRenderShader); // SurfaceTexture defines (0,0) to be bottom-left. The filter framework // defines (0,0) as top-left, so do the flip here. mFrameExtractor.setSourceRect(0, 1, 1, -1); diff --git a/mca/filterpacks/videosrc/java/SurfaceTextureTarget.java b/mca/filterpacks/videosrc/java/SurfaceTextureTarget.java index 2096ccfe..ec02f545 100644 --- a/mca/filterpacks/videosrc/java/SurfaceTextureTarget.java +++ b/mca/filterpacks/videosrc/java/SurfaceTextureTarget.java @@ -127,7 +127,7 @@ public class SurfaceTextureTarget extends Filter { public void prepare(FilterContext context) { // Create identity shader to render, and make sure to render upside-down, as textures // are stored internally bottom-to-top. - mProgram = ShaderProgram.createIdentity(); + mProgram = ShaderProgram.createIdentity(context); mProgram.setSourceRect(0, 1, 1, -1); mProgram.setClearColor(0.0f, 0.0f, 0.0f);