/** * Copyright (c) 2003-2009, Xith3D Project Group all rights reserved. * * Portions based on the Java3D interface, Copyright by Sun Microsystems. * Many thanks to the developers of Java3D and Sun Microsystems for their * innovation and design. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 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. * * Neither the name of the 'Xith3D Project Group' nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER 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) A * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE */ package org.xith3d.render.jsr231; import java.nio.IntBuffer; import java.util.List; import javax.media.opengl.GL; import org.openmali.types.twodee.Rect2i; import org.xith3d.picking.PickRequest; import org.xith3d.render.CanvasPeer; import org.xith3d.render.OpenGLCapabilities; import org.xith3d.render.OpenGLInfo; import org.xith3d.render.OpenGlExtensions; import org.xith3d.render.RenderPass; import org.xith3d.render.SceneGraphOpenGLReference; import org.xith3d.render.config.DisplayMode; import org.xith3d.render.config.FSAA; import org.xith3d.render.config.DisplayMode.FullscreenMode; import org.xith3d.scenegraph.View; import com.sun.opengl.util.BufferUtil; /** * The base for CanvasPeer implementation for the official Java OpenGL Bindings (JOGL) * * @author David Yazel [jogl] * @author Lilian Chamontin [jsr231 port] * @author Marvin Froehlich (aka Qudus) [major clean-up / speed-up, multipass rendering] */ public abstract class CanvasPeerImplBase extends CanvasPeer { private Rect2i maxViewport = new Rect2i( -1, -1, -1, -1 ); private Rect2i currentViewport = null; private boolean isDefaultViewport = true; /** The GL swapInterval (uses vsync or not) * 0 means : disable VSync. * -1 means : unspecified (default value) * > 0 means : should wait before swapping buffers. */ private int swapInterval = -1; protected boolean swapIntervalChanged = false; private long renderedFrames = 0L; private boolean isInitialized = false; @Override protected RenderPeerImpl createRenderPeer() { return ( new RenderPeerImpl( this, new StateUnitPeerRegistryImpl(), new OpenGLStatesCacheImpl() ) ); } public CanvasPeerImplBase( DisplayMode displayMode, FullscreenMode fullscreen, boolean vsync, FSAA fsaa, int depthBufferSize ) { super( displayMode, fullscreen, vsync, fsaa, depthBufferSize ); } protected final void init() { this.oglInfo = new OpenGLInfo( getGL().glGetString( GL.GL_RENDERER ), getGL().glGetString( GL.GL_VERSION ), getGL().glGetString( GL.GL_VENDOR ), getGL().glGetString( GL.GL_EXTENSIONS ) ); OpenGlExtensions.setExtensions( oglInfo ); //if ( !( this instanceof CanvasPeerImplSwing ) ) { final IntBuffer intBuffer = BufferUtil.newIntBuffer( 2 ); getGL().glGetIntegerv( GL.GL_MAX_TEXTURE_SIZE, intBuffer ); final int maxTexSize = intBuffer.get( 0 ); intBuffer.rewind(); getGL().glGetIntegerv( GL.GL_MAX_TEXTURE_UNITS, intBuffer ); final int maxTUs = intBuffer.get( 0 ); final int maxVAs; if ( oglInfo.getVersionMajor() >= 2 ) { intBuffer.rewind(); getGL().glGetIntegerv( GL.GL_MAX_VERTEX_ATTRIBS, intBuffer ); maxVAs = intBuffer.get( 0 ); } else { maxVAs = 0; } intBuffer.rewind(); getGL().glGetIntegerv( GL.GL_MAX_VIEWPORT_DIMS, intBuffer ); this.maxViewport.set( 0, 0, intBuffer.get( 0 ), intBuffer.get( 1 ) ); setOpenGLCapabilities( new OpenGLCapabilities( maxTexSize, maxTUs, TextureUnitStateUnitPeer.getMaxAnisotropicLevel( getGL() ), maxVAs, oglInfo ) ); } getRenderPeer().getStatesCache().update( getGL(), getOpenGLCapabilities() ); int[] depth_bits = new int[ 1 ]; getGL().glGetIntegerv( GL.GL_DEPTH_BITS, depth_bits, 0 ); setDepthBufferSize( depth_bits[ 0 ] ); getGL().glViewport( 0, 0, getWidth(), getHeight() ); boolean showInfos = true; try { showInfos = System.getProperty( "org.xith3d.render.jsr231.displayGLInfos", "true" ).equals( "true" ); } catch ( SecurityException ignore ) { // Ignore a SecurityException for Applet deployment } if ( showInfos ) { System.out.println( "Init GL is " + getGL().getClass().getName() ); oglInfo.dump(); } isInitialized = true; } protected final boolean isInitialized() { return ( isInitialized ); } @Override protected final Class< ? > getExpectedNativeDisplayModeClass() { return ( java.awt.DisplayMode.class ); } public abstract GL getGL(); /** * {@inheritDoc} */ @Override public final RenderPeerImpl getRenderPeer() { return ( (RenderPeerImpl)super.getRenderPeer() ); } /** * {@inheritDoc} */ @Override public long getRenderedFrames() { return ( renderedFrames ); } /** * Updates the swapInterval (used to enable/disable vsync). * * @param swapInterval the new swap interval (>=0) or -1 to use platform default. */ public final void setSwapInterval( int swapInterval ) { this.swapInterval = swapInterval; this.swapIntervalChanged = true; } /** * @return the swap interval in use (or -1 if not specified). * * @see #setSwapInterval(int) */ public final int getSwapInterval() { return ( swapInterval ); } protected abstract void setAutoSwapBufferMode( boolean mode ); /** * {@inheritDoc} */ @Override public final void addDestroyableObject( SceneGraphOpenGLReference ref ) { super.addDestroyableObject( ref ); } protected void beforeRenderStart( PickRequest pickRequest, boolean forceNoSwap ) { setAutoSwapBufferMode( !( ( pickRequest != null ) | forceNoSwap ) ); // reset triangles count setTriangles( 0 ); destroyGLNames( true ); } /** * {@inheritDoc} */ @Override public Rect2i getMaxViewport() { return ( maxViewport ); } public Rect2i getCurrentViewport() { return ( currentViewport ); } public final void updateViewport( GL gl, Rect2i viewport ) { // get the current viewport boolean viewportChanged = false; if ( currentViewport == null ) { if ( viewport == null ) { if ( getViewport() == null ) { currentViewport = new Rect2i( 0, 0, getWidth(), getHeight() ); } else { currentViewport = new Rect2i( getViewport() ); getViewport().setClean(); } isDefaultViewport = true; } else { currentViewport = new Rect2i( viewport ); isDefaultViewport = false; } viewportChanged = true; } else if ( viewport != null ) { if ( ( getViewport() != null ) && ( getViewport().isDirty() ) ) { currentViewport.set( getViewport() ); getViewport().setClean(); } if ( !currentViewport.equals( viewport ) ) { currentViewport.set( viewport ); isDefaultViewport = false; viewportChanged = true; } } else if ( !isDefaultViewport ) { if ( getViewport() == null ) { currentViewport.set( 0, 0, getWidth(), getHeight() ); } else { currentViewport.set( getViewport() ); getViewport().setClean(); } isDefaultViewport = true; viewportChanged = true; } else if ( ( isDefaultViewport ) && ( !currentViewport.equals( ( getViewport() == null ) ? this : getViewport() ) ) ) { if ( getViewport() == null ) { currentViewport.set( 0, 0, getWidth(), getHeight() ); } else { currentViewport.set( getViewport() ); getViewport().setClean(); } viewportChanged = true; } if ( viewportChanged ) { // OpenGL wants it flipped! final int y = getHeight() - currentViewport.getTop() - currentViewport.getHeight(); gl.glViewport( currentViewport.getLeft(), y, currentViewport.getWidth(), currentViewport.getHeight() ); } } /** * {@inheritDoc} */ @Override public void clear() { getRenderPeer().clearViewport( getGL() ); } /** * Uses the current render frame to draw all the graphics for the frame. * If there is not one defined then nothing wil be drawm. */ protected final Object doRender( View view, List< RenderPass > renderPasses, boolean layeredMode, long frameId, long nanoTime, long nanoStep, PickRequest pickRequest ) { Object result = null; synchronized ( getRenderLock() ) { result = getRenderPeer().render( getGL(), view, renderPasses, layeredMode, frameId, nanoTime, nanoStep, pickRequest ); } renderedFrames++; return ( result ); } }