1776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn/* 2776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * Copyright (C) 2011 The Android Open Source Project 3776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * 4776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * Licensed under the Apache License, Version 2.0 (the "License"); 5776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * you may not use this file except in compliance with the License. 6776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * You may obtain a copy of the License at 7776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * 8776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * http://www.apache.org/licenses/LICENSE-2.0 9776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * 10776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * Unless required by applicable law or agreed to in writing, software 11776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * distributed under the License is distributed on an "AS IS" BASIS, 12776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * See the License for the specific language governing permissions and 14776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * limitations under the License. 15776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn */ 16776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 17776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 18776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Rennpackage android.media.effect; 19776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 20776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Rennimport android.filterfw.core.CachedFrameManager; 21776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Rennimport android.filterfw.core.FilterContext; 22776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Rennimport android.filterfw.core.FilterFactory; 23776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Rennimport android.filterfw.core.GLEnvironment; 24776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Rennimport android.filterfw.core.GLFrame; 25776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Rennimport android.filterfw.core.FrameManager; 26776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Rennimport android.opengl.GLES20; 27776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 28776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn/** 29aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * <p>An EffectContext keeps all necessary state information to run Effects within a Open GL ES 2.0 30aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * context.</p> 31aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * 32aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * <p>Every EffectContext is bound to one GL context. The application is responsible for creating 33aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * this EGL context, and making it current before applying any effect. If your EGL context is 34aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * destroyed, the EffectContext becomes invalid and any effects bound to this context can no longer 35aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * be used. If you switch to another EGL context, you must create a new EffectContext. Each Effect 36aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * is bound to a single EffectContext, and can only be executed in that context.</p> 37776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn */ 38776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Rennpublic class EffectContext { 39776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 40776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn private final int GL_STATE_FBO = 0; 41776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn private final int GL_STATE_PROGRAM = 1; 42776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn private final int GL_STATE_ARRAYBUFFER = 2; 43776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn private final int GL_STATE_COUNT = 3; 44776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 45776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn FilterContext mFilterContext; 46776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 47776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn private EffectFactory mFactory; 48776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 49776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn private int[] mOldState = new int[GL_STATE_COUNT]; 50776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 51776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn /** 52776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * Creates a context within the current GL context. 53776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * 54aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * <p>Binds the EffectContext to the current OpenGL context. All subsequent calls to the 55776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * EffectContext must be made in the GL context that was active during creation. 56776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * When you have finished using a context, you must call {@link #release()}. to dispose of all 57aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * resources associated with this context.</p> 58776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn */ 59776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn public static EffectContext createWithCurrentGlContext() { 60776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn EffectContext result = new EffectContext(); 61776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn result.initInCurrentGlContext(); 62776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn return result; 63776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn } 64776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 65776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn /** 66776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * Returns the EffectFactory for this context. 67776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * 68aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * <p>The EffectFactory returned from this method allows instantiating new effects within this 69aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * context.</p> 70776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * 71c2ab83c3be33a48d47b10c9c141e7ef2180956a5Marius Renn * @return The EffectFactory instance for this context. 72776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn */ 73776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn public EffectFactory getFactory() { 74776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn return mFactory; 75776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn } 76776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 77776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn /** 78776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * Releases the context. 79776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn * 80aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * <p>Releases all the resources and effects associated with the EffectContext. This renders the 81aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * context and all the effects bound to this context invalid. You must no longer use the context 82aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * or any of its bound effects after calling release().</p> 83aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * 84aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * <p>Note that this method must be called with the proper EGL context made current, as the 85aaf40ac9627e3dd89601ac31268ab36ec3fe359bMarius Renn * EffectContext and its effects may release internal GL resources.</p> 86776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn */ 87776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn public void release() { 88776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn mFilterContext.tearDown(); 89776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn mFilterContext = null; 90776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn } 91776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 92776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn private EffectContext() { 93776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn mFilterContext = new FilterContext(); 94776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn mFilterContext.setFrameManager(new CachedFrameManager()); 95776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn mFactory = new EffectFactory(this); 96776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn } 97776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 98776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn private void initInCurrentGlContext() { 99776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn if (!GLEnvironment.isAnyContextActive()) { 100776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn throw new RuntimeException("Attempting to initialize EffectContext with no active " 101776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn + "GL context!"); 102776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn } 103776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn GLEnvironment glEnvironment = new GLEnvironment(); 104776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn glEnvironment.initWithCurrentContext(); 105776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn mFilterContext.initGLEnvironment(glEnvironment); 106776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn } 107776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 108776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn final void assertValidGLState() { 109776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn GLEnvironment glEnv = mFilterContext.getGLEnvironment(); 110776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn if (glEnv == null || !glEnv.isContextActive()) { 111776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn if (GLEnvironment.isAnyContextActive()) { 112776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn throw new RuntimeException("Applying effect in wrong GL context!"); 113776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn } else { 114776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn throw new RuntimeException("Attempting to apply effect without valid GL context!"); 115776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn } 116776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn } 117776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn } 118776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 119776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn final void saveGLState() { 120776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn GLES20.glGetIntegerv(GLES20.GL_FRAMEBUFFER_BINDING, mOldState, GL_STATE_FBO); 121776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn GLES20.glGetIntegerv(GLES20.GL_CURRENT_PROGRAM, mOldState, GL_STATE_PROGRAM); 122776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn GLES20.glGetIntegerv(GLES20.GL_ARRAY_BUFFER_BINDING, mOldState, GL_STATE_ARRAYBUFFER); 123776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn } 124776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 125776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn final void restoreGLState() { 126776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mOldState[GL_STATE_FBO]); 127776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn GLES20.glUseProgram(mOldState[GL_STATE_PROGRAM]); 128776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mOldState[GL_STATE_ARRAYBUFFER]); 129776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn } 130776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn} 131776102d45a18a5df53d2ec76c5d93f20b3e99da1Marius Renn 132