X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.scenegraph%2Fsrc%2Forg%2Fsimantics%2Fscenegraph%2Futils%2FVolatileImageCache.java;fp=bundles%2Forg.simantics.scenegraph%2Fsrc%2Forg%2Fsimantics%2Fscenegraph%2Futils%2FVolatileImageCache.java;h=0a8d2ba1978d1d84f6b80df4b38df0e8b2bdd041;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hp=f7a297cc13105fbbf760b9642e6f449ae66647e1;hpb=24e2b34260f219f0d1644ca7a138894980e25b14;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/VolatileImageCache.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/VolatileImageCache.java index f7a297cc1..0a8d2ba19 100644 --- a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/VolatileImageCache.java +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/VolatileImageCache.java @@ -1,182 +1,182 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.scenegraph.utils; - -import java.awt.GraphicsConfiguration; -import java.awt.Image; -import java.awt.Transparency; -import java.awt.image.VolatileImage; -import java.lang.ref.Reference; -import java.lang.ref.SoftReference; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * @author Antti Villberg - */ -public class VolatileImageCache { - - private static final boolean DEBUG = false; - - private static VolatileImageCache instance = null; - - private VolatileImageCache() { - } - - public static VolatileImageCache getInstance() { - if (instance == null) { - instance = new VolatileImageCache(); - } - return instance; - } - - /** - * The max allowed size of the cache in megapixels. The amount of actual - * consumed (video) memory is approximately 4 times this. - */ - private static final int MAX_SIZE = 8 * 1024 * 1024; - - - /** - * Current size of the cache in megapixels. - */ - private int size = 0; - private int counter = 0; - - class VolatileImageProviderImpl implements VolatileImageProvider { - private final int id; - private final int w; - private final int h; - - private Reference imageRef = null; - - public VolatileImageProviderImpl(int w, int h) { - this.id = counter++; - this.w = w; - this.h = h; - } - - private VolatileImage dereferenceImage() { - return imageRef != null ? imageRef.get() : null; - } - - public VolatileImage get(GraphicsConfiguration gc, AtomicInteger _validateResult) { - int validateResult = VolatileImage.IMAGE_INCOMPATIBLE; - VolatileImage vimg = dereferenceImage(); - //System.out.println("GC: " + gc); - if (vimg != null) - validateResult = vimg.validate(gc); - - if (validateResult == VolatileImage.IMAGE_RESTORED) { - if (DEBUG) - System.out.println("VOLATILE IMAGE RESTORED for PROVIDER " + this); - } - if (validateResult == VolatileImage.IMAGE_INCOMPATIBLE) { - if (DEBUG) - System.out.println("(RE)CREATING VOLATILE IMAGE FOR PROVIDER " + this); - vimg = gc.createCompatibleVolatileImage(w, h, Transparency.TRANSLUCENT); - - if (vimg == null) { - throw new IllegalStateException(this + ": got null VolatileImage from GraphicsConfiguration " + gc); - } else { - this.imageRef = new SoftReference(vimg); - - // Implement move to front required for LRU - synchronized (cache) { - Object oldObject = cache.remove(this); - boolean wasCached = oldObject == this; - cache.put(this, this); - if (!wasCached) { - size += w * h; - - if (DEBUG) - debug(this, cache.size(), size - w*h, size, "created new image"); - } else { - //if (DEBUG) - // debug(this, cache.size(), size, size, "LRU move-to-front"); - } - } - } - } - - if (_validateResult != null) - _validateResult.set(validateResult); - - return vimg; - } - - public void dispose() { - int newSize; - synchronized (cache) { - newSize = size; - Object removed = cache.remove(this); - if (removed == this) { - newSize -= w * h; - size = newSize; - - if (DEBUG) - debug(this, cache.size(), newSize + w*h, newSize, "explicitly disposed"); - } - if (imageRef != null) { - flushImageRef(imageRef); - imageRef = null; - } - } - } - } - - private static final String MSG = "[provider #%-10d @%-8x][image (%-3d,%-3d)][cache entries=%-4d, old size=%-10d, new size=%-10d, size change=%-+6d] %s"; - - private static void debug(VolatileImageProviderImpl i, int entries, int oldSize, int newSize, String msg) { - if (DEBUG) { - int sizeChange = newSize - oldSize; - String s = String.format(MSG, i.id, i.hashCode(), i.w, i.h, entries, oldSize, newSize, sizeChange, msg); - System.out.println(s); - } - } - - private final Map cache = new LinkedHashMap(50, .75F, true) { - private static final long serialVersionUID = 5946026822169837291L; - @Override - protected boolean removeEldestEntry(Map.Entry eldest) { - boolean result = size > MAX_SIZE; - if (result) { -// new Exception().printStackTrace(); - VolatileImageProviderImpl impl = eldest.getKey(); - size -= impl.w*impl.h; - - //debug(impl, impl.imageId, cache.size(), oldSize, size, "cache full, dumping oldest"); - - flushImageRef(impl.imageRef); - impl.imageRef = null; - } - return result; - } - }; - - private static final void flushImageRef(Reference imageRef) { - if (imageRef != null) { - Image img = imageRef.get(); - imageRef.clear(); - if (img != null) - img.flush(); - } - } - - VolatileImageProvider create(int w, int h) { -// System.out.println("VolatileImageProvider.create(" + w + ", " + h + ")"); - VolatileImageProviderImpl result = new VolatileImageProviderImpl(w, h); - return result; - } - -} +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.scenegraph.utils; + +import java.awt.GraphicsConfiguration; +import java.awt.Image; +import java.awt.Transparency; +import java.awt.image.VolatileImage; +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * @author Antti Villberg + */ +public class VolatileImageCache { + + private static final boolean DEBUG = false; + + private static VolatileImageCache instance = null; + + private VolatileImageCache() { + } + + public static VolatileImageCache getInstance() { + if (instance == null) { + instance = new VolatileImageCache(); + } + return instance; + } + + /** + * The max allowed size of the cache in megapixels. The amount of actual + * consumed (video) memory is approximately 4 times this. + */ + private static final int MAX_SIZE = 8 * 1024 * 1024; + + + /** + * Current size of the cache in megapixels. + */ + private int size = 0; + private int counter = 0; + + class VolatileImageProviderImpl implements VolatileImageProvider { + private final int id; + private final int w; + private final int h; + + private Reference imageRef = null; + + public VolatileImageProviderImpl(int w, int h) { + this.id = counter++; + this.w = w; + this.h = h; + } + + private VolatileImage dereferenceImage() { + return imageRef != null ? imageRef.get() : null; + } + + public VolatileImage get(GraphicsConfiguration gc, AtomicInteger _validateResult) { + int validateResult = VolatileImage.IMAGE_INCOMPATIBLE; + VolatileImage vimg = dereferenceImage(); + //System.out.println("GC: " + gc); + if (vimg != null) + validateResult = vimg.validate(gc); + + if (validateResult == VolatileImage.IMAGE_RESTORED) { + if (DEBUG) + System.out.println("VOLATILE IMAGE RESTORED for PROVIDER " + this); + } + if (validateResult == VolatileImage.IMAGE_INCOMPATIBLE) { + if (DEBUG) + System.out.println("(RE)CREATING VOLATILE IMAGE FOR PROVIDER " + this); + vimg = gc.createCompatibleVolatileImage(w, h, Transparency.TRANSLUCENT); + + if (vimg == null) { + throw new IllegalStateException(this + ": got null VolatileImage from GraphicsConfiguration " + gc); + } else { + this.imageRef = new SoftReference(vimg); + + // Implement move to front required for LRU + synchronized (cache) { + Object oldObject = cache.remove(this); + boolean wasCached = oldObject == this; + cache.put(this, this); + if (!wasCached) { + size += w * h; + + if (DEBUG) + debug(this, cache.size(), size - w*h, size, "created new image"); + } else { + //if (DEBUG) + // debug(this, cache.size(), size, size, "LRU move-to-front"); + } + } + } + } + + if (_validateResult != null) + _validateResult.set(validateResult); + + return vimg; + } + + public void dispose() { + int newSize; + synchronized (cache) { + newSize = size; + Object removed = cache.remove(this); + if (removed == this) { + newSize -= w * h; + size = newSize; + + if (DEBUG) + debug(this, cache.size(), newSize + w*h, newSize, "explicitly disposed"); + } + if (imageRef != null) { + flushImageRef(imageRef); + imageRef = null; + } + } + } + } + + private static final String MSG = "[provider #%-10d @%-8x][image (%-3d,%-3d)][cache entries=%-4d, old size=%-10d, new size=%-10d, size change=%-+6d] %s"; + + private static void debug(VolatileImageProviderImpl i, int entries, int oldSize, int newSize, String msg) { + if (DEBUG) { + int sizeChange = newSize - oldSize; + String s = String.format(MSG, i.id, i.hashCode(), i.w, i.h, entries, oldSize, newSize, sizeChange, msg); + System.out.println(s); + } + } + + private final Map cache = new LinkedHashMap(50, .75F, true) { + private static final long serialVersionUID = 5946026822169837291L; + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + boolean result = size > MAX_SIZE; + if (result) { +// new Exception().printStackTrace(); + VolatileImageProviderImpl impl = eldest.getKey(); + size -= impl.w*impl.h; + + //debug(impl, impl.imageId, cache.size(), oldSize, size, "cache full, dumping oldest"); + + flushImageRef(impl.imageRef); + impl.imageRef = null; + } + return result; + } + }; + + private static final void flushImageRef(Reference imageRef) { + if (imageRef != null) { + Image img = imageRef.get(); + imageRef.clear(); + if (img != null) + img.flush(); + } + } + + VolatileImageProvider create(int w, int h) { +// System.out.println("VolatileImageProvider.create(" + w + ", " + h + ")"); + VolatileImageProviderImpl result = new VolatileImageProviderImpl(w, h); + return result; + } + +}