From e3c4fd02b70f04099c3ea39e9ba3202db68b787a Mon Sep 17 00:00:00 2001 From: Walter Korman Date: Tue, 8 Jan 2002 22:16:59 +0000 Subject: [PATCH] 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 --- .../threerings/cast/builder/SpritePanel.java | 7 +- .../media/sprite/AnimatedPanel.java | 133 ++++++++---------- .../threerings/media/sprite/AnimatedView.java | 9 +- .../threerings/miso/client/IsoSceneView.java | 6 +- .../com/threerings/miso/client/SceneView.java | 11 +- .../miso/client/SceneViewPanel.java | 18 ++- .../com/threerings/miso/viewer/ViewerApp.java | 44 +++++- .../threerings/miso/viewer/ViewerFrame.java | 36 ++++- .../miso/viewer/ViewerSceneViewPanel.java | 11 +- 9 files changed, 159 insertions(+), 116 deletions(-) diff --git a/src/java/com/threerings/cast/builder/SpritePanel.java b/src/java/com/threerings/cast/builder/SpritePanel.java index 011fdaaa0..eb4fa6a64 100644 --- a/src/java/com/threerings/cast/builder/SpritePanel.java +++ b/src/java/com/threerings/cast/builder/SpritePanel.java @@ -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); diff --git a/src/java/com/threerings/media/sprite/AnimatedPanel.java b/src/java/com/threerings/media/sprite/AnimatedPanel.java index c978dc818..307d93624 100644 --- a/src/java/com/threerings/media/sprite/AnimatedPanel.java +++ b/src/java/com/threerings/media/sprite/AnimatedPanel.java @@ -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 JComponent.paintImmediately() 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; } diff --git a/src/java/com/threerings/media/sprite/AnimatedView.java b/src/java/com/threerings/media/sprite/AnimatedView.java index f11470988..210f2d163 100644 --- a/src/java/com/threerings/media/sprite/AnimatedView.java +++ b/src/java/com/threerings/media/sprite/AnimatedView.java @@ -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 (); } diff --git a/src/java/com/threerings/miso/client/IsoSceneView.java b/src/java/com/threerings/miso/client/IsoSceneView.java index dca9d0b02..153f31d28 100644 --- a/src/java/com/threerings/miso/client/IsoSceneView.java +++ b/src/java/com/threerings/miso/client/IsoSceneView.java @@ -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); } /** diff --git a/src/java/com/threerings/miso/client/SceneView.java b/src/java/com/threerings/miso/client/SceneView.java index 1ab5ec7cd..4a4cb00ad 100644 --- a/src/java/com/threerings/miso/client/SceneView.java +++ b/src/java/com/threerings/miso/client/SceneView.java @@ -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. * diff --git a/src/java/com/threerings/miso/client/SceneViewPanel.java b/src/java/com/threerings/miso/client/SceneViewPanel.java index 56a77e273..7af40c56d 100644 --- a/src/java/com/threerings/miso/client/SceneViewPanel.java +++ b/src/java/com/threerings/miso/client/SceneViewPanel.java @@ -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. diff --git a/tests/src/java/com/threerings/miso/viewer/ViewerApp.java b/tests/src/java/com/threerings/miso/viewer/ViewerApp.java index 20f3603f3..51e91282a 100644 --- a/tests/src/java/com/threerings/miso/viewer/ViewerApp.java +++ b/tests/src/java/com/threerings/miso/viewer/ViewerApp.java @@ -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(); } diff --git a/tests/src/java/com/threerings/miso/viewer/ViewerFrame.java b/tests/src/java/com/threerings/miso/viewer/ViewerFrame.java index ad3f7192c..acb6f65fc 100644 --- a/tests/src/java/com/threerings/miso/viewer/ViewerFrame.java +++ b/tests/src/java/com/threerings/miso/viewer/ViewerFrame.java @@ -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; } diff --git a/tests/src/java/com/threerings/miso/viewer/ViewerSceneViewPanel.java b/tests/src/java/com/threerings/miso/viewer/ViewerSceneViewPanel.java index 2e21017be..d8c903abf 100644 --- a/tests/src/java/com/threerings/miso/viewer/ViewerSceneViewPanel.java +++ b/tests/src/java/com/threerings/miso/viewer/ViewerSceneViewPanel.java @@ -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"); }