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
This commit is contained in:
Charlie Groves
2008-10-22 01:02:31 +00:00
parent b13728ac5f
commit e2e3243a29
2 changed files with 55 additions and 42 deletions
@@ -21,14 +21,6 @@
package com.threerings.miso.client; 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.AlphaComposite;
import java.awt.BasicStroke; import java.awt.BasicStroke;
import java.awt.Color; import java.awt.Color;
@@ -48,6 +40,13 @@ import java.awt.event.ActionListener;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.awt.event.MouseListener; import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener; 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.Icon;
import javax.swing.JFrame; import javax.swing.JFrame;
@@ -150,6 +149,7 @@ public class MisoScenePanel extends VirtualMediaPanel
_blocks.clear(); _blocks.clear();
_vizobjs.clear(); _vizobjs.clear();
_fringes.clear(); _fringes.clear();
_masks.clear();
if (_dpanel != null) { if (_dpanel != null) {
_dpanel.newScene(); _dpanel.newScene();
} }
@@ -1007,10 +1007,10 @@ public class MisoScenePanel extends VirtualMediaPanel
// see which of this block's objects are visible // see which of this block's objects are visible
SceneObject[] objs = block.getObjects(); SceneObject[] objs = block.getObjects();
for (int ii = 0; ii < objs.length; ii++) { for (SceneObject obj : objs) {
if (objs[ii].bounds != null && if (obj.bounds != null &&
vbounds.intersects(objs[ii].bounds)) { vbounds.intersects(obj.bounds)) {
_vizobjs.add(objs[ii]); _vizobjs.add(obj);
} }
} }
} }
@@ -1415,7 +1415,8 @@ public class MisoScenePanel extends VirtualMediaPanel
/** Computes the fringe tile for the specified coordinate. */ /** Computes the fringe tile for the specified coordinate. */
protected BaseTile computeFringeTile (int tx, int ty) 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. */ /** A list of the potentially visible objects in the scene. */
protected List<SceneObject> _vizobjs = Lists.newArrayList(); protected List<SceneObject> _vizobjs = Lists.newArrayList();
/**
* Map of the masks used to calculate fringes in this scene.
*/
protected Map<Long, BufferedImage> _masks = Maps.newHashMap();
/** /**
* Map of active fringe tiles. Scene blocks have hard references to fringe tiles in this map * 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 * for the tiles they're using, so the blocks coming in and out of the influential bounds
@@ -113,7 +113,7 @@ public class AutoFringer
* Compute and return the fringe tile to be inserted at the specified location. * Compute and return the fringe tile to be inserted at the specified location.
*/ */
public BaseTile getFringeTile (MisoSceneModel scene, int col, int row, public BaseTile getFringeTile (MisoSceneModel scene, int col, int row,
Map<FringeTile, WeakReference<FringeTile>> fringes) Map<FringeTile, WeakReference<FringeTile>> fringes, Map<Long, BufferedImage> masks)
{ {
// get the tileset id of the base tile we are considering // get the tileset id of the base tile we are considering
int underset = adjustTileSetId(scene.getBaseTileId(col, row) >> 16); 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. * Compose a FringeTile out of the various fringe images needed.
*/ */
protected FringeTile composeFringeTile (FringerRec[] fringers, protected FringeTile composeFringeTile (FringerRec[] fringers,
Map<FringeTile, WeakReference<FringeTile>> fringes, int hashValue, boolean passable) Map<FringeTile, WeakReference<FringeTile>> fringes, int hashValue, boolean passable,
Map<Long, BufferedImage> masks)
{ {
// sort the array so that higher priority fringers get drawn first // sort the array so that higher priority fringers get drawn first
QuickSort.sort(fringers); 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 // 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. // component tiles in the order they'll be drawn in the fringe tile.
List<Long> keys = Lists.newArrayList(); List<Long> keys = Lists.newArrayList();
for (int ii = 0; ii < fringers.length; ii++) { for (FringerRec fringer : fringers) {
int[] indexes = getFringeIndexes(fringers[ii].bits); int[] indexes = getFringeIndexes(fringer.bits);
FringeConfiguration.FringeTileSetRecord tsr = _fringeconf.getFringe( FringeConfiguration.FringeTileSetRecord tsr = _fringeconf.getFringe(
fringers[ii].baseset, hashValue); fringer.baseset, hashValue);
int fringeset = tsr.fringe_tsid; 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 // 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. // 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()]; 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. // There's no fringe with he same identifier, so we need to create the tile.
BufferedImage img = null; BufferedImage img = null;
for (int ii = 0; ii < fringers.length; ii++) { for (FringerRec fringer : fringers) {
int[] indexes = getFringeIndexes(fringers[ii].bits); int[] indexes = getFringeIndexes(fringer.bits);
FringeConfiguration.FringeTileSetRecord tsr = _fringeconf.getFringe( FringeConfiguration.FringeTileSetRecord tsr = _fringeconf.getFringe(
fringers[ii].baseset, hashValue); fringer.baseset, hashValue);
for (int jj = 0; jj < indexes.length; jj++) { for (int index : indexes) {
try { try {
img = getTileImage(img, tsr, fringers[ii].baseset, indexes[jj], hashValue); img = getTileImage(img, tsr, fringer.baseset, index, hashValue, masks);
} catch (NoSuchTileSetException nstse) { } catch (NoSuchTileSetException nstse) {
log.warning("Autofringer couldn't find a needed tileset", 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. * Retrieve or compose an image for the specified fringe.
*/ */
protected BufferedImage getTileImage (BufferedImage img, protected BufferedImage getTileImage (BufferedImage img,
FringeConfiguration.FringeTileSetRecord tsr, int baseset, int index, int hashValue) FringeConfiguration.FringeTileSetRecord tsr, int baseset, int index, int hashValue,
Map<Long, BufferedImage> masks)
throws NoSuchTileSetException throws NoSuchTileSetException
{ {
int fringeset = tsr.fringe_tsid; int fringeset = tsr.fringe_tsid;
@@ -257,9 +259,14 @@ public class AutoFringer
} }
// otherwise, it's a mask.. // otherwise, it's a mask..
BufferedImage fsrc = _tmgr.getTileSet(fringeset).getRawTileImage(index); Long maskkey = Long.valueOf((((long)baseset) << 32) + (fringeset << 16) + index);
BufferedImage bsrc = _tmgr.getTileSet(baseset).getRawTileImage(0); BufferedImage mask = masks.get(maskkey);
BufferedImage mask = ImageUtil.composeMaskedImage(_imgr, fsrc, bsrc); 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)); return stampTileImage(mask, img, mask.getWidth(null), mask.getHeight(null));
} }