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.GLEnvironment; 23import android.opengl.GLES20; 24 25/** 26 * <p>An EffectContext keeps all necessary state information to run Effects within a Open GL ES 2.0 27 * context.</p> 28 * 29 * <p>Every EffectContext is bound to one GL context. The application is responsible for creating 30 * this EGL context, and making it current before applying any effect. If your EGL context is 31 * destroyed, the EffectContext becomes invalid and any effects bound to this context can no longer 32 * be used. If you switch to another EGL context, you must create a new EffectContext. Each Effect 33 * is bound to a single EffectContext, and can only be executed in that context.</p> 34 */ 35public class EffectContext { 36 37 private final int GL_STATE_FBO = 0; 38 private final int GL_STATE_PROGRAM = 1; 39 private final int GL_STATE_ARRAYBUFFER = 2; 40 private final int GL_STATE_COUNT = 3; 41 42 FilterContext mFilterContext; 43 44 private EffectFactory mFactory; 45 46 private int[] mOldState = new int[GL_STATE_COUNT]; 47 48 /** 49 * Creates a context within the current GL context. 50 * 51 * <p>Binds the EffectContext to the current OpenGL context. All subsequent calls to the 52 * EffectContext must be made in the GL context that was active during creation. 53 * When you have finished using a context, you must call {@link #release()}. to dispose of all 54 * resources associated with this context.</p> 55 */ 56 public static EffectContext createWithCurrentGlContext() { 57 EffectContext result = new EffectContext(); 58 result.initInCurrentGlContext(); 59 return result; 60 } 61 62 /** 63 * Returns the EffectFactory for this context. 64 * 65 * <p>The EffectFactory returned from this method allows instantiating new effects within this 66 * context.</p> 67 * 68 * @return The EffectFactory instance for this context. 69 */ 70 public EffectFactory getFactory() { 71 return mFactory; 72 } 73 74 /** 75 * Releases the context. 76 * 77 * <p>Releases all the resources and effects associated with the EffectContext. This renders the 78 * context and all the effects bound to this context invalid. You must no longer use the context 79 * or any of its bound effects after calling release().</p> 80 * 81 * <p>Note that this method must be called with the proper EGL context made current, as the 82 * EffectContext and its effects may release internal GL resources.</p> 83 */ 84 public void release() { 85 mFilterContext.tearDown(); 86 mFilterContext = null; 87 } 88 89 private EffectContext() { 90 mFilterContext = new FilterContext(); 91 mFilterContext.setFrameManager(new CachedFrameManager()); 92 mFactory = new EffectFactory(this); 93 } 94 95 private void initInCurrentGlContext() { 96 if (!GLEnvironment.isAnyContextActive()) { 97 throw new RuntimeException("Attempting to initialize EffectContext with no active " 98 + "GL context!"); 99 } 100 GLEnvironment glEnvironment = new GLEnvironment(); 101 glEnvironment.initWithCurrentContext(); 102 mFilterContext.initGLEnvironment(glEnvironment); 103 } 104 105 final void assertValidGLState() { 106 GLEnvironment glEnv = mFilterContext.getGLEnvironment(); 107 if (glEnv == null || !glEnv.isContextActive()) { 108 if (GLEnvironment.isAnyContextActive()) { 109 throw new RuntimeException("Applying effect in wrong GL context!"); 110 } else { 111 throw new RuntimeException("Attempting to apply effect without valid GL context!"); 112 } 113 } 114 } 115 116 final void saveGLState() { 117 GLES20.glGetIntegerv(GLES20.GL_FRAMEBUFFER_BINDING, mOldState, GL_STATE_FBO); 118 GLES20.glGetIntegerv(GLES20.GL_CURRENT_PROGRAM, mOldState, GL_STATE_PROGRAM); 119 GLES20.glGetIntegerv(GLES20.GL_ARRAY_BUFFER_BINDING, mOldState, GL_STATE_ARRAYBUFFER); 120 } 121 122 final void restoreGLState() { 123 GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mOldState[GL_STATE_FBO]); 124 GLES20.glUseProgram(mOldState[GL_STATE_PROGRAM]); 125 GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mOldState[GL_STATE_ARRAYBUFFER]); 126 } 127} 128 129