GLFBO.java 3.11 KB
Newer Older
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
1 2 3 4 5 6 7
package com.projectseptember.RNGL;

import java.util.ArrayList;
import java.util.List;

import static android.opengl.GLES20.*;

Gaëtan Renaudeau's avatar
wip  
Gaëtan Renaudeau committed
8
public class GLFBO {
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
9 10 11 12 13 14 15 16 17
    public final List<GLTexture> color = new ArrayList<>();
    private int handle;
    private int width = 0;
    private int height = 0;

    private static GLTexture initTexture (int width, int height, int attachment) {
        GLTexture texture = new GLTexture();
        texture.bind();
        texture.setShape(width, height);
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
18
        glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, texture.getHandle(), 0);
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
19 20 21 22 23 24 25 26
        return texture;
    }

    class FBOState {

        private int fbo;

        public FBOState() {
Gaëtan Renaudeau's avatar
wip  
Gaëtan Renaudeau committed
27
            int[] fbo = new int[1];
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
28 29 30 31 32 33 34 35 36 37
            glGetIntegerv(GL_FRAMEBUFFER_BINDING, fbo, 0);
            this.fbo = fbo[0];
        }

        private void restore() {
            glBindFramebuffer(GL_FRAMEBUFFER, fbo);
        }
    }

    public GLFBO() {
Gaëtan Renaudeau's avatar
wip  
Gaëtan Renaudeau committed
38
        FBOState state = new FBOState();
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
39 40 41 42 43 44 45 46 47 48 49 50

        int[] handleArr = new int[1];
        glGenFramebuffers(1, handleArr, 0);
        handle = handleArr[0];

        int numColors = 1;

        glBindFramebuffer(GL_FRAMEBUFFER, handle);

        for(int i=0; i<numColors; ++i) {
            color.add(initTexture(width, height, GL_COLOR_ATTACHMENT0 + i));
        }
Gaëtan Renaudeau's avatar
wip  
Gaëtan Renaudeau committed
51
        state.restore();
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        int[] handleArr = new int[] { handle };
        glDeleteFramebuffers(1, handleArr, 0);
    }


    void checkStatus () {
        int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        if(status != GL_FRAMEBUFFER_COMPLETE) {
            switch (status) {
                case GL_FRAMEBUFFER_UNSUPPORTED:
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
67
                    throw new RuntimeException("Framebuffer unsupported");
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
68
                case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
69
                    throw new RuntimeException("Framebuffer incomplete attachment");
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
70
                case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
71
                    throw new RuntimeException("Framebuffer incomplete dimensions");
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
72
                case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
73
                    throw new RuntimeException("Framebuffer incomplete missing attachment");
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
74
                default:
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
75
                    throw new RuntimeException("Failed to create framebuffer: " + status);
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
76 77 78 79 80 81 82 83 84 85 86 87 88 89
            }
        }
    }

    public void bind () {
        glBindFramebuffer(GL_FRAMEBUFFER, handle);
        glViewport(0, 0, width, height);
    }

    public void setShape(int w, int h) {
        if (w == width && h == height) return;
        int[] maxFBOSize = new int[1];
        glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, maxFBOSize, 0);
        if( w < 0 || w > maxFBOSize[0] || h < 0 || h > maxFBOSize[0]) {
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
90
            throw new IllegalArgumentException("Can't resize framebuffer. Invalid dimensions");
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
91 92 93 94
        }
        width = w;
        height = h;

Gaëtan Renaudeau's avatar
wip  
Gaëtan Renaudeau committed
95
        FBOState state = new FBOState();
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
96 97 98 99 100 101 102 103

        for (GLTexture clr: color) {
            clr.setShape(w, h);
        }

        glBindFramebuffer(GL_FRAMEBUFFER, handle);
        checkStatus();

Gaëtan Renaudeau's avatar
wip  
Gaëtan Renaudeau committed
104
        state.restore();
Gaëtan Renaudeau's avatar
WIP  
Gaëtan Renaudeau committed
105 106
    }
}