1/* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18package android.media.effect; 19 20import android.filterfw.core.CachedFrameManager; 21import android.filterfw.core.FilterContext; 22import android.filterfw.core.FilterFactory; 23import android.filterfw.core.GLEnvironment; 24import android.filterfw.core.GLFrame; 25import android.filterfw.core.FrameManager; 26import android.opengl.GLES20; 27 28/** 29 * <p>An EffectContext keeps all necessary state information to run Effects within a Open GL ES 2.0 30 * context.</p> 31 * 32 * <p>Every EffectContext is bound to one GL context. The application is responsible for creating 33 * this EGL context, and making it current before applying any effect. If your EGL context is 34 * destroyed, the EffectContext becomes invalid and any effects bound to this context can no longer 35 * be used. If you switch to another EGL context, you must create a new EffectContext. Each Effect 36 * is bound to a single EffectContext, and can only be executed in that context.</p> 37 */ 38public class EffectContext { 39 40 private final int GL_STATE_FBO = 0; 41 private final int GL_STATE_PROGRAM = 1; 42 private final int GL_STATE_ARRAYBUFFER = 2; 43 private final int GL_STATE_COUNT = 3; 44 45 FilterContext mFilterContext; 46 47 private EffectFactory mFactory; 48 49 private int[] mOldState = new int[GL_STATE_COUNT]; 50 51 /** 52 * Creates a context within the current GL context. 53 * 54 * <p>Binds the EffectContext to the current OpenGL context. All subsequent calls to the 55 * EffectContext must be made in the GL context that was active during creation. 56 * When you have finished using a context, you must call {@link #release()}. to dispose of all 57 * resources associated with this context.</p> 58 */ 59 public static EffectContext createWithCurrentGlContext() { 60 EffectContext result = new EffectContext(); 61 result.initInCurrentGlContext(); 62 return result; 63 } 64 65 /** 66 * Returns the EffectFactory for this context. 67 * 68 * <p>The EffectFactory returned from this method allows instantiating new effects within this 69 * context.</p> 70 * 71 * @return The EffectFactory instance for this context. 72 */ 73 public EffectFactory getFactory() { 74 return mFactory; 75 } 76 77 /** 78 * Releases the context. 79 * 80 * <p>Releases all the resources and effects associated with the EffectContext. This renders the 81 * context and all the effects bound to this context invalid. You must no longer use the context 82 * or any of its bound effects after calling release().</p> 83 * 84 * <p>Note that this method must be called with the proper EGL context made current, as the 85 * EffectContext and its effects may release internal GL resources.</p> 86 */ 87 public void release() { 88 mFilterContext.tearDown(); 89 mFilterContext = null; 90 } 91 92 private EffectContext() { 93 mFilterContext = new FilterContext(); 94 mFilterContext.setFrameManager(new CachedFrameManager()); 95 mFactory = new EffectFactory(this); 96 } 97 98 private void initInCurrentGlContext() { 99 if (!GLEnvironment.isAnyContextActive()) { 100 throw new RuntimeException("Attempting to initialize EffectContext with no active " 101 + "GL context!"); 102 } 103 GLEnvironment glEnvironment = new GLEnvironment(); 104 glEnvironment.initWithCurrentContext(); 105 mFilterContext.initGLEnvironment(glEnvironment); 106 } 107 108 final void assertValidGLState() { 109 GLEnvironment glEnv = mFilterContext.getGLEnvironment(); 110 if (glEnv == null || !glEnv.isContextActive()) { 111 if (GLEnvironment.isAnyContextActive()) { 112 throw new RuntimeException("Applying effect in wrong GL context!"); 113 } else { 114 throw new RuntimeException("Attempting to apply effect without valid GL context!"); 115 } 116 } 117 } 118 119 final void saveGLState() { 120 GLES20.glGetIntegerv(GLES20.GL_FRAMEBUFFER_BINDING, mOldState, GL_STATE_FBO); 121 GLES20.glGetIntegerv(GLES20.GL_CURRENT_PROGRAM, mOldState, GL_STATE_PROGRAM); 122 GLES20.glGetIntegerv(GLES20.GL_ARRAY_BUFFER_BINDING, mOldState, GL_STATE_ARRAYBUFFER); 123 } 124 125 final void restoreGLState() { 126 GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mOldState[GL_STATE_FBO]); 127 GLES20.glUseProgram(mOldState[GL_STATE_PROGRAM]); 128 GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mOldState[GL_STATE_ARRAYBUFFER]); 129 } 130} 131 132