165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/* 265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Copyright (C) 2011 The Android Open Source Project 365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Licensed under the Apache License, Version 2.0 (the "License"); 565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * you may not use this file except in compliance with the License. 665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * You may obtain a copy of the License at 765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * http://www.apache.org/licenses/LICENSE-2.0 965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 1065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Unless required by applicable law or agreed to in writing, software 1165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * distributed under the License is distributed on an "AS IS" BASIS, 1265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * See the License for the specific language governing permissions and 1465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * limitations under the License. 1565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 1665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 1765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 1865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpackage android.media.effect; 1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.CachedFrameManager; 2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.FilterContext; 2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.GLEnvironment; 2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.opengl.GLES20; 2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/** 2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * <p>An EffectContext keeps all necessary state information to run Effects within a Open GL ES 2.0 2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * context.</p> 2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * <p>Every EffectContext is bound to one GL context. The application is responsible for creating 3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * this EGL context, and making it current before applying any effect. If your EGL context is 3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * destroyed, the EffectContext becomes invalid and any effects bound to this context can no longer 3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * be used. If you switch to another EGL context, you must create a new EffectContext. Each Effect 3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * is bound to a single EffectContext, and can only be executed in that context.</p> 3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpublic class EffectContext { 3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private final int GL_STATE_FBO = 0; 3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private final int GL_STATE_PROGRAM = 1; 3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private final int GL_STATE_ARRAYBUFFER = 2; 4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private final int GL_STATE_COUNT = 3; 4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn FilterContext mFilterContext; 4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private EffectFactory mFactory; 4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private int[] mOldState = new int[GL_STATE_COUNT]; 4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn /** 4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Creates a context within the current GL context. 5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * <p>Binds the EffectContext to the current OpenGL context. All subsequent calls to the 5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * EffectContext must be made in the GL context that was active during creation. 5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * When you have finished using a context, you must call {@link #release()}. to dispose of all 5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * resources associated with this context.</p> 5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static EffectContext createWithCurrentGlContext() { 5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn EffectContext result = new EffectContext(); 5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn result.initInCurrentGlContext(); 5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return result; 6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn /** 6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Returns the EffectFactory for this context. 6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * <p>The EffectFactory returned from this method allows instantiating new effects within this 6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * context.</p> 6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * @return The EffectFactory instance for this context. 6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public EffectFactory getFactory() { 7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return mFactory; 7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn /** 7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Releases the context. 7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * <p>Releases all the resources and effects associated with the EffectContext. This renders the 7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * context and all the effects bound to this context invalid. You must no longer use the context 7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * or any of its bound effects after calling release().</p> 8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * 8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * <p>Note that this method must be called with the proper EGL context made current, as the 8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * EffectContext and its effects may release internal GL resources.</p> 8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void release() { 8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mFilterContext.tearDown(); 8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mFilterContext = null; 8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private EffectContext() { 9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mFilterContext = new FilterContext(); 9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mFilterContext.setFrameManager(new CachedFrameManager()); 9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mFactory = new EffectFactory(this); 9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private void initInCurrentGlContext() { 9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!GLEnvironment.isAnyContextActive()) { 9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Attempting to initialize EffectContext with no active " 9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn + "GL context!"); 9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLEnvironment glEnvironment = new GLEnvironment(); 10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glEnvironment.initWithCurrentContext(); 10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mFilterContext.initGLEnvironment(glEnvironment); 10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final void assertValidGLState() { 10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLEnvironment glEnv = mFilterContext.getGLEnvironment(); 10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (glEnv == null || !glEnv.isContextActive()) { 10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (GLEnvironment.isAnyContextActive()) { 10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Applying effect in wrong GL context!"); 11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Attempting to apply effect without valid GL context!"); 11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final void saveGLState() { 11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLES20.glGetIntegerv(GLES20.GL_FRAMEBUFFER_BINDING, mOldState, GL_STATE_FBO); 11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLES20.glGetIntegerv(GLES20.GL_CURRENT_PROGRAM, mOldState, GL_STATE_PROGRAM); 11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLES20.glGetIntegerv(GLES20.GL_ARRAY_BUFFER_BINDING, mOldState, GL_STATE_ARRAYBUFFER); 12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn final void restoreGLState() { 12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mOldState[GL_STATE_FBO]); 12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLES20.glUseProgram(mOldState[GL_STATE_PROGRAM]); 12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mOldState[GL_STATE_ARRAYBUFFER]); 12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 129