001: /*
002: * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.awt.image;
027:
028: import java.awt.Color;
029: import java.awt.GraphicsEnvironment;
030: import java.awt.GraphicsConfiguration;
031: import java.awt.Image;
032: import java.awt.ImageCapabilities;
033: import java.awt.image.BufferedImage;
034: import java.util.concurrent.ConcurrentHashMap;
035: import java.util.Iterator;
036: import sun.java2d.SurfaceData;
037: import sun.java2d.SurfaceDataProxy;
038: import sun.java2d.loops.CompositeType;
039:
040: /**
041: * The abstract base class that manages the various SurfaceData objects that
042: * represent an Image's contents. Subclasses can customize how the surfaces
043: * are organized, whether to cache the original contents in an accelerated
044: * surface, and so on.
045: * <p>
046: * The SurfaceManager also maintains an arbitrary "cache" mechanism which
047: * allows other agents to store data in it specific to their use of this
048: * image. The most common use of the caching mechanism is for destination
049: * SurfaceData objects to store cached copies of the source image.
050: */
051: public abstract class SurfaceManager {
052:
053: public static abstract class ImageAccessor {
054: public abstract SurfaceManager getSurfaceManager(Image img);
055:
056: public abstract void setSurfaceManager(Image img,
057: SurfaceManager mgr);
058: }
059:
060: private static ImageAccessor imgaccessor;
061:
062: public static void setImageAccessor(ImageAccessor ia) {
063: if (imgaccessor != null) {
064: throw new InternalError(
065: "Attempt to set ImageAccessor twice");
066: }
067: imgaccessor = ia;
068: }
069:
070: /**
071: * Returns the SurfaceManager object contained within the given Image.
072: */
073: public static SurfaceManager getManager(Image img) {
074: SurfaceManager sMgr = imgaccessor.getSurfaceManager(img);
075: if (sMgr == null) {
076: /*
077: * In practice only a BufferedImage will get here.
078: */
079: try {
080: BufferedImage bi = (BufferedImage) img;
081: sMgr = new BufImgSurfaceManager(bi);
082: setManager(bi, sMgr);
083: } catch (ClassCastException e) {
084: throw new IllegalArgumentException(
085: "Invalid Image variant");
086: }
087: }
088: return sMgr;
089: }
090:
091: public static void setManager(Image img, SurfaceManager mgr) {
092: imgaccessor.setSurfaceManager(img, mgr);
093: }
094:
095: private ConcurrentHashMap cacheMap;
096:
097: /**
098: * Return an arbitrary cached object for an arbitrary cache key.
099: * Other objects can use this mechanism to store cached data about
100: * the source image that will let them save time when using or
101: * manipulating the image in the future.
102: * <p>
103: * Note that the cache is maintained as a simple Map with no
104: * attempts to keep it up to date or invalidate it so any data
105: * stored here must either not be dependent on the state of the
106: * image or it must be individually tracked to see if it is
107: * outdated or obsolete.
108: * <p>
109: * The SurfaceData object of the primary (destination) surface
110: * has a StateTracker mechanism which can help track the validity
111: * and "currentness" of any data stored here.
112: * For convenience and expediency an object stored as cached
113: * data may implement the FlushableCacheData interface specified
114: * below so that it may be notified immediately if the flush()
115: * method is ever called.
116: */
117: public Object getCacheData(Object key) {
118: return (cacheMap == null) ? null : cacheMap.get(key);
119: }
120:
121: /**
122: * Store an arbitrary cached object for an arbitrary cache key.
123: * See the getCacheData() method for notes on tracking the
124: * validity of data stored using this mechanism.
125: */
126: public void setCacheData(Object key, Object value) {
127: if (cacheMap == null) {
128: synchronized (this ) {
129: if (cacheMap == null) {
130: cacheMap = new ConcurrentHashMap(2);
131: }
132: }
133: }
134: cacheMap.put(key, value);
135: }
136:
137: /**
138: * Returns the main SurfaceData object that "owns" the pixels for
139: * this SurfaceManager. This SurfaceData is used as the destination
140: * surface in a rendering operation and is the most authoritative
141: * storage for the current state of the pixels, though other
142: * versions might be cached in other locations for efficiency.
143: */
144: public abstract SurfaceData getPrimarySurfaceData();
145:
146: /**
147: * Restores the primary surface being managed, and then returns the
148: * replacement surface. This is called when an accelerated surface has
149: * been "lost", in an attempt to auto-restore its contents.
150: */
151: public abstract SurfaceData restoreContents();
152:
153: /**
154: * Notification that any accelerated surfaces associated with this manager
155: * have been "lost", which might mean that they need to be manually
156: * restored or recreated.
157: *
158: * The default implementation does nothing, but platform-specific
159: * variants which have accelerated surfaces should perform any necessary
160: * actions.
161: */
162: public void acceleratedSurfaceLost() {
163: }
164:
165: /**
166: * Returns an ImageCapabilities object which can be
167: * inquired as to the specific capabilities of this
168: * Image. The capabilities object will return true for
169: * isAccelerated() if the image has a current and valid
170: * SurfaceDataProxy object cached for the specified
171: * GraphicsConfiguration parameter.
172: * <p>
173: * This class provides a default implementation of the
174: * ImageCapabilities that will try to determine if there
175: * is an associated SurfaceDataProxy object and if it is
176: * up to date, but only works for GraphicsConfiguration
177: * objects which implement the ProxiedGraphicsConfig
178: * interface defined below. In practice, all configs
179: * which can be accelerated are currently implementing
180: * that interface.
181: * <p>
182: * A null GraphicsConfiguration returns a value based on whether the
183: * image is currently accelerated on its default GraphicsConfiguration.
184: *
185: * @see java.awt.Image#getCapabilities
186: * @since 1.5
187: */
188: public ImageCapabilities getCapabilities(GraphicsConfiguration gc) {
189: return new ImageCapabilitiesGc(gc);
190: }
191:
192: class ImageCapabilitiesGc extends ImageCapabilities {
193: GraphicsConfiguration gc;
194:
195: public ImageCapabilitiesGc(GraphicsConfiguration gc) {
196: super (false);
197: this .gc = gc;
198: }
199:
200: public boolean isAccelerated() {
201: // Note that when img.getAccelerationPriority() gets set to 0
202: // we remove SurfaceDataProxy objects from the cache and the
203: // answer will be false.
204: GraphicsConfiguration tmpGc = gc;
205: if (tmpGc == null) {
206: tmpGc = GraphicsEnvironment
207: .getLocalGraphicsEnvironment()
208: .getDefaultScreenDevice()
209: .getDefaultConfiguration();
210: }
211: if (tmpGc instanceof ProxiedGraphicsConfig) {
212: Object proxyKey = ((ProxiedGraphicsConfig) tmpGc)
213: .getProxyKey();
214: if (proxyKey != null) {
215: SurfaceDataProxy sdp = (SurfaceDataProxy) getCacheData(proxyKey);
216: return (sdp != null && sdp.isAccelerated());
217: }
218: }
219: return false;
220: }
221: }
222:
223: /**
224: * An interface for GraphicsConfiguration objects to implement if
225: * their surfaces accelerate images using SurfaceDataProxy objects.
226: *
227: * Implementing this interface facilitates the default
228: * implementation of getImageCapabilities() above.
229: */
230: public static interface ProxiedGraphicsConfig {
231: /**
232: * Return the key that destination surfaces created on the
233: * given GraphicsConfiguration use to store SurfaceDataProxy
234: * objects for their cached copies.
235: */
236: public Object getProxyKey();
237: }
238:
239: /**
240: * Releases system resources in use by ancillary SurfaceData objects,
241: * such as surfaces cached in accelerated memory. Subclasses should
242: * override to release any of their flushable data.
243: * <p>
244: * The default implementation will visit all of the value objects
245: * in the cacheMap and flush them if they implement the
246: * FlushableCacheData interface.
247: */
248: public synchronized void flush() {
249: flush(false);
250: }
251:
252: synchronized void flush(boolean deaccelerate) {
253: if (cacheMap != null) {
254: Iterator i = cacheMap.values().iterator();
255: while (i.hasNext()) {
256: Object o = i.next();
257: if (o instanceof FlushableCacheData) {
258: if (((FlushableCacheData) o).flush(deaccelerate)) {
259: i.remove();
260: }
261: }
262: }
263: }
264: }
265:
266: /**
267: * An interface for Objects used in the SurfaceManager cache
268: * to implement if they have data that should be flushed when
269: * the Image is flushed.
270: */
271: public static interface FlushableCacheData {
272: /**
273: * Flush all cached resources.
274: * The deaccelerated parameter indicates if the flush is
275: * happening because the associated surface is no longer
276: * being accelerated (for instance the acceleration priority
277: * is set below the threshold needed for acceleration).
278: * Returns a boolean that indicates if the cached object is
279: * no longer needed and should be removed from the cache.
280: */
281: public boolean flush(boolean deaccelerated);
282: }
283:
284: /**
285: * Called when image's acceleration priority is changed.
286: * <p>
287: * The default implementation will visit all of the value objects
288: * in the cacheMap when the priority gets set to 0.0 and flush them
289: * if they implement the FlushableCacheData interface.
290: */
291: public void setAccelerationPriority(float priority) {
292: if (priority == 0.0f) {
293: flush(true);
294: }
295: }
296: }
|