summaryrefslogtreecommitdiffstats
path: root/src/jogl/classes/jogamp/opengl/GLFBODrawableImpl.java
blob: 03bc26cbca10cfb720c1dc9e6ac52427420e650b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package jogamp.opengl;

import javax.media.nativewindow.NativeSurface;
import javax.media.opengl.GL;
import javax.media.opengl.GL2GL3;
import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLException;

import com.jogamp.nativewindow.MutableGraphicsConfiguration;
import com.jogamp.opengl.FBObject;
import com.jogamp.opengl.FBObject.Attachment;
import com.jogamp.opengl.FBObject.TextureAttachment;

/**
 * Offscreen GLDrawable implementation using framebuffer object (FBO)
 * as it's offscreen rendering mechanism.
 * 
 * @see GLDrawableImpl#contextRealized(GLContext, boolean)
 * @see GLDrawableImpl#contextMadeCurrent(GLContext, boolean)
 * @see GLDrawableImpl#getDefaultDrawFramebuffer()
 * @see GLDrawableImpl#getDefaultReadFramebuffer()
 */
public class GLFBODrawableImpl extends GLDrawableImpl {
    final GLDrawableImpl parent;
    final FBObject fbo;
    int texUnit;
    int samplesTexUnit = 0;
    int width=0, height=0, samples=0;
    
    protected GLFBODrawableImpl(GLDrawableFactoryImpl factory, GLDrawableImpl parent, 
                                NativeSurface surface, int initialWidth, int initialHeight, int textureUnit) {
        super(factory, surface, false);
        this.parent = parent;
        this.texUnit = textureUnit;
        final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities();
        this.width = initialWidth;
        this.height = initialHeight;
        this.samples = caps.getNumSamples();
        this.fbo = new FBObject();
    }
    
    @Override
    protected void contextRealized(GLContext glc, boolean realized) {
        final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) surface.getGraphicsConfiguration().getChosenCapabilities();
        final GL gl = glc.getGL();
        if(realized) {                   
            fbo.reset(gl, width, height, samples);
            samples = fbo.getNumSamples(); // update, maybe capped
            if(samples > 0) {
                fbo.attachColorbuffer(gl, 0, caps.getAlphaBits()>0);
            } else {
                fbo.attachTexture2D(gl, 0, caps.getAlphaBits()>0);
            }
            if( caps.getStencilBits() > 0 ) {
                fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH_STENCIL, 24);
            } else {
                fbo.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24);
            }
        } else if(null != fbo) {
            fbo.destroy(gl);
        }
    }
    
    @Override
    protected void contextMadeCurrent(GLContext glc, boolean current) {
        final GL gl = glc.getGL();
        if(current) {
            fbo.bind(gl);
        } else {
            fbo.unbind(gl);
            final TextureAttachment attachment = samples > 0 ? fbo.getSamplingSink() : (TextureAttachment) fbo.getColorbuffer(0) ;
            if(null == attachment) {
                throw new GLException("Null texture colorbuffer, samples "+samples+", "+fbo.toString());
            }
            gl.glActiveTexture(GL.GL_TEXTURE0 + texUnit);
            fbo.use(gl, attachment );
            if( samples > 0) {
                gl.glBindFramebuffer(GL2GL3.GL_READ_FRAMEBUFFER, fbo.getReadFramebuffer());
            }
        }
    }
    
    @Override
    protected int getDefaultDrawFramebuffer() { return fbo.getWriteFramebuffer(); }
    
    @Override
    protected int getDefaultReadFramebuffer() { return fbo.getReadFramebuffer(); }
    
    public FBObject getFBObject() { return fbo; }
    
    public void setSize(GL gl, int newWidth, int newHeight) throws GLException {
        width = newWidth;
        height = newHeight;        
        fbo.reset(gl, width, height, samples);
        samples = fbo.getNumSamples(); // update, maybe capped
    }
    
    public void setSamples(GL gl, int newSamples) throws GLException {
        samples = newSamples;
        fbo.reset(gl, width, height, samples);
        samples = fbo.getNumSamples(); // update, maybe capped
    }
    
    
    @Override
    public GLContext createContext(GLContext shareWith) {
        final GLContext ctx = parent.createContext(shareWith);
        ctx.setGLDrawable(this, false);
        return ctx;
    }

    @Override
    public GLDynamicLookupHelper getGLDynamicLookupHelper() {
        return parent.getGLDynamicLookupHelper();
    }

    @Override
    protected void swapBuffersImpl() {
    }

    @Override
    protected void setRealizedImpl() {
        parent.setRealized(realized);
        if(realized) {    
            final MutableGraphicsConfiguration msConfig = (MutableGraphicsConfiguration) surface.getGraphicsConfiguration();
            final GLCapabilitiesImmutable chosenCaps = (GLCapabilitiesImmutable) msConfig.getChosenCapabilities();
            final GLCapabilitiesImmutable chosenFBOCaps = GLGraphicsConfigurationUtil.fixOffscreenGLCapabilities(chosenCaps, true /*FBO*/, false /*PBO*/);    
            msConfig.setChosenCapabilities(chosenFBOCaps);
        }
    }

    @Override
    public int getWidth() {
        return width;
    }

    @Override
    public int getHeight() {
        return height;
    }    
}