blob: ad6295f150544789282f19f47b45971394aae3d5 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.awt.image;
27
28import java.awt.Color;
29import java.awt.GraphicsEnvironment;
30import java.awt.GraphicsConfiguration;
31import java.awt.Image;
32import java.awt.ImageCapabilities;
33import java.awt.image.BufferedImage;
34import java.util.concurrent.ConcurrentHashMap;
35import java.util.Iterator;
36import sun.java2d.SurfaceData;
37import sun.java2d.SurfaceDataProxy;
38import sun.java2d.loops.CompositeType;
39
40/**
41 * The abstract base class that manages the various SurfaceData objects that
42 * represent an Image's contents. Subclasses can customize how the surfaces
43 * are organized, whether to cache the original contents in an accelerated
44 * surface, and so on.
45 * <p>
46 * The SurfaceManager also maintains an arbitrary "cache" mechanism which
47 * allows other agents to store data in it specific to their use of this
48 * image. The most common use of the caching mechanism is for destination
49 * SurfaceData objects to store cached copies of the source image.
50 */
51public abstract class SurfaceManager {
52
53 public static abstract class ImageAccessor {
54 public abstract SurfaceManager getSurfaceManager(Image img);
55 public abstract void setSurfaceManager(Image img, SurfaceManager mgr);
56 }
57
58 private static ImageAccessor imgaccessor;
59
60 public static void setImageAccessor(ImageAccessor ia) {
61 if (imgaccessor != null) {
62 throw new InternalError("Attempt to set ImageAccessor twice");
63 }
64 imgaccessor = ia;
65 }
66
67 /**
68 * Returns the SurfaceManager object contained within the given Image.
69 */
70 public static SurfaceManager getManager(Image img) {
71 SurfaceManager sMgr = imgaccessor.getSurfaceManager(img);
72 if (sMgr == null) {
73 /*
74 * In practice only a BufferedImage will get here.
75 */
76 try {
77 BufferedImage bi = (BufferedImage) img;
78 sMgr = new BufImgSurfaceManager(bi);
79 setManager(bi, sMgr);
80 } catch (ClassCastException e) {
81 throw new IllegalArgumentException("Invalid Image variant");
82 }
83 }
84 return sMgr;
85 }
86
87 public static void setManager(Image img, SurfaceManager mgr) {
88 imgaccessor.setSurfaceManager(img, mgr);
89 }
90
91 private ConcurrentHashMap cacheMap;
92
93 /**
94 * Return an arbitrary cached object for an arbitrary cache key.
95 * Other objects can use this mechanism to store cached data about
96 * the source image that will let them save time when using or
97 * manipulating the image in the future.
98 * <p>
99 * Note that the cache is maintained as a simple Map with no
100 * attempts to keep it up to date or invalidate it so any data
101 * stored here must either not be dependent on the state of the
102 * image or it must be individually tracked to see if it is
103 * outdated or obsolete.
104 * <p>
105 * The SurfaceData object of the primary (destination) surface
106 * has a StateTracker mechanism which can help track the validity
107 * and "currentness" of any data stored here.
108 * For convenience and expediency an object stored as cached
109 * data may implement the FlushableCacheData interface specified
110 * below so that it may be notified immediately if the flush()
111 * method is ever called.
112 */
113 public Object getCacheData(Object key) {
114 return (cacheMap == null) ? null : cacheMap.get(key);
115 }
116
117 /**
118 * Store an arbitrary cached object for an arbitrary cache key.
119 * See the getCacheData() method for notes on tracking the
120 * validity of data stored using this mechanism.
121 */
122 public void setCacheData(Object key, Object value) {
123 if (cacheMap == null) {
124 synchronized (this) {
125 if (cacheMap == null) {
126 cacheMap = new ConcurrentHashMap(2);
127 }
128 }
129 }
130 cacheMap.put(key, value);
131 }
132
133 /**
134 * Returns the main SurfaceData object that "owns" the pixels for
135 * this SurfaceManager. This SurfaceData is used as the destination
136 * surface in a rendering operation and is the most authoritative
137 * storage for the current state of the pixels, though other
138 * versions might be cached in other locations for efficiency.
139 */
140 public abstract SurfaceData getPrimarySurfaceData();
141
142 /**
143 * Restores the primary surface being managed, and then returns the
144 * replacement surface. This is called when an accelerated surface has
145 * been "lost", in an attempt to auto-restore its contents.
146 */
147 public abstract SurfaceData restoreContents();
148
149 /**
150 * Notification that any accelerated surfaces associated with this manager
151 * have been "lost", which might mean that they need to be manually
152 * restored or recreated.
153 *
154 * The default implementation does nothing, but platform-specific
155 * variants which have accelerated surfaces should perform any necessary
156 * actions.
157 */
158 public void acceleratedSurfaceLost() {}
159
160 /**
161 * Returns an ImageCapabilities object which can be
162 * inquired as to the specific capabilities of this
163 * Image. The capabilities object will return true for
164 * isAccelerated() if the image has a current and valid
165 * SurfaceDataProxy object cached for the specified
166 * GraphicsConfiguration parameter.
167 * <p>
168 * This class provides a default implementation of the
169 * ImageCapabilities that will try to determine if there
170 * is an associated SurfaceDataProxy object and if it is
171 * up to date, but only works for GraphicsConfiguration
172 * objects which implement the ProxiedGraphicsConfig
173 * interface defined below. In practice, all configs
174 * which can be accelerated are currently implementing
175 * that interface.
176 * <p>
177 * A null GraphicsConfiguration returns a value based on whether the
178 * image is currently accelerated on its default GraphicsConfiguration.
179 *
180 * @see java.awt.Image#getCapabilities
181 * @since 1.5
182 */
183 public ImageCapabilities getCapabilities(GraphicsConfiguration gc) {
184 return new ImageCapabilitiesGc(gc);
185 }
186
187 class ImageCapabilitiesGc extends ImageCapabilities {
188 GraphicsConfiguration gc;
189
190 public ImageCapabilitiesGc(GraphicsConfiguration gc) {
191 super(false);
192 this.gc = gc;
193 }
194
195 public boolean isAccelerated() {
196 // Note that when img.getAccelerationPriority() gets set to 0
197 // we remove SurfaceDataProxy objects from the cache and the
198 // answer will be false.
199 GraphicsConfiguration tmpGc = gc;
200 if (tmpGc == null) {
201 tmpGc = GraphicsEnvironment.getLocalGraphicsEnvironment().
202 getDefaultScreenDevice().getDefaultConfiguration();
203 }
204 if (tmpGc instanceof ProxiedGraphicsConfig) {
205 Object proxyKey =
206 ((ProxiedGraphicsConfig) tmpGc).getProxyKey();
207 if (proxyKey != null) {
208 SurfaceDataProxy sdp =
209 (SurfaceDataProxy) getCacheData(proxyKey);
210 return (sdp != null && sdp.isAccelerated());
211 }
212 }
213 return false;
214 }
215 }
216
217 /**
218 * An interface for GraphicsConfiguration objects to implement if
219 * their surfaces accelerate images using SurfaceDataProxy objects.
220 *
221 * Implementing this interface facilitates the default
222 * implementation of getImageCapabilities() above.
223 */
224 public static interface ProxiedGraphicsConfig {
225 /**
226 * Return the key that destination surfaces created on the
227 * given GraphicsConfiguration use to store SurfaceDataProxy
228 * objects for their cached copies.
229 */
230 public Object getProxyKey();
231 }
232
233 /**
234 * Releases system resources in use by ancillary SurfaceData objects,
235 * such as surfaces cached in accelerated memory. Subclasses should
236 * override to release any of their flushable data.
237 * <p>
238 * The default implementation will visit all of the value objects
239 * in the cacheMap and flush them if they implement the
240 * FlushableCacheData interface.
241 */
242 public synchronized void flush() {
243 flush(false);
244 }
245
246 synchronized void flush(boolean deaccelerate) {
247 if (cacheMap != null) {
248 Iterator i = cacheMap.values().iterator();
249 while (i.hasNext()) {
250 Object o = i.next();
251 if (o instanceof FlushableCacheData) {
252 if (((FlushableCacheData) o).flush(deaccelerate)) {
253 i.remove();
254 }
255 }
256 }
257 }
258 }
259
260 /**
261 * An interface for Objects used in the SurfaceManager cache
262 * to implement if they have data that should be flushed when
263 * the Image is flushed.
264 */
265 public static interface FlushableCacheData {
266 /**
267 * Flush all cached resources.
268 * The deaccelerated parameter indicates if the flush is
269 * happening because the associated surface is no longer
270 * being accelerated (for instance the acceleration priority
271 * is set below the threshold needed for acceleration).
272 * Returns a boolean that indicates if the cached object is
273 * no longer needed and should be removed from the cache.
274 */
275 public boolean flush(boolean deaccelerated);
276 }
277
278 /**
279 * Called when image's acceleration priority is changed.
280 * <p>
281 * The default implementation will visit all of the value objects
282 * in the cacheMap when the priority gets set to 0.0 and flush them
283 * if they implement the FlushableCacheData interface.
284 */
285 public void setAccelerationPriority(float priority) {
286 if (priority == 0.0f) {
287 flush(true);
288 }
289 }
290}