diff options
author | Sven Gothel <[email protected]> | 2014-07-05 04:04:43 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-07-05 04:04:43 +0200 |
commit | f8f0f051604721bceaee214b8e5218fd47d2eb9e (patch) | |
tree | e9c3103498984fbc5d2f8567e88009c49e8810f7 /src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java | |
parent | 2293a53ba04a8cf2881e8919f8be97c16a9af336 (diff) |
Bug 1021: Make OVR access vendor agnostic: Package 'com.jogamp.opengl.util.stereo' contains all public interfaces/classes
Renamed interfaces:
CustomRendererListener -> CustomGLEventListener
StereoRendererListener -> StereoGLEventListener
New vendor agnostic 'stuff' in com.jogamp.opengl.util.stereo:
1 - StereoDeviceFactory
To create a vendor specific StereoDeviceFactory instance,
which creates the StereoDevice.
2 - StereoDevice
For vendor specific implementation.
Can create StereoDeviceRenderer.
3 - StereoDeviceRenderer
For vendor specific implementation.
4 - StereoClientRenderer
Vendor agnostic client StereoGLEventListener renderer,
using a StereoDeviceRenderer.
Now supports multiple StereoGLEventListener, via add/remove.
- MovieSBSStereo demo-able via StereoDemo01
can show SBS 3D movies.
Diffstat (limited to 'src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java')
-rw-r--r-- | src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java new file mode 100644 index 000000000..9f9ebdf2a --- /dev/null +++ b/src/jogl/classes/com/jogamp/opengl/util/stereo/StereoClientRenderer.java @@ -0,0 +1,255 @@ +/** + * Copyright 2014 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ +package com.jogamp.opengl.util.stereo; + +import javax.media.nativewindow.util.DimensionImmutable; +import javax.media.nativewindow.util.RectangleImmutable; +import javax.media.opengl.GL; +import javax.media.opengl.GL2ES2; +import javax.media.opengl.GLAutoDrawable; +import javax.media.opengl.GLEventListener; + +import jogamp.opengl.GLDrawableHelper; +import jogamp.opengl.GLDrawableHelper.GLEventListenerAction; + +import com.jogamp.opengl.FBObject; +import com.jogamp.opengl.FBObject.Attachment; +import com.jogamp.opengl.FBObject.TextureAttachment; +import com.jogamp.opengl.FBObject.Attachment.Type; +import com.jogamp.opengl.util.CustomGLEventListener; + +/** + * {@link StereoClientRenderer} utilizing {@link StereoDeviceRenderer} + * implementing {@link GLEventListener} for convenience. + * <p> + * Implementation renders {@link StereoGLEventListener} + * using one or more {@link FBObject} according to {@link StereoDeviceRenderer#getTextureCount()}. + * </p> + */ +public class StereoClientRenderer implements GLEventListener { + private final GLDrawableHelper helper; + private final StereoDeviceRenderer deviceRenderer; + private final boolean ownsDevice; + private final FBObject[] fbos; + private final int magFilter; + private final int minFilter; + private final boolean usePostprocessing; + + private int numSamples; + private final TextureAttachment[] fboTexs; + + public StereoClientRenderer(final StereoDeviceRenderer deviceRenderer, final boolean ownsDevice, + final int magFilter, final int minFilter, final int numSamples) { + final int fboCount = deviceRenderer.getTextureCount(); + if( 0 > fboCount || 2 < fboCount ) { + throw new IllegalArgumentException("fboCount must be within [0..2], has "+fboCount+", due to "+deviceRenderer); + } + this.helper = new GLDrawableHelper(); + this.deviceRenderer = deviceRenderer; + this.usePostprocessing = deviceRenderer.ppRequired() || deviceRenderer.usesSideBySideStereo() && fboCount > 1; + this.ownsDevice = ownsDevice; + this.magFilter = magFilter; + this.minFilter = minFilter; + + this.numSamples = numSamples; + + this.fbos = new FBObject[fboCount]; + for(int i=0; i<fboCount; i++) { + this.fbos[i] = new FBObject(); + } + this.fboTexs = new TextureAttachment[fboCount]; + } + + private void initFBOs(final GL gl, final DimensionImmutable size) { + for(int i=0; i<fbos.length; i++) { + fbos[i].detachAllColorbuffer(gl); + fbos[i].reset(gl, size.getWidth(), size.getHeight(), numSamples, false); + if( i>0 && fbos[i-1].getNumSamples() != fbos[i].getNumSamples()) { + throw new InternalError("sample size mismatch: \n\t0: "+fbos[i-1]+"\n\t1: "+fbos[i]); + } + numSamples = fbos[i].getNumSamples(); + + if(numSamples>0) { + fbos[i].attachColorbuffer(gl, 0, true); // MSAA requires alpha + fbos[i].attachRenderbuffer(gl, Type.DEPTH, 24); + final FBObject ssink = new FBObject(); + { + ssink.reset(gl, size.getWidth(), size.getHeight()); + ssink.attachTexture2D(gl, 0, false, magFilter, minFilter, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + ssink.attachRenderbuffer(gl, Attachment.Type.DEPTH, 24); + } + fbos[i].setSamplingSink(ssink); + fbos[i].resetSamplingSink(gl); // validate + fboTexs[i] = fbos[i].getSamplingSink(); + } else { + fboTexs[i] = fbos[i].attachTexture2D(gl, 0, false, magFilter, minFilter, GL.GL_CLAMP_TO_EDGE, GL.GL_CLAMP_TO_EDGE); + fbos[i].attachRenderbuffer(gl, Type.DEPTH, 24); + } + fbos[i].unbind(gl); + System.err.println("FBO["+i+"]: "+fbos[i]); + } + + } + + @SuppressWarnings("unused") + private void resetFBOs(final GL gl, final DimensionImmutable size) { + for(int i=0; i<fbos.length; i++) { + fbos[i].reset(gl, size.getWidth(), size.getHeight(), numSamples, true); + if( i>0 && fbos[i-1].getNumSamples() != fbos[i].getNumSamples()) { + throw new InternalError("sample size mismatch: \n\t0: "+fbos[i-1]+"\n\t1: "+fbos[i]); + } + numSamples = fbos[i].getNumSamples(); + if(numSamples>0) { + fboTexs[i] = fbos[i].getSamplingSink(); + } else { + fboTexs[i] = (TextureAttachment) fbos[i].getColorbuffer(0); + } + } + } + + public final StereoDeviceRenderer getStereoDeviceRenderer() { return deviceRenderer; } + + public final void addGLEventListener(final StereoGLEventListener l) { + helper.addGLEventListener(l); + } + public final void removeGLEventListener(final StereoGLEventListener l) { + helper.removeGLEventListener(l); + } + + @Override + public void init(final GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + deviceRenderer.init(gl); + + // We will do some offscreen rendering, setup FBO... + final DimensionImmutable textureSize = deviceRenderer.getTextureCount() > 1 ? deviceRenderer.getSingleSurfaceSize() : deviceRenderer.getTotalSurfaceSize(); + initFBOs(gl, textureSize); + helper.init(drawable, false); + + gl.setSwapInterval(1); + } + + @Override + public void dispose(final GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + helper.disposeAllGLEventListener(drawable, false); + for(int i=0; i<fbos.length; i++) { + fbos[i].destroy(gl); + fboTexs[i] = null; + } + if( ownsDevice ) { + deviceRenderer.dispose(gl); + } + } + + @Override + public void display(final GLAutoDrawable drawable) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + + deviceRenderer.beginFrame(gl); + + if(0 < numSamples) { + gl.glEnable(GL.GL_MULTISAMPLE); + } + + final int fboCount = fbos.length; + final int displayRepeatFlags; + if( 1 == fboCount ) { + displayRepeatFlags = CustomGLEventListener.DISPLAY_DONTCLEAR; + } else { + displayRepeatFlags = 0; + } + + // Update eye pos upfront to have same (almost) results + deviceRenderer.updateEyePose(0); + deviceRenderer.updateEyePose(1); + + if( 1 == fboCount ) { + fbos[0].bind(gl); + } + + for(int eyeNum=0; eyeNum<2; eyeNum++) { + if( 1 < fboCount ) { + fbos[eyeNum].bind(gl); + } + + final StereoDeviceRenderer.Eye eye = deviceRenderer.getEye(eyeNum); + final RectangleImmutable viewport = eye.getViewport(); + gl.glViewport(viewport.getX(), viewport.getY(), viewport.getWidth(), viewport.getHeight()); + + final int displayFlags = eyeNum > 0 ? CustomGLEventListener.DISPLAY_REPEAT | displayRepeatFlags : 0; + final GLEventListenerAction reshapeDisplayAction = new GLEventListenerAction() { + public void run(final GLAutoDrawable drawable, final GLEventListener listener) { + final StereoGLEventListener sl = (StereoGLEventListener) listener; + sl.reshapeForEye(drawable, viewport.getX(), viewport.getY(), viewport.getWidth(), viewport.getHeight(), + eye.getEyeParameter(), eye.getLastEyePose()); + sl.display(drawable, displayFlags); + } }; + helper.runForAllGLEventListener(drawable, reshapeDisplayAction); + + if( 1 < fboCount ) { + fbos[eyeNum].unbind(gl); + } + } + if( 1 == fboCount ) { + fbos[0].unbind(gl); + } + // restore viewport + gl.glViewport(0, 0, drawable.getSurfaceWidth(), drawable.getSurfaceHeight()); + + if( usePostprocessing ) { + deviceRenderer.ppBegin(gl); + if( 1 == fboCount ) { + fbos[0].use(gl, fboTexs[0]); + deviceRenderer.ppBothEyes(gl); + fbos[0].unuse(gl); + } else { + fbos[0].use(gl, fboTexs[0]); + deviceRenderer.ppOneEye(gl, 0); + fbos[0].unuse(gl); + fbos[1].use(gl, fboTexs[1]); + deviceRenderer.ppOneEye(gl, 1); + fbos[1].unuse(gl); + } + deviceRenderer.ppEnd(gl); + } + + if( !drawable.getAutoSwapBufferMode() ) { + drawable.swapBuffers(); + } + deviceRenderer.endFrame(gl); + } + + @Override + public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) { + if( !drawable.getAutoSwapBufferMode() ) { + final GL2ES2 gl = drawable.getGL().getGL2ES2(); + gl.glViewport(0, 0, width, height); + } + } +} |