Initial work on making use of full-screen exclusive mode and additional

rendering optimizations available in JDK 1.4.  Use a BufferStrategy, and
changed AnimatedPanel to extend Canvas rather than JPanel.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@847 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Walter Korman
2002-01-08 22:16:59 +00:00
parent df14615e11
commit e3c4fd02b7
9 changed files with 159 additions and 116 deletions
@@ -1,11 +1,9 @@
//
// $Id: SpritePanel.java,v 1.8 2001/12/17 03:33:40 mdb Exp $
// $Id: SpritePanel.java,v 1.9 2002/01/08 22:16:58 shaper Exp $
package com.threerings.cast.builder;
import java.awt.*;
import javax.swing.BorderFactory;
import javax.swing.border.BevelBorder;
import com.threerings.media.sprite.*;
@@ -33,9 +31,6 @@ public class SpritePanel
_spritemgr = new SpriteManager();
_animmgr = new AnimationManager(_spritemgr, this);
// create a visually pleasing border
setBorder(BorderFactory.createBevelBorder(BevelBorder.LOWERED));
// listen to the builder model so that we can update the
// sprite when a new component is selected
_model.addListener(this);
@@ -1,25 +1,28 @@
//
// $Id: AnimatedPanel.java,v 1.5 2002/01/07 23:05:39 shaper Exp $
// $Id: AnimatedPanel.java,v 1.6 2002/01/08 22:16:58 shaper Exp $
package com.threerings.media.sprite;
import java.awt.Dimension;
import java.awt.AWTException;
import java.awt.BufferCapabilities;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.ImageCapabilities;
import java.awt.Rectangle;
import javax.swing.JComponent;
import javax.swing.JPanel;
import java.awt.image.BufferStrategy;
import com.threerings.media.Log;
/**
* The animated panel provides a useful extensible implementation of a
* Swing {@link JPanel} that implements the {@link AnimatedView}
* interface. Sub-classes should override {@link #render} to draw
* their panel-specific contents, and may choose to override {@link
* #invalidateRects} to optimize their internal rendering.
* {@link Canvas} that implements the {@link AnimatedView} interface.
* Sub-classes should override {@link #render} to draw their
* panel-specific contents, and may choose to override {@link
* #invalidateRects} and {@link #invalidateRect} to optimize their
* internal rendering.
*/
public class AnimatedPanel extends JPanel implements AnimatedView
public class AnimatedPanel extends Canvas implements AnimatedView
{
/**
* Constructs an animated panel.
@@ -27,26 +30,19 @@ public class AnimatedPanel extends JPanel implements AnimatedView
public AnimatedPanel ()
{
// set our attributes for optimal display performance
setDoubleBuffered(false);
setOpaque(true);
// setIgnoreRepaint(true);
}
// documentation inherited
public void paintComponent (Graphics g)
public void paint (Graphics g)
{
// create the offscreens if they don't yet exist
if (_offimg == null && !createOffscreen()) {
return;
}
update(g);
}
// give sub-classes a chance to do their thing
render(_offg);
// Rectangle bounds = getBounds();
// Log.info("paintComponent [bounds=" + bounds + "].");
// draw the offscreen to the screen
g.drawImage(_offimg, 0, 0, null);
// documentation inherited
public void update (Graphics g)
{
paintImmediately();
}
/**
@@ -59,26 +55,6 @@ public class AnimatedPanel extends JPanel implements AnimatedView
// nothing for now
}
/**
* Creates the offscreen image and graphics context to which we draw
* the scene for double-buffering purposes. Returns whether the
* offscreen image was successfully created.
*/
protected boolean createOffscreen ()
{
Dimension d = getSize();
try {
_offimg = createImage(d.width, d.height);
_offg = _offimg.getGraphics();
return true;
} catch (Exception e) {
Log.warning("Failed to create offscreen [e=" + e + "].");
Log.logStackTrace(e);
return false;
}
}
// documentation inherited
public void invalidateRects (DirtyRectList rects)
{
@@ -91,47 +67,54 @@ public class AnimatedPanel extends JPanel implements AnimatedView
// nothing for now
}
/**
* Paints this panel immediately. Since we know that we are always
* opaque and not dependent on Swing's double-buffering, we bypass the
* antics that <code>JComponent.paintImmediately()</code> performs in
* the interest of better performance.
*/
// documentation inherited
public void paintImmediately ()
{
if (!isValid()) {
// don't paint anything until we've been fully laid out
// Log.warning("Attempted to paint invalid panel.");
if (!isValid() || !isShowing()) {
Log.warning("Attempt to paint unprepared panel " +
"[valid=" + isValid() +
", showing=" + isShowing() + "].");
return;
}
if (_strategy == null) {
// create and obtain a reference to the buffer strategy
createBufferStrategy(BUFFER_COUNT);
_strategy = getBufferStrategy();
Log.info("Created buffer strategy [strategy=" + _strategy + "].");
}
// render the panel
Graphics g = null;
try {
Graphics pcg = getGraphics();
// apparently getGraphics() can fail if we are removed from
// the UI between the time that we queued up the code that
// calls this method and the time that it's called
if (pcg != null) {
g = pcg.create();
pcg.dispose();
paintComponent(g);
g = _strategy.getDrawGraphics();
render(g);
} finally {
if (g != null) {
g.dispose();
}
}
_strategy.show();
}
} catch (NullPointerException e) {
e.printStackTrace();
public void createBufferStrategy (int numBuffers)
{
// for now, always use un-accelerated blitting. page-flipping
// seems to result in artifacts in certain conditions, and the
// buffer strategy's volatile images are irretrievably lost when
// the panel is hidden.
BufferCapabilities bufferCaps = new BufferCapabilities(
new ImageCapabilities(false), new ImageCapabilities(false), null);
try {
createBufferStrategy(numBuffers, bufferCaps);
} catch (AWTException e) {
throw new InternalError("Could not create a buffer strategy");
}
}
// documentation inherited
public JComponent getComponent ()
{
return this;
}
/** The number of buffers to use when rendering. */
protected static final int BUFFER_COUNT = 2;
/** The offscreen image used for double-buffering. */
protected Image _offimg;
/** The graphics context for the offscreen image. */
protected Graphics _offg;
/** The buffer strategy used for optimal animation rendering. */
protected BufferStrategy _strategy;
}
@@ -1,5 +1,5 @@
//
// $Id: AnimatedView.java,v 1.5 2001/12/15 04:20:26 mdb Exp $
// $Id: AnimatedView.java,v 1.6 2002/01/08 22:16:58 shaper Exp $
package com.threerings.media.sprite;
@@ -37,11 +37,4 @@ public interface AnimatedView
* paint.
*/
public void paintImmediately ();
/**
* Return the component associated with the view so that the
* animation manager can restrict its animation to when the
* component is actually visible.
*/
public JComponent getComponent ();
}
@@ -1,5 +1,5 @@
//
// $Id: IsoSceneView.java,v 1.81 2001/12/18 08:38:33 mdb Exp $
// $Id: IsoSceneView.java,v 1.82 2002/01/08 22:16:59 shaper Exp $
package com.threerings.miso.scene;
@@ -143,9 +143,7 @@ public class IsoSceneView implements SceneView
*/
protected void invalidate ()
{
DirtyRectList rects = new DirtyRectList();
rects.add(_model.bounds);
invalidateRects(rects);
invalidateRect(_model.bounds);
}
/**
@@ -1,10 +1,11 @@
//
// $Id: SceneView.java,v 1.20 2001/12/15 04:20:55 mdb Exp $
// $Id: SceneView.java,v 1.21 2002/01/08 22:16:59 shaper Exp $
package com.threerings.miso.scene;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.List;
import com.threerings.media.sprite.DirtyRectList;
@@ -25,6 +26,14 @@ public interface SceneView
*/
public void invalidateRects (DirtyRectList rects);
/**
* Invalidate a rectangle in screen pixel coordinates in the scene
* view for later repainting.
*
* @param rect the {@link java.awt.Rectangle} object.
*/
public void invalidateRect (Rectangle rect);
/**
* Renders the scene to the given graphics context.
*
@@ -1,15 +1,17 @@
//
// $Id: SceneViewPanel.java,v 1.21 2001/11/29 20:33:16 mdb Exp $
// $Id: SceneViewPanel.java,v 1.22 2002/01/08 22:16:59 shaper Exp $
package com.threerings.miso.scene;
import java.awt.*;
import java.util.List;
import javax.swing.*;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Rectangle;
import com.samskivert.util.Config;
import com.threerings.media.sprite.*;
import com.threerings.media.sprite.AnimatedPanel;
import com.threerings.media.sprite.DirtyRectList;
import com.threerings.media.sprite.SpriteManager;
import com.threerings.miso.util.MisoUtil;
/**
@@ -82,6 +84,12 @@ public class SceneViewPanel extends AnimatedPanel
_view.invalidateRects(rects);
}
// documentation inherited
public void invalidateRect (Rectangle rect)
{
_view.invalidateRect(rect);
}
/**
* Returns the desired size for the panel based on the requested
* and calculated bounds of the scene view.
@@ -1,8 +1,12 @@
//
// $Id: ViewerApp.java,v 1.22 2001/12/16 06:52:11 shaper Exp $
// $Id: ViewerApp.java,v 1.23 2002/01/08 22:16:59 shaper Exp $
package com.threerings.miso.viewer;
import java.awt.DisplayMode;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.io.IOException;
import com.samskivert.swing.util.SwingUtil;
@@ -43,9 +47,26 @@ public class ViewerApp
System.exit(-1);
}
// create and size the main application frame
_frame = new ViewerFrame();
_frame.setSize(WIDTH, HEIGHT);
// get the graphics environment
GraphicsEnvironment env =
GraphicsEnvironment.getLocalGraphicsEnvironment();
// get the target graphics device
GraphicsDevice gd = env.getDefaultScreenDevice();
Log.info("Graphics device [dev=" + gd +
", mem=" + gd.getAvailableAcceleratedMemory() +
", displayChange=" + gd.isDisplayChangeSupported() +
", fullScreen=" + gd.isFullScreenSupported() + "].");
// get the graphics configuration and display mode information
GraphicsConfiguration gc = gd.getDefaultConfiguration();
DisplayMode dm = gd.getDisplayMode();
Log.info("Display mode [bits=" + dm.getBitDepth() +
", wid=" + dm.getWidth() + ", hei=" + dm.getHeight() +
", refresh=" + dm.getRefreshRate() + "].");
// create the window
_frame = new ViewerFrame(gc);
// we don't need to configure anything
_config = new Config();
@@ -88,6 +109,18 @@ public class ViewerApp
Log.logStackTrace(e);
System.exit(-1);
}
// size and position the window, entering full-screen exclusive
// mode if available
if (gd.isFullScreenSupported()) {
Log.info("Entering full-screen exclusive mode.");
gd.setFullScreenWindow(_frame);
} else {
Log.warning("Full-screen exclusive mode not available.");
_frame.pack();
SwingUtil.centerWindow(_frame);
}
}
/**
@@ -113,8 +146,7 @@ public class ViewerApp
*/
public void run ()
{
_frame.pack();
SwingUtil.centerWindow(_frame);
// show the window
_frame.show();
}
@@ -1,10 +1,16 @@
//
// $Id: ViewerFrame.java,v 1.28 2001/11/18 04:09:21 mdb Exp $
// $Id: ViewerFrame.java,v 1.29 2002/01/08 22:16:59 shaper Exp $
package com.threerings.miso.viewer;
import java.awt.Color;
import java.awt.Component;
import java.awt.GraphicsConfiguration;
import javax.swing.JFrame;
import javax.swing.JPanel;
import com.samskivert.swing.GroupLayout;
import com.samskivert.swing.VGroupLayout;
/**
* The viewer frame is the main application window.
@@ -14,14 +20,32 @@ public class ViewerFrame extends JFrame
/**
* Creates a frame in which the viewer application can operate.
*/
public ViewerFrame ()
public ViewerFrame (GraphicsConfiguration gc)
{
super("Scene Viewer");
super(gc);
// set up the frame options
setTitle("Scene Viewer");
// setUndecorated(true);
setIgnoreRepaint(true);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
// center the scene view within the frame
GroupLayout gl = new VGroupLayout();
gl.setJustification(GroupLayout.CENTER);
gl.setOffAxisJustification(GroupLayout.CENTER);
getContentPane().setLayout(gl);
// set the frame and content panel background to black
setBackground(Color.black);
getContentPane().setBackground(Color.black);
}
public void setPanel (JPanel panel)
/**
* Sets the panel displayed by this frame.
*/
public void setPanel (Component panel)
{
// if we had an old panel, remove it
if (_panel != null) {
@@ -33,5 +57,5 @@ public class ViewerFrame extends JFrame
getContentPane().add(_panel);
}
protected JPanel _panel;
protected Component _panel;
}
@@ -1,9 +1,10 @@
//
// $Id: ViewerSceneViewPanel.java,v 1.36 2001/12/16 06:52:11 shaper Exp $
// $Id: ViewerSceneViewPanel.java,v 1.37 2002/01/08 22:16:59 shaper Exp $
package com.threerings.miso.viewer;
import java.awt.*;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
@@ -45,7 +46,7 @@ public class ViewerSceneViewPanel extends SceneViewPanel
super(ctx.getConfig(), spritemgr);
// create an animation manager for this panel
_animmgr = new AnimationManager(spritemgr, this);
_animmgr = new AnimationManager(spritemgr, this);
// create the character descriptors
_descUser = CastUtil.getRandomDescriptor(crepo);
@@ -126,9 +127,9 @@ public class ViewerSceneViewPanel extends SceneViewPanel
}
// documentation inherited
public void paintComponent (Graphics g)
public void render (Graphics g)
{
super.paintComponent(g);
super.render(g);
PerformanceMonitor.tick(this, "paint");
}