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