@ -11,9 +11,11 @@ import com.jme3.util.Screenshots;
import java.awt.AWTException ;
import java.awt.BufferCapabilities ;
import java.awt.Canvas ;
import java.awt.Graphics ;
import java.awt.Graphics2D ;
import java.awt.Image ;
import java.awt.ImageCapabilities ;
import java.awt.RenderingHints ;
import java.awt.event.ComponentAdapter ;
import java.awt.event.ComponentEvent ;
import java.awt.geom.AffineTransform ;
@ -32,14 +34,16 @@ public class AwtPanel extends Canvas implements SceneProcessor {
private FrameBuffer fb ;
private ByteBuffer byteBuf ;
private IntBuffer intBuf ;
private boolean activeUpdates = true ;
private RenderManager rm ;
private PaintMode paintMode ;
private ArrayList < ViewPort > viewPorts = new ArrayList < ViewPort > ( ) ;
// Visibility/drawing vars
private BufferStrategy strategy ;
private AffineTransformOp transformOp ;
private AtomicBoolean visible = new AtomicBoolean ( false ) ;
private AtomicBoolean hasNativePeer = new AtomicBoolean ( false ) ;
private AtomicBoolean showing = new AtomicBoolean ( false ) ;
private AtomicBoolean repaintRequest = new AtomicBoolean ( false ) ;
// Reshape vars
private int newWidth = 1 ;
@ -47,10 +51,13 @@ public class AwtPanel extends Canvas implements SceneProcessor {
private AtomicBoolean reshapeNeeded = new AtomicBoolean ( false ) ;
private final Object lock = new Object ( ) ;
public AwtPanel ( boolean activeUpdates ) {
this . activeUpdates = activeUpdates ;
public AwtPanel ( PaintMode paintMode ) {
this . paintMode = paintMode ;
if ( paintMode = = PaintMode . Accelerated ) {
setIgnoreRepaint ( true ) ;
}
setIgnoreRepaint ( true ) ;
addComponentListener ( new ComponentAdapter ( ) {
@Override
public void componentResized ( ComponentEvent e ) {
@ -73,7 +80,7 @@ public class AwtPanel extends Canvas implements SceneProcessor {
super . addNotify ( ) ;
synchronized ( lock ) {
visible . set ( true ) ;
hasNativePeer . set ( true ) ;
System . out . println ( "EDT: addNotify" ) ;
}
@ -83,58 +90,102 @@ public class AwtPanel extends Canvas implements SceneProcessor {
@Override
public void removeNotify ( ) {
synchronized ( lock ) {
visible . set ( false ) ;
// strategy.dispose();
// strategy = null;
hasNativePeer . set ( false ) ;
System . out . println ( "EDT: removeNotify" ) ;
}
super . removeNotify ( ) ;
}
public void drawFrameInThread ( ) {
if ( ! visible . get ( ) ) {
@Override
public void paint ( Graphics g ) {
Graphics2D g2d = ( Graphics2D ) g ;
synchronized ( lock ) {
g2d . drawImage ( img , transformOp , 0 , 0 ) ;
}
}
public boolean checkVisibilityState ( ) {
if ( ! hasNativePeer . get ( ) ) {
if ( strategy ! = null ) {
strategy . dispose ( ) ;
strategy = null ;
System . out . println ( "OGL: Not visible. Destroy strategy." ) ;
}
return ;
return false ;
}
if ( strategy = = null | | strategy . contentsLost ( ) ) {
if ( strategy ! = null ) {
strategy . dispose ( ) ;
}
try {
createBufferStrategy ( 1 , new BufferCapabilities ( new ImageCapabilities ( true ) , new ImageCapabilities ( true ) , BufferCapabilities . FlipContents . UNDEFINED ) ) ;
} catch ( AWTException ex ) {
ex . printStackTrace ( ) ;
boolean currentShowing = isShowing ( ) ;
if ( showing . getAndSet ( currentShowing ) ! = currentShowing ) {
if ( currentShowing ) {
System . out . println ( "OGL: Enter showing state." ) ;
} else {
System . out . println ( "OGL: Exit showing state." ) ;
}
strategy = getBufferStrategy ( ) ;
System . out . println ( "OGL: BufferStrategy lost!" ) ;
}
Graphics2D g2d ;
return currentShowing ;
}
public void repaintInThread ( ) {
// Convert screenshot.
byteBuf . clear ( ) ;
rm . getRenderer ( ) . readFrameBuffer ( fb , byteBuf ) ;
synchronized ( lock ) {
g2d = ( Graphics2D ) strategy . getDrawGraphics ( ) ;
// All operations on img must be synchronized
// as it is accessed from EDT.
Screenshots . convertScreenShot2 ( intBuf , img ) ;
repaint ( ) ;
}
g2d . drawImage ( img , transformOp , 0 , 0 ) ;
g2d . dispose ( ) ;
strategy . show ( ) ;
}
public boolean isActiveUpdates ( ) {
return activeUpdates ;
}
public void setActiveUpdates ( boolean activeUpdates ) {
public void drawFrameInThread ( ) {
// Convert screenshot.
byteBuf . clear ( ) ;
rm . getRenderer ( ) . readFrameBuffer ( fb , byteBuf ) ;
Screenshots . convertScreenShot2 ( intBuf , img ) ;
synchronized ( lock ) {
this . activeUpdates = activeUpdates ;
// All operations on strategy should be synchronized (?)
if ( strategy = = null ) {
try {
createBufferStrategy ( 1 ,
new BufferCapabilities (
new ImageCapabilities ( true ) ,
new ImageCapabilities ( true ) ,
BufferCapabilities . FlipContents . UNDEFINED )
) ;
} catch ( AWTException ex ) {
ex . printStackTrace ( ) ;
}
strategy = getBufferStrategy ( ) ;
System . out . println ( "OGL: Visible. Create strategy." ) ;
}
// Draw screenshot.
do {
do {
Graphics2D g2d = ( Graphics2D ) strategy . getDrawGraphics ( ) ;
if ( g2d = = null ) {
System . out . println ( "OGL: DrawGraphics was null." ) ;
return ;
}
g2d . setRenderingHint ( RenderingHints . KEY_RENDERING ,
RenderingHints . VALUE_RENDER_SPEED ) ;
g2d . drawImage ( img , transformOp , 0 , 0 ) ;
g2d . dispose ( ) ;
strategy . show ( ) ;
} while ( strategy . contentsRestored ( ) ) ;
} while ( strategy . contentsLost ( ) ) ;
}
}
public boolean isActiveDrawing ( ) {
return paintMode ! = PaintMode . OnRequest & & showing . get ( ) ;
}
public void attachTo ( ViewPort . . . vps ) {
if ( viewPorts . size ( ) > 0 ) {
for ( ViewPort vp : viewPorts ) {
@ -158,14 +209,19 @@ public class AwtPanel extends Canvas implements SceneProcessor {
private void reshapeInThread ( int width , int height ) {
byteBuf = BufferUtils . ensureLargeEnough ( byteBuf , width * height * 4 ) ;
intBuf = byteBuf . asIntBuffer ( ) ;
fb = new FrameBuffer ( width , height , 1 ) ;
fb . setDepthBuffer ( Format . Depth ) ;
fb . setColorBuffer ( Format . RGB8 ) ;
img = new BufferedImage ( width , height , BufferedImage . TYPE_INT_RGB ) ;
synchronized ( lock ) {
img = new BufferedImage ( width , height , BufferedImage . TYPE_INT_RGB ) ;
}
// synchronized (lock){
// img = (BufferedImage) getGraphicsConfiguration().createCompatibleImage(width, height);
// }
AffineTransform tx = AffineTransform . getScaleInstance ( 1 , - 1 ) ;
tx . translate ( 0 , - img . getHeight ( ) ) ;
transformOp = new AffineTransformOp ( tx , AffineTransformOp . TYPE_NEAREST_NEIGHBOR ) ;
@ -173,6 +229,12 @@ public class AwtPanel extends Canvas implements SceneProcessor {
for ( ViewPort vp : viewPorts ) {
vp . setOutputFrameBuffer ( fb ) ;
vp . getCamera ( ) . resize ( width , height , true ) ;
// NOTE: Hack alert. This is done ONLY for custom framebuffers.
// Main framebuffer should use RenderManager.notifyReshape().
for ( SceneProcessor sp : vp . getProcessors ( ) ) {
sp . reshape ( vp , width , height ) ;
}
}
}
@ -185,6 +247,12 @@ public class AwtPanel extends Canvas implements SceneProcessor {
public void postQueue ( RenderQueue rq ) {
}
@Override
public void invalidate ( ) {
// For "PaintMode.OnDemand" only.
repaintRequest . set ( true ) ;
}
public void postFrame ( FrameBuffer out ) {
if ( out ! = fb ) {
@ -193,13 +261,25 @@ public class AwtPanel extends Canvas implements SceneProcessor {
if ( reshapeNeeded . getAndSet ( false ) ) {
reshapeInThread ( newWidth , newHeight ) ;
} else if ( activeUpdates ) {
byteBuf . clear ( ) ;
rm . getRenderer ( ) . readFrameBuffer ( fb , byteBuf ) ;
Screenshots . convertScreenShot2 ( intBuf , img ) ;
drawFrameInThread ( ) ;
} else {
if ( ! checkVisibilityState ( ) ) {
return ;
}
switch ( paintMode ) {
case Accelerated :
drawFrameInThread ( ) ;
break ;
case Repaint :
repaintInThread ( ) ;
break ;
case OnRequest :
if ( repaintRequest . getAndSet ( false ) ) {
repaintInThread ( ) ;
}
break ;
}
}
}
public void reshape ( ViewPort vp , int w , int h ) {