/**
* 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;
import java.util.Arrays;
import java.util.Vector;
/**
* This class manages {@link SceneGraphOpenGLReference}es per OpenGL context.
*
* @author Marvin Froehlich (aka Qudus)
*/
public class SceneGraphOpenGLReferences
{
public static interface Provider
{
public SceneGraphOpenGLReference newReference( CanvasPeer canvasPeer, SceneGraphOpenGLReferences references, int numNamesPerContext );
}
private static final Vector<SceneGraphOpenGLReferences> instances = new Vector<SceneGraphOpenGLReferences>();
//private CanvasPeer[] contexts = new CanvasPeer[ 0 ];
private SceneGraphOpenGLReference[] references = new SceneGraphOpenGLReference[ 0 ];
private final int numNamesPerContext;
private final boolean ensureCanvasID( int canvasID )
{
if ( references.length >= canvasID )
return ( true );
final SceneGraphOpenGLReference[] newReferences = new SceneGraphOpenGLReference[ canvasID ];
System.arraycopy( references, 0, newReferences, 0, references.length );
Arrays.fill( newReferences, references.length, newReferences.length, null );
references = newReferences;
/*
final CanvasPeer[] newContexts = new CanvasPeer[ canvasID ];
System.arraycopy( contexts, 0, newContexts, 0, contexts.length );
Arrays.fill( newContexts, contexts.length, newContexts.length, null );
contexts = newContexts;
*/
return ( false );
}
/*
public final SceneGraphOpenGLReference getReference( int canvasID, Provider provider )
{
final int canvasIDm1 = canvasID - 1;
if ( ( !ensureCanvasID( canvasID ) ) || ( references[ canvasIDm1 ] == null ) )
{
references[ canvasIDm1 ] = provider.newReference( this, numNamesPerContext );
}
return ( references[ canvasIDm1 ] );
}
*/
public final SceneGraphOpenGLReference getReference( CanvasPeer canvasPeer, Provider provider )
{
int canvasID = canvasPeer.getCanvasID();
final int canvasIDm1 = canvasID - 1;
if ( references.length < canvasID )
{
ensureCanvasID( canvasID );
references[ canvasIDm1 ] = provider.newReference( canvasPeer, this, numNamesPerContext );
//contexts[ canvasIDm1 ] = canvasPeer;
}
else if ( references[ canvasIDm1 ] == null )
{
references[ canvasIDm1 ] = provider.newReference( canvasPeer, this, numNamesPerContext );
//contexts[ canvasIDm1 ] = canvasPeer;
}
/*
else if ( contexts[ canvasIDm1 ] != canvasPeer )
{
references[ canvasIDm1 ].destroyObject();
references[ canvasIDm1 ] = provider.newReference( canvasPeer, this, numNamesPerContext );
//contexts[ canvasIDm1 ] = canvasPeer;
}
*/
return ( references[ canvasIDm1 ] );
}
public SceneGraphOpenGLReference removeReference( int canvasID )
{
if ( references.length < canvasID )
//throw new Error( "No reference available" ) );
return ( null );
final int canvasIDm1 = canvasID - 1;
final SceneGraphOpenGLReference result = references[ canvasIDm1 ];
//references[ canvasIDm1 ].destroy();
references[ canvasIDm1 ] = null;
//contexts[ canvasIDm1 ] = null;
return ( result );
}
public final boolean referenceExists( CanvasPeer canvasPeer )
{
final int canvasIDm1 = canvasPeer.getCanvasID() - 1;
if ( canvasIDm1 >= references.length )
return ( false );
if ( references[ canvasIDm1 ] != null )
{
/*
if ( contexts[ canvasIDm1 ] != canvasPeer )
{
//references[ canvasIDm1 ].prepareObjectForDestroy();
references[ canvasIDm1 ] = null;
contexts[ canvasIDm1 ] = null;
return ( false );
}
*/
return ( true );
}
return ( false );
}
public final int getNumReferences()
{
return ( references.length );
}
public final int getNumExistingNames()
{
int num = 0;
for ( int i = 0; i < references.length; i++ )
{
if ( references[ i ] != null )
num += references[ i ].getNumNames( true );
}
return ( num );
}
public void set( SceneGraphOpenGLReferences other )
{
this.ensureCanvasID( other.references.length );
Arrays.fill( this.references, other.references.length + 1, this.references.length, null );
//Arrays.fill( this.contexts, other.contexts.length + 1, this.contexts.length, null );
System.arraycopy( other.references, 0, this.references, 0, other.references.length );
//System.arraycopy( other.contexts, 0, this.contexts, 0, other.contexts.length );
}
public final void prepareObjectForDestroy( CanvasPeer canvasPeer )
{
if ( references.length == 0 )
return;
if ( canvasPeer == null )
return;
final SceneGraphOpenGLReference ref = references[ canvasPeer.getCanvasID() - 1 ];
if ( ( ref != null )/* && ( contexts[ canvasPeer.getCanvasID() - 1 ] == canvasPeer )*/ )
ref.prepareObjectForDestroy();
}
public final void prepareObjectForDestroy()
{
for ( int i = 0; i < references.length; i++ )
{
if ( references[ i ] != null )
{
references[ i ].prepareObjectForDestroy();
}
}
// we can remove the references container now, since this references object does not contain any gl references anymore
synchronized ( instances )
{
instances.remove( this );
}
}
public final void invalidateNames()
{
for ( int i = 0; i < references.length; i++ )
{
if ( references[ i ] != null )
{
final int numNames = references[ i ].getNumNames( false );
for ( int j = 0; j < numNames; j++ )
{
references[ i ].invalidateName( j );
}
}
}
}
public static void destroyObjects( CanvasPeer context )
{
synchronized ( instances )
{
for ( int i = instances.size() - 1; i >= 0; i-- )
{
SceneGraphOpenGLReferences object = instances.get( i );
for ( int j = 0; j < object.references.length; j++ )
{
if ( ( object.references[ j ] != null ) && ( object.references[ j ].getContext() == context ) )
{
object.references[ j ].destroyObject();
object.references[ j ] = null;
//object.contexts[ j ] = null;
}
}
}
}
}
public SceneGraphOpenGLReferences( int numNamesPerContext )
{
this.numNamesPerContext = numNamesPerContext;
synchronized ( instances )
{
instances.add( this );
}
}
}