From e2e3243a2987bbdf65e7983794cd6820295061b3 Mon Sep 17 00:00:00 2001 From: Charlie Groves Date: Wed, 22 Oct 2008 01:02:31 +0000 Subject: [PATCH] Reinstate the mask cache. We were spending about half our scene time making masks git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@672 ed5b42cb-e716-0410-a449-f6a68f950b19 --- .../miso/client/MisoScenePanel.java | 56 ++++++++++--------- .../com/threerings/miso/tile/AutoFringer.java | 41 ++++++++------ 2 files changed, 55 insertions(+), 42 deletions(-) diff --git a/src/java/com/threerings/miso/client/MisoScenePanel.java b/src/java/com/threerings/miso/client/MisoScenePanel.java index 07a9b5ad..835bb13b 100644 --- a/src/java/com/threerings/miso/client/MisoScenePanel.java +++ b/src/java/com/threerings/miso/client/MisoScenePanel.java @@ -21,14 +21,6 @@ package com.threerings.miso.client; -import java.lang.ref.WeakReference; - -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; - import java.awt.AlphaComposite; import java.awt.BasicStroke; import java.awt.Color; @@ -48,6 +40,13 @@ import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; +import java.awt.image.BufferedImage; +import java.lang.ref.WeakReference; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; import javax.swing.Icon; import javax.swing.JFrame; @@ -150,6 +149,7 @@ public class MisoScenePanel extends VirtualMediaPanel _blocks.clear(); _vizobjs.clear(); _fringes.clear(); + _masks.clear(); if (_dpanel != null) { _dpanel.newScene(); } @@ -370,9 +370,9 @@ public class MisoScenePanel extends VirtualMediaPanel for (SceneBlock block : _blocks.values()) { block.computeMemoryUsage(base, fringe, object, usage); } - log.info("Scene tile memory usage", + log.info("Scene tile memory usage", "scene", StringUtil.shortClassName(this), - "base", base.size() + "->" + (usage[0] / 1024) + "k", + "base", base.size() + "->" + (usage[0] / 1024) + "k", "fringe", fringe.size() + "->" + (usage[1] / 1024) + "k", "obj", object.size() + "->" + (usage[2] / 1024) + "k"); } @@ -479,7 +479,7 @@ public class MisoScenePanel extends VirtualMediaPanel // make the menu surround the clicked object, but with consistent size Rectangle mbounds = getRadialMenuBounds(scobj); - + _activeMenu = menu; _activeMenu.addActionListener(new ActionListener() { public void actionPerformed (ActionEvent e) { @@ -515,7 +515,7 @@ public class MisoScenePanel extends VirtualMediaPanel } return mbounds; } - + /** * Returns the size of the rectangle around which we create an * object's radial menu. The default is a sensible size, but derived @@ -874,7 +874,7 @@ public class MisoScenePanel extends VirtualMediaPanel * Configures influentialBounds to contain the bounds of the potentially * "influential" world and visibleBlockBounds to contain bounds that are used to * determine which blocks should be resolved before making the view visible. - * + * *

