/* * Copyright (C) 2011 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.media.effect; import android.filterfw.core.CachedFrameManager; import android.filterfw.core.FilterContext; import android.filterfw.core.GLEnvironment; import android.opengl.GLES20; /** *
An EffectContext keeps all necessary state information to run Effects within a Open GL ES 2.0 * context.
* *Every EffectContext is bound to one GL context. The application is responsible for creating * this EGL context, and making it current before applying any effect. If your EGL context is * destroyed, the EffectContext becomes invalid and any effects bound to this context can no longer * be used. If you switch to another EGL context, you must create a new EffectContext. Each Effect * is bound to a single EffectContext, and can only be executed in that context.
*/ public class EffectContext { private final int GL_STATE_FBO = 0; private final int GL_STATE_PROGRAM = 1; private final int GL_STATE_ARRAYBUFFER = 2; private final int GL_STATE_COUNT = 3; FilterContext mFilterContext; private EffectFactory mFactory; private int[] mOldState = new int[GL_STATE_COUNT]; /** * Creates a context within the current GL context. * *Binds the EffectContext to the current OpenGL context. All subsequent calls to the * EffectContext must be made in the GL context that was active during creation. * When you have finished using a context, you must call {@link #release()}. to dispose of all * resources associated with this context.
*/ public static EffectContext createWithCurrentGlContext() { EffectContext result = new EffectContext(); result.initInCurrentGlContext(); return result; } /** * Returns the EffectFactory for this context. * *The EffectFactory returned from this method allows instantiating new effects within this * context.
* * @return The EffectFactory instance for this context. */ public EffectFactory getFactory() { return mFactory; } /** * Releases the context. * *Releases all the resources and effects associated with the EffectContext. This renders the * context and all the effects bound to this context invalid. You must no longer use the context * or any of its bound effects after calling release().
* *Note that this method must be called with the proper EGL context made current, as the * EffectContext and its effects may release internal GL resources.
*/ public void release() { mFilterContext.tearDown(); mFilterContext = null; } private EffectContext() { mFilterContext = new FilterContext(); mFilterContext.setFrameManager(new CachedFrameManager()); mFactory = new EffectFactory(this); } private void initInCurrentGlContext() { if (!GLEnvironment.isAnyContextActive()) { throw new RuntimeException("Attempting to initialize EffectContext with no active " + "GL context!"); } GLEnvironment glEnvironment = new GLEnvironment(); glEnvironment.initWithCurrentContext(); mFilterContext.initGLEnvironment(glEnvironment); } final void assertValidGLState() { GLEnvironment glEnv = mFilterContext.getGLEnvironment(); if (glEnv == null || !glEnv.isContextActive()) { if (GLEnvironment.isAnyContextActive()) { throw new RuntimeException("Applying effect in wrong GL context!"); } else { throw new RuntimeException("Attempting to apply effect without valid GL context!"); } } } final void saveGLState() { GLES20.glGetIntegerv(GLES20.GL_FRAMEBUFFER_BINDING, mOldState, GL_STATE_FBO); GLES20.glGetIntegerv(GLES20.GL_CURRENT_PROGRAM, mOldState, GL_STATE_PROGRAM); GLES20.glGetIntegerv(GLES20.GL_ARRAY_BUFFER_BINDING, mOldState, GL_STATE_ARRAYBUFFER); } final void restoreGLState() { GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mOldState[GL_STATE_FBO]); GLES20.glUseProgram(mOldState[GL_STATE_PROGRAM]); GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mOldState[GL_STATE_ARRAYBUFFER]); } }