/* * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package sun.awt.image;import java.awt.Color;import java.awt.GraphicsEnvironment;import java.awt.GraphicsConfiguration;import java.awt.Image;import java.awt.ImageCapabilities;import java.awt.image.BufferedImage;import java.util.concurrent.ConcurrentHashMap;import java.util.Iterator;import sun.java2d.SurfaceData;import sun.java2d.SurfaceDataProxy;import sun.java2d.loops.CompositeType;/** * The abstract base class that manages the various SurfaceData objects that * represent an Image's contents. Subclasses can customize how the surfaces * are organized, whether to cache the original contents in an accelerated * surface, and so on. * <p> * The SurfaceManager also maintains an arbitrary "cache" mechanism which * allows other agents to store data in it specific to their use of this * image. The most common use of the caching mechanism is for destination * SurfaceData objects to store cached copies of the source image. */public abstract class SurfaceManager { public static abstract class ImageAccessor { public abstract SurfaceManager getSurfaceManager(Image img); public abstract void setSurfaceManager(Image img, SurfaceManager mgr); } private static ImageAccessor imgaccessor; public static void setImageAccessor(ImageAccessor ia) { if (imgaccessor != null) { throw new InternalError("Attempt to set ImageAccessor twice"); } imgaccessor = ia; } /** * Returns the SurfaceManager object contained within the given Image. */ public static SurfaceManager getManager(Image img) { SurfaceManager sMgr = imgaccessor.getSurfaceManager(img); if (sMgr == null) { /* * In practice only a BufferedImage will get here. */ try { BufferedImage bi = (BufferedImage) img; sMgr = new BufImgSurfaceManager(bi); setManager(bi, sMgr); } catch (ClassCastException e) { throw new IllegalArgumentException("Invalid Image variant"); } } return sMgr; } public static void setManager(Image img, SurfaceManager mgr) { imgaccessor.setSurfaceManager(img, mgr); } private ConcurrentHashMap cacheMap; /** * Return an arbitrary cached object for an arbitrary cache key. * Other objects can use this mechanism to store cached data about * the source image that will let them save time when using or * manipulating the image in the future. * <p> * Note that the cache is maintained as a simple Map with no * attempts to keep it up to date or invalidate it so any data * stored here must either not be dependent on the state of the * image or it must be individually tracked to see if it is * outdated or obsolete. * <p> * The SurfaceData object of the primary (destination) surface * has a StateTracker mechanism which can help track the validity * and "currentness" of any data stored here. * For convenience and expediency an object stored as cached * data may implement the FlushableCacheData interface specified * below so that it may be notified immediately if the flush() * method is ever called. */ public Object getCacheData(Object key) { return (cacheMap == null) ? null : cacheMap.get(key); } /** * Store an arbitrary cached object for an arbitrary cache key. * See the getCacheData() method for notes on tracking the * validity of data stored using this mechanism. */ public void setCacheData(Object key, Object value) { if (cacheMap == null) { synchronized (this) { if (cacheMap == null) { cacheMap = new ConcurrentHashMap(2); } } } cacheMap.put(key, value); } /** * Returns the main SurfaceData object that "owns" the pixels for * this SurfaceManager. This SurfaceData is used as the destination * surface in a rendering operation and is the most authoritative * storage for the current state of the pixels, though other * versions might be cached in other locations for efficiency. */ public abstract SurfaceData getPrimarySurfaceData(); /** * Restores the primary surface being managed, and then returns the * replacement surface. This is called when an accelerated surface has * been "lost", in an attempt to auto-restore its contents. */ public abstract SurfaceData restoreContents(); /** * Notification that any accelerated surfaces associated with this manager * have been "lost", which might mean that they need to be manually * restored or recreated. * * The default implementation does nothing, but platform-specific * variants which have accelerated surfaces should perform any necessary * actions. */ public void acceleratedSurfaceLost() {} /** * Returns an ImageCapabilities object which can be * inquired as to the specific capabilities of this * Image. The capabilities object will return true for * isAccelerated() if the image has a current and valid * SurfaceDataProxy object cached for the specified * GraphicsConfiguration parameter. * <p> * This class provides a default implementation of the * ImageCapabilities that will try to determine if there * is an associated SurfaceDataProxy object and if it is * up to date, but only works for GraphicsConfiguration * objects which implement the ProxiedGraphicsConfig * interface defined below. In practice, all configs * which can be accelerated are currently implementing * that interface. * <p> * A null GraphicsConfiguration returns a value based on whether the * image is currently accelerated on its default GraphicsConfiguration. * * @see java.awt.Image#getCapabilities * @since 1.5 */ public ImageCapabilities getCapabilities(GraphicsConfiguration gc) { return new ImageCapabilitiesGc(gc); } class ImageCapabilitiesGc extends ImageCapabilities { GraphicsConfiguration gc; public ImageCapabilitiesGc(GraphicsConfiguration gc) { super(false); this.gc = gc; } public boolean isAccelerated() { // Note that when img.getAccelerationPriority() gets set to 0 // we remove SurfaceDataProxy objects from the cache and the // answer will be false. GraphicsConfiguration tmpGc = gc; if (tmpGc == null) { tmpGc = GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().getDefaultConfiguration(); } if (tmpGc instanceof ProxiedGraphicsConfig) { Object proxyKey = ((ProxiedGraphicsConfig) tmpGc).getProxyKey(); if (proxyKey != null) { SurfaceDataProxy sdp = (SurfaceDataProxy) getCacheData(proxyKey); return (sdp != null && sdp.isAccelerated()); } } return false; } } /** * An interface for GraphicsConfiguration objects to implement if * their surfaces accelerate images using SurfaceDataProxy objects. * * Implementing this interface facilitates the default * implementation of getImageCapabilities() above. */ public static interface ProxiedGraphicsConfig { /** * Return the key that destination surfaces created on the * given GraphicsConfiguration use to store SurfaceDataProxy * objects for their cached copies. */ public Object getProxyKey(); } /** * Releases system resources in use by ancillary SurfaceData objects, * such as surfaces cached in accelerated memory. Subclasses should * override to release any of their flushable data. * <p> * The default implementation will visit all of the value objects * in the cacheMap and flush them if they implement the * FlushableCacheData interface. */ public synchronized void flush() { flush(false); } synchronized void flush(boolean deaccelerate) { if (cacheMap != null) { Iterator i = cacheMap.values().iterator(); while (i.hasNext()) { Object o = i.next(); if (o instanceof FlushableCacheData) { if (((FlushableCacheData) o).flush(deaccelerate)) { i.remove(); } } } } } /** * An interface for Objects used in the SurfaceManager cache * to implement if they have data that should be flushed when * the Image is flushed. */ public static interface FlushableCacheData { /** * Flush all cached resources. * The deaccelerated parameter indicates if the flush is * happening because the associated surface is no longer * being accelerated (for instance the acceleration priority * is set below the threshold needed for acceleration). * Returns a boolean that indicates if the cached object is * no longer needed and should be removed from the cache. */ public boolean flush(boolean deaccelerated); } /** * Called when image's acceleration priority is changed. * <p> * The default implementation will visit all of the value objects * in the cacheMap when the priority gets set to 0.0 and flush them * if they implement the FlushableCacheData interface. */ public void setAccelerationPriority(float priority) { if (priority == 0.0f) { flush(true); } }}
/*
* Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.awt.image;
import java.awt.Color;
import java.awt.GraphicsEnvironment;
import java.awt.GraphicsConfiguration;
import java.awt.Image;
import java.awt.ImageCapabilities;
import java.awt.image.BufferedImage;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Iterator;
import sun.java2d.SurfaceData;
import sun.java2d.SurfaceDataProxy;
import sun.java2d.loops.CompositeType;
/**
* The abstract base class that manages the various SurfaceData objects that
* represent an Image's contents. Subclasses can customize how the surfaces
* are organized, whether to cache the original contents in an accelerated
* surface, and so on.
* <p>
* The SurfaceManager also maintains an arbitrary "cache" mechanism which
* allows other agents to store data in it specific to their use of this
* image. The most common use of the caching mechanism is for destination
* SurfaceData objects to store cached copies of the source image.
*/
public abstract class SurfaceManager {
public static abstract class ImageAccessor {
public abstract SurfaceManager getSurfaceManager(Image img);
public abstract void setSurfaceManager(Image img, SurfaceManager mgr);
}
private static ImageAccessor imgaccessor;
public static void setImageAccessor(ImageAccessor ia) {
if (imgaccessor != null) {
throw new InternalError("Attempt to set ImageAccessor twice");
}
imgaccessor = ia;
}
/**
* Returns the SurfaceManager object contained within the given Image.
*/
public static SurfaceManager getManager(Image img) {
SurfaceManager sMgr = imgaccessor.getSurfaceManager(img);
if (sMgr == null) {
/*
* In practice only a BufferedImage will get here.
*/
try {
BufferedImage bi = (BufferedImage) img;
sMgr = new BufImgSurfaceManager(bi);
setManager(bi, sMgr);
} catch (ClassCastException e) {
throw new IllegalArgumentException("Invalid Image variant");
}
}
return sMgr;
}
public static void setManager(Image img, SurfaceManager mgr) {
imgaccessor.setSurfaceManager(img, mgr);
}
private ConcurrentHashMap cacheMap;
/**
* Return an arbitrary cached object for an arbitrary cache key.
* Other objects can use this mechanism to store cached data about
* the source image that will let them save time when using or
* manipulating the image in the future.
* <p>
* Note that the cache is maintained as a simple Map with no
* attempts to keep it up to date or invalidate it so any data
* stored here must either not be dependent on the state of the
* image or it must be individually tracked to see if it is
* outdated or obsolete.
* <p>
* The SurfaceData object of the primary (destination) surface
* has a StateTracker mechanism which can help track the validity
* and "currentness" of any data stored here.
* For convenience and expediency an object stored as cached
* data may implement the FlushableCacheData interface specified
* below so that it may be notified immediately if the flush()
* method is ever called.
*/
public Object getCacheData(Object key) {
return (cacheMap == null) ? null : cacheMap.get(key);
}
/**
* Store an arbitrary cached object for an arbitrary cache key.
* See the getCacheData() method for notes on tracking the
* validity of data stored using this mechanism.
*/
public void setCacheData(Object key, Object value) {
if (cacheMap == null) {
synchronized (this) {
if (cacheMap == null) {
cacheMap = new ConcurrentHashMap(2);
}
}
}
cacheMap.put(key, value);
}
/**
* Returns the main SurfaceData object that "owns" the pixels for
* this SurfaceManager. This SurfaceData is used as the destination
* surface in a rendering operation and is the most authoritative
* storage for the current state of the pixels, though other
* versions might be cached in other locations for efficiency.
*/
public abstract SurfaceData getPrimarySurfaceData();
/**
* Restores the primary surface being managed, and then returns the
* replacement surface. This is called when an accelerated surface has
* been "lost", in an attempt to auto-restore its contents.
*/
public abstract SurfaceData restoreContents();
/**
* Notification that any accelerated surfaces associated with this manager
* have been "lost", which might mean that they need to be manually
* restored or recreated.
*
* The default implementation does nothing, but platform-specific
* variants which have accelerated surfaces should perform any necessary
* actions.
*/
public void acceleratedSurfaceLost() {}
/**
* Returns an ImageCapabilities object which can be
* inquired as to the specific capabilities of this
* Image. The capabilities object will return true for
* isAccelerated() if the image has a current and valid
* SurfaceDataProxy object cached for the specified
* GraphicsConfiguration parameter.
* <p>
* This class provides a default implementation of the
* ImageCapabilities that will try to determine if there
* is an associated SurfaceDataProxy object and if it is
* up to date, but only works for GraphicsConfiguration
* objects which implement the ProxiedGraphicsConfig
* interface defined below. In practice, all configs
* which can be accelerated are currently implementing
* that interface.
* <p>
* A null GraphicsConfiguration returns a value based on whether the
* image is currently accelerated on its default GraphicsConfiguration.
*
* @see java.awt.Image#getCapabilities
* @since 1.5
*/
public ImageCapabilities getCapabilities(GraphicsConfiguration gc) {
return new ImageCapabilitiesGc(gc);
}
class ImageCapabilitiesGc extends ImageCapabilities {
GraphicsConfiguration gc;
public ImageCapabilitiesGc(GraphicsConfiguration gc) {
super(false);
this.gc = gc;
}
public boolean isAccelerated() {
// Note that when img.getAccelerationPriority() gets set to 0
// we remove SurfaceDataProxy objects from the cache and the
// answer will be false.
GraphicsConfiguration tmpGc = gc;
if (tmpGc == null) {
tmpGc = GraphicsEnvironment.getLocalGraphicsEnvironment().
getDefaultScreenDevice().getDefaultConfiguration();
}
if (tmpGc instanceof ProxiedGraphicsConfig) {
Object proxyKey =
((ProxiedGraphicsConfig) tmpGc).getProxyKey();
if (proxyKey != null) {
SurfaceDataProxy sdp =
(SurfaceDataProxy) getCacheData(proxyKey);
return (sdp != null && sdp.isAccelerated());
}
}
return false;
}
}
/**
* An interface for GraphicsConfiguration objects to implement if
* their surfaces accelerate images using SurfaceDataProxy objects.
*
* Implementing this interface facilitates the default
* implementation of getImageCapabilities() above.
*/
public static interface ProxiedGraphicsConfig {
/**
* Return the key that destination surfaces created on the
* given GraphicsConfiguration use to store SurfaceDataProxy
* objects for their cached copies.
*/
public Object getProxyKey();
}
/**
* Releases system resources in use by ancillary SurfaceData objects,
* such as surfaces cached in accelerated memory. Subclasses should
* override to release any of their flushable data.
* <p>
* The default implementation will visit all of the value objects
* in the cacheMap and flush them if they implement the
* FlushableCacheData interface.
*/
public synchronized void flush() {
flush(false);
}
synchronized void flush(boolean deaccelerate) {
if (cacheMap != null) {
Iterator i = cacheMap.values().iterator();
while (i.hasNext()) {
Object o = i.next();
if (o instanceof FlushableCacheData) {
if (((FlushableCacheData) o).flush(deaccelerate)) {
i.remove();
}
}
}
}
}
/**
* An interface for Objects used in the SurfaceManager cache
* to implement if they have data that should be flushed when
* the Image is flushed.
*/
public static interface FlushableCacheData {
/**
* Flush all cached resources.
* The deaccelerated parameter indicates if the flush is
* happening because the associated surface is no longer
* being accelerated (for instance the acceleration priority
* is set below the threshold needed for acceleration).
* Returns a boolean that indicates if the cached object is
* no longer needed and should be removed from the cache.
*/
public boolean flush(boolean deaccelerated);
}
/**
* Called when image's acceleration priority is changed.
* <p>
* The default implementation will visit all of the value objects
* in the cacheMap when the priority gets set to 0.0 and flush them
* if they implement the FlushableCacheData interface.
*/
public void setAccelerationPriority(float priority) {
if (priority == 0.0f) {
flush(true);
}
}
}