OSDN Git Service

Fixes to GL related classes.
authorMarius Renn <renn@google.com>
Mon, 18 Jul 2011 18:26:18 +0000 (11:26 -0700)
committerMarius Renn <renn@google.com>
Mon, 18 Jul 2011 18:26:18 +0000 (11:26 -0700)
Patch: Java keeps reference to GLEnvironment to make sure it does not
get deallocated before all its objects are deallocated.

Change-Id: Ic3dffb84b2592cafc4df27331f63a44c221b19bd

43 files changed:
mca/filterfw/java/android/filterfw/MffEnvironment.java
mca/filterfw/java/android/filterfw/basefilters/RetargetFilter.java
mca/filterfw/java/android/filterfw/core/FilterContext.java
mca/filterfw/java/android/filterfw/core/FilterPort.java
mca/filterfw/java/android/filterfw/core/Frame.java
mca/filterfw/java/android/filterfw/core/FrameManager.java
mca/filterfw/java/android/filterfw/core/GLEnvironment.java
mca/filterfw/java/android/filterfw/core/GLFrame.java
mca/filterfw/java/android/filterfw/core/InputPort.java
mca/filterfw/java/android/filterfw/core/ShaderProgram.java
mca/filterfw/java/android/filterfw/core/SimpleFrameManager.java
mca/filterfw/java/android/filterfw/core/StreamPort.java
mca/filterfw/jni/jni_gl_environment.cpp
mca/filterfw/jni/jni_gl_environment.h
mca/filterfw/jni/jni_gl_frame.cpp
mca/filterfw/jni/jni_gl_frame.h
mca/filterfw/jni/jni_shader_program.cpp
mca/filterfw/jni/jni_shader_program.h
mca/filterfw/native/core/gl_env.cpp
mca/filterfw/native/core/gl_env.h
mca/filterfw/native/core/gl_frame.cpp
mca/filterfw/native/core/gl_frame.h
mca/filterfw/native/core/shader_program.cpp
mca/filterfw/native/core/shader_program.h
mca/filterpacks/imageproc/java/AlphaBlendFilter.java
mca/filterpacks/imageproc/java/BlendFilter.java
mca/filterpacks/imageproc/java/BrightnessFilter.java
mca/filterpacks/imageproc/java/ContrastFilter.java
mca/filterpacks/imageproc/java/CropFilter.java
mca/filterpacks/imageproc/java/DrawOverlayFilter.java
mca/filterpacks/imageproc/java/DrawRectFilter.java
mca/filterpacks/imageproc/java/FisheyeFilter.java
mca/filterpacks/imageproc/java/ImageCombineFilter.java
mca/filterpacks/imageproc/java/Invert.java
mca/filterpacks/imageproc/java/ResizeFilter.java
mca/filterpacks/imageproc/java/SimpleImageFilter.java
mca/filterpacks/imageproc/java/ToGrayFilter.java
mca/filterpacks/imageproc/java/ToPackedGrayFilter.java
mca/filterpacks/ui/java/SurfaceRenderFilter.java
mca/filterpacks/videosrc/java/CameraSource.java
mca/filterpacks/videosrc/java/MediaSource.java
mca/filterpacks/videosrc/java/SurfaceTextureSource.java
mca/filterpacks/videosrc/java/SurfaceTextureTarget.java

