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.filterfw.core; 1965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.Frame; 2165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.FrameFormat; 2265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.FrameManager; 2365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.NativeFrame; 2465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.filterfw.core.StopWatchMap; 2565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.graphics.Bitmap; 2665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.opengl.GLES20; 2765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport android.graphics.Rect; 2865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 2965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennimport java.nio.ByteBuffer; 3065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 3165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennclass GLFrameTimer { 3265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 3365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private static StopWatchMap mTimer = null; 3465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 3565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public static StopWatchMap get() { 3665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (mTimer == null) { 3765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mTimer = new StopWatchMap(); 3865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 3965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return mTimer; 4065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 4165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 4265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 4365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 4465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn/** 4565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * @hide 4665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 4765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Rennpublic class GLFrame extends Frame { 4865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 4965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // GL-related binding types 5065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public final static int EXISTING_TEXTURE_BINDING = 100; 5165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public final static int EXISTING_FBO_BINDING = 101; 5265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public final static int NEW_TEXTURE_BINDING = 102; // TODO: REMOVE THIS 5365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public final static int NEW_FBO_BINDING = 103; // TODO: REMOVE THIS 5465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public final static int EXTERNAL_TEXTURE = 104; 5565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 5665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private int glFrameId = -1; 5765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 5865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn /** 5965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Flag whether we own the texture or not. If we do not, we must be careful when caching or 6065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * storing the frame, as the user may delete, and regenerate it. 6165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 6265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private boolean mOwnsTexture = true; 6365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 6465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn /** 6565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * Keep a reference to the GL environment, so that it does not get deallocated while there 6665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn * are still frames living in it. 6765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn */ 6865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private GLEnvironment mGLEnvironment; 6965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 7065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLFrame(FrameFormat format, FrameManager frameManager) { 7165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn super(format, frameManager); 7265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 7365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 7465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLFrame(FrameFormat format, FrameManager frameManager, int bindingType, long bindingId) { 7565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn super(format, frameManager, bindingType, bindingId); 7665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 7765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 7865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn void init(GLEnvironment glEnv) { 7965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn FrameFormat format = getFormat(); 8065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mGLEnvironment = glEnv; 8165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 8265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Check that we have a valid format 8365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (format.getBytesPerSample() != 4) { 8465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new IllegalArgumentException("GL frames must have 4 bytes per sample!"); 8565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (format.getDimensionCount() != 2) { 8665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new IllegalArgumentException("GL frames must be 2-dimensional!"); 8765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (getFormat().getSize() < 0) { 8865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new IllegalArgumentException("Initializing GL frame with zero size!"); 8965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 9065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 9165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Create correct frame 9265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int bindingType = getBindingType(); 9365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn boolean reusable = true; 9465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (bindingType == Frame.NO_BINDING) { 9565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn initNew(false); 9665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (bindingType == EXTERNAL_TEXTURE) { 9765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn initNew(true); 9865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn reusable = false; 9965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (bindingType == EXISTING_TEXTURE_BINDING) { 10065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn initWithTexture((int)getBindingId()); 10165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (bindingType == EXISTING_FBO_BINDING) { 10265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn initWithFbo((int)getBindingId()); 10365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (bindingType == NEW_TEXTURE_BINDING) { 10465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn initWithTexture((int)getBindingId()); 10565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (bindingType == NEW_FBO_BINDING) { 10665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn initWithFbo((int)getBindingId()); 10765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 10865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Attempting to create GL frame with unknown binding type " 10965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn + bindingType + "!"); 11065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 11165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn setReusable(reusable); 11265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 11365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 11465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private void initNew(boolean isExternal) { 11565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (isExternal) { 11665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!nativeAllocateExternal(mGLEnvironment)) { 11765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Could not allocate external GL frame!"); 11865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 11965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 12065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!nativeAllocate(mGLEnvironment, getFormat().getWidth(), getFormat().getHeight())) { 12165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Could not allocate GL frame!"); 12265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 12365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 12465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 12565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 12665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private void initWithTexture(int texId) { 12765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int width = getFormat().getWidth(); 12865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int height = getFormat().getHeight(); 12965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!nativeAllocateWithTexture(mGLEnvironment, texId, width, height)) { 13065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Could not allocate texture backed GL frame!"); 13165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 13265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn mOwnsTexture = false; 13365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn markReadOnly(); 13465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 13565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 13665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private void initWithFbo(int fboId) { 13765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int width = getFormat().getWidth(); 13865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int height = getFormat().getHeight(); 13965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!nativeAllocateWithFbo(mGLEnvironment, fboId, width, height)) { 14065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Could not allocate FBO backed GL frame!"); 14165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 14265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 14365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 14465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn void flushGPU(String message) { 14565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn StopWatchMap timer = GLFrameTimer.get(); 14665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (timer.LOG_MFF_RUNNING_TIMES) { 14765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn timer.start("glFinish " + message); 14865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn GLES20.glFinish(); 14965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn timer.stop("glFinish " + message); 15065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 15165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 15265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 15365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 15465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn protected synchronized boolean hasNativeAllocation() { 15565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return glFrameId != -1; 15665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 15765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 15865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 15965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn protected synchronized void releaseNativeAllocation() { 16065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn nativeDeallocate(); 16165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn glFrameId = -1; 16265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 16365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 16465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public GLEnvironment getGLEnvironment() { 16565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return mGLEnvironment; 16665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 16765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 16865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 16965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public Object getObjectValue() { 17065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertGLEnvValid(); 17165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return ByteBuffer.wrap(getNativeData()); 17265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 17365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 17465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 17565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void setInts(int[] ints) { 17665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertFrameMutable(); 17765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertGLEnvValid(); 17865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!setNativeInts(ints)) { 17965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Could not set int values for GL frame!"); 18065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 18165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 18265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 18365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 18465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public int[] getInts() { 18565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertGLEnvValid(); 18665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn flushGPU("getInts"); 18765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return getNativeInts(); 18865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 18965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 19065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 19165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void setFloats(float[] floats) { 19265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertFrameMutable(); 19365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertGLEnvValid(); 19465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!setNativeFloats(floats)) { 19565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Could not set int values for GL frame!"); 19665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 19765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 19865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 19965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 20065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public float[] getFloats() { 20165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertGLEnvValid(); 20265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn flushGPU("getFloats"); 20365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return getNativeFloats(); 20465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 20565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 20665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 20765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void setData(ByteBuffer buffer, int offset, int length) { 20865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertFrameMutable(); 20965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertGLEnvValid(); 21065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn byte[] bytes = buffer.array(); 21165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (getFormat().getSize() != bytes.length) { 21265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Data size in setData does not match GL frame size!"); 21365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (!setNativeData(bytes, offset, length)) { 21465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Could not set GL frame data!"); 21565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 21665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 21765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 21865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 21965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public ByteBuffer getData() { 22065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertGLEnvValid(); 22165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn flushGPU("getData"); 22265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return ByteBuffer.wrap(getNativeData()); 22365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 22465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 22565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 22665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void setBitmap(Bitmap bitmap) { 22765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertFrameMutable(); 22865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertGLEnvValid(); 22965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (getFormat().getWidth() != bitmap.getWidth() || 23065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn getFormat().getHeight() != bitmap.getHeight()) { 23165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Bitmap dimensions do not match GL frame dimensions!"); 23265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 23365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Bitmap rgbaBitmap = convertBitmapToRGBA(bitmap); 23465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!setNativeBitmap(rgbaBitmap, rgbaBitmap.getByteCount())) { 23565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Could not set GL frame bitmap data!"); 23665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 23765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 23865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 23965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 24065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 24165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public Bitmap getBitmap() { 24265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertGLEnvValid(); 24365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn flushGPU("getBitmap"); 24465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Bitmap result = Bitmap.createBitmap(getFormat().getWidth(), 24565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn getFormat().getHeight(), 24665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn Bitmap.Config.ARGB_8888); 24765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!getNativeBitmap(result)) { 24865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Could not get bitmap data from GL frame!"); 24965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 25065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return result; 25165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 25265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 25365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 25465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void setDataFromFrame(Frame frame) { 25565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertGLEnvValid(); 25665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 25765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Make sure frame fits 25865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (getFormat().getSize() < frame.getFormat().getSize()) { 25965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException( 26065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "Attempting to assign frame of size " + frame.getFormat().getSize() + " to " + 26165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "smaller GL frame of size " + getFormat().getSize() + "!"); 26265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 26365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 26465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Invoke optimized implementations if possible 26565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (frame instanceof NativeFrame) { 26665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn nativeCopyFromNative((NativeFrame)frame); 26765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (frame instanceof GLFrame) { 26865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn nativeCopyFromGL((GLFrame)frame); 26965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else if (frame instanceof SimpleFrame) { 27065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn setObjectValue(frame.getObjectValue()); 27165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 27265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn super.setDataFromFrame(frame); 27365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 27465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 27565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 27665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void setViewport(int x, int y, int width, int height) { 27765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertFrameMutable(); 27865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn setNativeViewport(x, y, width, height); 27965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 28065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 28165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void setViewport(Rect rect) { 28265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertFrameMutable(); 28365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn setNativeViewport(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top); 28465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 28565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 28665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void generateMipMap() { 28765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertFrameMutable(); 28865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertGLEnvValid(); 28965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!generateNativeMipMap()) { 29065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Could not generate mip-map for GL frame!"); 29165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 29265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 29365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 29465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void setTextureParameter(int param, int value) { 29565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertFrameMutable(); 29665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn assertGLEnvValid(); 29765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!setNativeTextureParam(param, value)) { 29865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Could not set texture value " + param + " = " + value + " " + 29965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "for GLFrame!"); 30065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 30165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 30265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 30365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public int getTextureId() { 30465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return getNativeTextureId(); 30565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 30665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 30765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public int getFboId() { 30865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return getNativeFboId(); 30965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 31065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 31165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public void focus() { 31265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!nativeFocus()) { 31365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Could not focus on GLFrame for drawing!"); 31465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 31565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 31665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 31765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 31865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn public String toString() { 31965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn return "GLFrame id: " + glFrameId + " (" + getFormat() + ") with texture ID " 32065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn + getTextureId() + ", FBO ID " + getFboId(); 32165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 32265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 32365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 32465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn protected void reset(FrameFormat newFormat) { 32565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!nativeResetParams()) { 32665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Could not reset GLFrame texture parameters!"); 32765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 32865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn super.reset(newFormat); 32965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 33065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 33165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 33265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn protected void onFrameStore() { 33365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!mOwnsTexture) { 33465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Detach texture from FBO in case user manipulates it. 33565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn nativeDetachTexFromFbo(); 33665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 33765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 33865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 33965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn @Override 34065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn protected void onFrameFetch() { 34165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!mOwnsTexture) { 34265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // Reattach texture to FBO when using frame again. This may reallocate the texture 34365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn // in case it has become invalid. 34465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn nativeReattachTexToFbo(); 34565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 34665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 34765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 34865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private void assertGLEnvValid() { 34965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (!mGLEnvironment.isContextActive()) { 35065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn if (GLEnvironment.isAnyContextActive()) { 35165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Attempting to access " + this + " with foreign GL " + 35265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn "context active!"); 35365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } else { 35465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn throw new RuntimeException("Attempting to access " + this + " with no GL context " + 35565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn " active!"); 35665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 35765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 35865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 35965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 36065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn static { 36165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn System.loadLibrary("filterfw"); 36265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn } 36365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 36465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean nativeAllocate(GLEnvironment env, int width, int height); 36565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 36665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean nativeAllocateWithTexture(GLEnvironment env, 36765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int textureId, 36865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int width, 36965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int height); 37065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 37165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean nativeAllocateWithFbo(GLEnvironment env, 37265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int fboId, 37365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int width, 37465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn int height); 37565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 37665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean nativeAllocateExternal(GLEnvironment env); 37765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 37865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean nativeDeallocate(); 37965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 38065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean setNativeData(byte[] data, int offset, int length); 38165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 38265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native byte[] getNativeData(); 38365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 38465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean setNativeInts(int[] ints); 38565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 38665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean setNativeFloats(float[] floats); 38765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 38865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native int[] getNativeInts(); 38965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 39065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native float[] getNativeFloats(); 39165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 39265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean setNativeBitmap(Bitmap bitmap, int size); 39365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 39465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean getNativeBitmap(Bitmap bitmap); 39565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 39665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean setNativeViewport(int x, int y, int width, int height); 39765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 39865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native int getNativeTextureId(); 39965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 40065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native int getNativeFboId(); 40165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 40265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean generateNativeMipMap(); 40365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 40465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean setNativeTextureParam(int param, int value); 40565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 40665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean nativeResetParams(); 40765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 40865953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean nativeCopyFromNative(NativeFrame frame); 40965953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 41065953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean nativeCopyFromGL(GLFrame frame); 41165953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 41265953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean nativeFocus(); 41365953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 41465953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean nativeReattachTexToFbo(); 41565953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn 41665953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn private native boolean nativeDetachTexFromFbo(); 41765953da4636fbf5f0a24b8f5f2b5fa7d76ff13d9Marius Renn} 418