Everything that intersects the influential area will be resolved on the expectation * that it could be scrolled into view at any time. The influential bounds should be large * enough that the time between a block becoming influential and the time at which it is @@ -890,7 +890,7 @@ public class MisoScenePanel extends VirtualMediaPanel influentualBounds.setBounds(visibleBounds.x - infborx, visibleBounds.y - infbory, visibleBounds.width + 2 * infborx, visibleBounds.height + 3 * infbory); visibleBlockBounds.setBounds(visibleBounds.x - visibleBounds.width / 4, - visibleBounds.y, visibleBounds.width + visibleBounds.width / 2, + visibleBounds.y, visibleBounds.width + visibleBounds.width / 2, visibleBounds.height + infbory); } @@ -922,7 +922,7 @@ public class MisoScenePanel extends VirtualMediaPanel if (_dpanel != null) { _dpanel.blockCleared(block); } - + blockFinished(block); } @@ -947,7 +947,7 @@ public class MisoScenePanel extends VirtualMediaPanel _remgr.invalidateRegion(sbounds); } } - + blockFinished(block); } @@ -1007,10 +1007,10 @@ public class MisoScenePanel extends VirtualMediaPanel // see which of this block's objects are visible SceneObject[] objs = block.getObjects(); - for (int ii = 0; ii < objs.length; ii++) { - if (objs[ii].bounds != null && - vbounds.intersects(objs[ii].bounds)) { - _vizobjs.add(objs[ii]); + for (SceneObject obj : objs) { + if (obj.bounds != null && + vbounds.intersects(obj.bounds)) { + _vizobjs.add(obj); } } } @@ -1228,7 +1228,7 @@ public class MisoScenePanel extends VirtualMediaPanel } super.paint(g); } - + @Override protected void paintInFront (Graphics2D gfx, Rectangle dirty) { @@ -1337,7 +1337,7 @@ public class MisoScenePanel extends VirtualMediaPanel { // make sure the indicators are ready if (!_indicatorsLaidOut) { - List boundaries = Lists.newArrayList(); + List boundaries = Lists.newArrayList(); for (Map.Entry entry : _indicators.entrySet()) { entry.getValue().layout(gfx, entry.getKey(), _vbounds, boundaries); dirtyIndicator(entry.getValue()); @@ -1415,7 +1415,8 @@ public class MisoScenePanel extends VirtualMediaPanel /** Computes the fringe tile for the specified coordinate. */ protected BaseTile computeFringeTile (int tx, int ty) { - return _ctx.getTileManager().getAutoFringer().getFringeTile(_model, tx, ty, _fringes); + return _ctx.getTileManager().getAutoFringer().getFringeTile(_model, tx, ty, _fringes, + _masks); } /** @@ -1563,6 +1564,11 @@ public class MisoScenePanel extends VirtualMediaPanel /** A list of the potentially visible objects in the scene. */ protected List _vizobjs = Lists.newArrayList(); + /** + * Map of the masks used to calculate fringes in this scene. + */ + protected Map _masks = Maps.newHashMap(); + /** * Map of active fringe tiles. Scene blocks have hard references to fringe tiles in this map * for the tiles they're using, so the blocks coming in and out of the influential bounds @@ -1616,7 +1622,7 @@ public class MisoScenePanel extends VirtualMediaPanel /** The scene block resolver for this scene panel's context. */ protected SceneBlockResolver _resolver; - + /** Scene block resolvers shared by all scene panels in a context. */ protected static Map _resolvers = new WeakHashMap(); @@ -1624,7 +1630,7 @@ public class MisoScenePanel extends VirtualMediaPanel // used to display debugging information on scene block resolution protected JFrame _dframe; protected ResolutionView _dpanel; - + protected TileOpApplicator _applicator; /** A debug hook that toggles debug rendering of traversable tiles. */ diff --git a/src/java/com/threerings/miso/tile/AutoFringer.java b/src/java/com/threerings/miso/tile/AutoFringer.java index 98536f56..bfd99c0b 100644 --- a/src/java/com/threerings/miso/tile/AutoFringer.java +++ b/src/java/com/threerings/miso/tile/AutoFringer.java @@ -113,7 +113,7 @@ public class AutoFringer * Compute and return the fringe tile to be inserted at the specified location. */ public BaseTile getFringeTile (MisoSceneModel scene, int col, int row, - Map> fringes) + Map> fringes, Map masks) { // get the tileset id of the base tile we are considering int underset = adjustTileSetId(scene.getBaseTileId(col, row) >> 16); @@ -180,14 +180,15 @@ public class AutoFringer } } - return composeFringeTile(frecs, fringes, TileUtil.getTileHash(col, row), passable); + return composeFringeTile(frecs, fringes, TileUtil.getTileHash(col, row), passable, masks); } /** * Compose a FringeTile out of the various fringe images needed. */ protected FringeTile composeFringeTile (FringerRec[] fringers, - Map> fringes, int hashValue, boolean passable) + Map> fringes, int hashValue, boolean passable, + Map masks) { // sort the array so that higher priority fringers get drawn first QuickSort.sort(fringers); @@ -195,15 +196,15 @@ public class AutoFringer // Generate an identifier for the fringe tile being created as an array of the keys of its // component tiles in the order they'll be drawn in the fringe tile. List keys = Lists.newArrayList(); - for (int ii = 0; ii < fringers.length; ii++) { - int[] indexes = getFringeIndexes(fringers[ii].bits); + for (FringerRec fringer : fringers) { + int[] indexes = getFringeIndexes(fringer.bits); FringeConfiguration.FringeTileSetRecord tsr = _fringeconf.getFringe( - fringers[ii].baseset, hashValue); + fringer.baseset, hashValue); int fringeset = tsr.fringe_tsid; - for (int jj = 0; jj < indexes.length; jj++) { + for (int index : indexes) { // Add a key for this tile as a long containing its base tile, the fringe set it's // working with and the index used in that set. - keys.add((((long)fringers[ii].baseset) << 32) + (fringeset << 16) + indexes[jj]); + keys.add((((long)fringer.baseset) << 32) + (fringeset << 16) + index); } } long[] fringeId = new long[keys.size()]; @@ -224,13 +225,13 @@ public class AutoFringer // There's no fringe with he same identifier, so we need to create the tile. BufferedImage img = null; - for (int ii = 0; ii < fringers.length; ii++) { - int[] indexes = getFringeIndexes(fringers[ii].bits); + for (FringerRec fringer : fringers) { + int[] indexes = getFringeIndexes(fringer.bits); FringeConfiguration.FringeTileSetRecord tsr = _fringeconf.getFringe( - fringers[ii].baseset, hashValue); - for (int jj = 0; jj < indexes.length; jj++) { + fringer.baseset, hashValue); + for (int index : indexes) { try { - img = getTileImage(img, tsr, fringers[ii].baseset, indexes[jj], hashValue); + img = getTileImage(img, tsr, fringer.baseset, index, hashValue, masks); } catch (NoSuchTileSetException nstse) { log.warning("Autofringer couldn't find a needed tileset", nstse); } @@ -245,7 +246,8 @@ public class AutoFringer * Retrieve or compose an image for the specified fringe. */ protected BufferedImage getTileImage (BufferedImage img, - FringeConfiguration.FringeTileSetRecord tsr, int baseset, int index, int hashValue) + FringeConfiguration.FringeTileSetRecord tsr, int baseset, int index, int hashValue, + Map masks) throws NoSuchTileSetException { int fringeset = tsr.fringe_tsid; @@ -257,9 +259,14 @@ public class AutoFringer } // otherwise, it's a mask.. - BufferedImage fsrc = _tmgr.getTileSet(fringeset).getRawTileImage(index); - BufferedImage bsrc = _tmgr.getTileSet(baseset).getRawTileImage(0); - BufferedImage mask = ImageUtil.composeMaskedImage(_imgr, fsrc, bsrc); + Long maskkey = Long.valueOf((((long)baseset) << 32) + (fringeset << 16) + index); + BufferedImage mask = masks.get(maskkey); + if (mask == null) { + BufferedImage fsrc = _tmgr.getTileSet(fringeset).getRawTileImage(index); + BufferedImage bsrc = _tmgr.getTileSet(baseset).getRawTileImage(0); + mask = ImageUtil.composeMaskedImage(_imgr, fsrc, bsrc); + masks.put(maskkey, mask); + } return stampTileImage(mask, img, mask.getWidth(null), mask.getHeight(null)); }