index a879bb6..1ab416a 100644 (file)
@@ -64,7 +64,7 @@ public class MffEnvironment {
      * the environment.
      */
     public void setGLEnvironment(GLEnvironment glEnvironment) {
-        mContext.setGLEnvironment(glEnvironment);
+        mContext.initGLEnvironment(glEnvironment);
     }
 
     /**
index c1db655..254167a 100644 (file)
@@ -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);
index e2592fc..08bae55 100644 (file)
@@ -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 {
index 7dd5408..9734b89 100644 (file)
@@ -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! ");
+        }
+    }
 }
 
index 257bbba..d891300 100644 (file)
@@ -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!");
index 70fd426..225c32c 100644 (file)
@@ -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;
+    }
 }
index bcd1416..cd7fc98 100644 (file)
@@ -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();
index 85b9d26..8f5b401 100644 (file)
@@ -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();
 
index 12d1937..53e8442 100644 (file)
@@ -77,6 +77,5 @@ public abstract class InputPort extends FilterPort {
         return !hasFrame();
     }
 
-    public void transfer(FilterContext context) {
-    }
+    public abstract void transfer(FilterContext context);
 }
index 0ebd491..bed04b3 100644 (file)
@@ -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);
 
index 5b85dd5..32877e4 100644 (file)
@@ -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;
             }
index c603595..0866b00 100644 (file)
@@ -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);
+        }
+    }
 }
index 329be64..f7ccc71 100644 (file)
@@ -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<GLEnv>(env, thiz);
   return gl_env ? ToJBool(gl_env->SwapBuffers()) : JNI_FALSE;
index 33691a1..9c46c6a 100644 (file)
@@ -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);
 
index 5e45391..8e3139e 100644 (file)
 #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<GLEnv>(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<GLEnv>(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<GLEnv>(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<GLEnv>(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 {
index 7c95f85..29d307f 100644 (file)
@@ -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);
index 978abba..89f6e2b 100644 (file)
 
 #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<GLEnv>(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<GLEnv>(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,
index debf4e0..af1c02d 100644 (file)
@@ -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,
index a78f793..63e3397 100644 (file)
  */
 
 #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 <map>
@@ -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<int, SurfaceWindowPair>::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
index 5784238..13d4048 100644 (file)
 
 #include <GLES2/gl2.h>
 #include <EGL/egl.h>
+#include <pthread.h>
 
 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<typename T>
-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<int, ShaderProgram*> attached_shaders_;
+    std::map<int, VertexFrame*> 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<int, T*> GLVarMap;
-    GLVarMap variables_;
+    DISALLOW_COPY_AND_ASSIGN(GLEnv);
 };
 
-// GLBoundVariable implementation //////////////////////////////////////////////
-template<typename T>
-void GLBoundVariable<T>::SetValue(T* value) {
-  if (GLEnv::ActiveEnv())
-    variables_[GLEnv::ActiveEnv()->id()] = value;
-  else
-    LOGE("Attempting to set GL bound variable without an active context!");
-}
-
-template<typename T>
-T* GLBoundVariable<T>::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
 
index 66e1640..e3e7b82 100644 (file)
@@ -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
index 0807dfe..fd1831f 100644 (file)
@@ -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
index 85c5d3c..41225f1 100644 (file)
@@ -30,8 +30,8 @@
 namespace android {
 namespace filterfw {
 
-// Statics /////////////////////////////////////////////////////////////////////
-GLBoundVariable<VertexFrame> 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<const uint8_t*>(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,
index f10e8a8..758d22f 100644 (file)
@@ -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<GLuint>& 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<VertexFrame> s_default_vbo_;
-
-    // Built-in shaders
-    static GLBoundVariable<ShaderProgram> s_identity_;
 };
 
 } // namespace filterfw
index 3783c69..473369c 100644 (file)
@@ -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);
     }
 
 }
index ea07f61..d109002 100644 (file)
@@ -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);
     }
 
 }
index 0e02027..046e69d 100644 (file)
@@ -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);
     }
 
 }
index 612df67..70e987f 100644 (file)
@@ -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);
     }
 
 }
index 5b32a19..506fd90 100644 (file)
@@ -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) {
index ddf5ca6..e947cf3 100644 (file)
@@ -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
index 0084b41..3d00310 100644 (file)
@@ -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
index b2ddf57..9128c83 100644 (file)
@@ -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
index ba7ccb2..e4b289e 100644 (file)
@@ -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);
 }
index f576aa2..400fd5d 100644 (file)
@@ -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);
     }
 
 }
index cb10805..e8f195c 100644 (file)
@@ -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;
 
index 3810536..8df7334 100644 (file)
@@ -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);
 }
index d6fb17a..ac58db2 100644 (file)
@@ -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;
index e6b7314..16b3e0b 100644 (file)
@@ -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
index b623ad9..3e512ee 100644 (file)
@@ -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);
index 1d050c5..d766c3b 100644 (file)
@@ -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);
index 5a162fe..57de0f8 100644 (file)
@@ -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);
index 5ba5a59..6019319 100644 (file)
@@ -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);
index 2096ccf..ec02f54 100644 (file)
@@ -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);