|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
|
|
/* |
|
* @author Charlton Innovations, Inc. |
|
*/ |
|
|
|
package sun.java2d.loops; |
|
|
|
import java.awt.image.BufferedImage; |
|
import java.awt.AlphaComposite; |
|
import java.awt.Rectangle; |
|
import sun.awt.image.BufImgSurfaceData; |
|
import sun.java2d.SurfaceData; |
|
import sun.java2d.pipe.Region; |
|
import java.lang.reflect.Field; |
|
import java.util.StringTokenizer; |
|
import java.util.Iterator; |
|
import java.util.HashMap; |
|
import java.util.Map; |
|
import java.io.PrintStream; |
|
import java.io.OutputStream; |
|
import java.io.FileOutputStream; |
|
import java.io.FileNotFoundException; |
|
import java.security.AccessController; |
|
import java.security.PrivilegedAction; |
|
import sun.security.action.GetPropertyAction; |
|
|
|
|
|
|
|
|
|
*/ |
|
public abstract class GraphicsPrimitive { |
|
|
|
protected static interface GeneralBinaryOp { |
|
|
|
|
|
|
|
*/ |
|
public void setPrimitives(Blit srcconverter, |
|
Blit dstconverter, |
|
GraphicsPrimitive genericop, |
|
Blit resconverter); |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public SurfaceType getSourceType(); |
|
public CompositeType getCompositeType(); |
|
public SurfaceType getDestType(); |
|
public String getSignature(); |
|
public int getPrimTypeID(); |
|
} |
|
|
|
protected static interface GeneralUnaryOp { |
|
|
|
|
|
|
|
*/ |
|
public void setPrimitives(Blit dstconverter, |
|
GraphicsPrimitive genericop, |
|
Blit resconverter); |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public CompositeType getCompositeType(); |
|
public SurfaceType getDestType(); |
|
public String getSignature(); |
|
public int getPrimTypeID(); |
|
} |
|
|
|
/** |
|
* INSTANCE DATA MEMBERS DESCRIBING CHARACTERISTICS OF THIS PRIMITIVE |
|
**/ |
|
|
|
// Making these be instance data members (instead of virtual methods |
|
// overridden by subclasses) is actually cheaper, since each class |
|
// is a singleton. As instance data members with final accessors, |
|
|
|
private String methodSignature; |
|
private int uniqueID; |
|
private static int unusedPrimID = 1; |
|
|
|
private SurfaceType sourceType; |
|
private CompositeType compositeType; |
|
private SurfaceType destType; |
|
|
|
private long pNativePrim; |
|
|
|
public synchronized static final int makePrimTypeID() { |
|
if (unusedPrimID > 255) { |
|
throw new InternalError("primitive id overflow"); |
|
} |
|
return unusedPrimID++; |
|
} |
|
|
|
public synchronized static final int makeUniqueID(int primTypeID, |
|
SurfaceType src, |
|
CompositeType cmp, |
|
SurfaceType dst) |
|
{ |
|
return (primTypeID << 24) | |
|
(dst.getUniqueID() << 16) | |
|
(cmp.getUniqueID() << 8) | |
|
(src.getUniqueID()); |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
protected GraphicsPrimitive(String methodSignature, |
|
int primTypeID, |
|
SurfaceType sourceType, |
|
CompositeType compositeType, |
|
SurfaceType destType) |
|
{ |
|
this.methodSignature = methodSignature; |
|
this.sourceType = sourceType; |
|
this.compositeType = compositeType; |
|
this.destType = destType; |
|
|
|
if(sourceType == null || compositeType == null || destType == null) { |
|
this.uniqueID = primTypeID << 24; |
|
} else { |
|
this.uniqueID = GraphicsPrimitive.makeUniqueID(primTypeID, |
|
sourceType, |
|
compositeType, |
|
destType); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
protected GraphicsPrimitive(long pNativePrim, |
|
String methodSignature, |
|
int primTypeID, |
|
SurfaceType sourceType, |
|
CompositeType compositeType, |
|
SurfaceType destType) |
|
{ |
|
this.pNativePrim = pNativePrim; |
|
this.methodSignature = methodSignature; |
|
this.sourceType = sourceType; |
|
this.compositeType = compositeType; |
|
this.destType = destType; |
|
|
|
if(sourceType == null || compositeType == null || destType == null) { |
|
this.uniqueID = primTypeID << 24; |
|
} else { |
|
this.uniqueID = GraphicsPrimitive.makeUniqueID(primTypeID, |
|
sourceType, |
|
compositeType, |
|
destType); |
|
} |
|
} |
|
|
|
/** |
|
* METHODS TO DESCRIBE THE SURFACES PRIMITIVES |
|
* CAN OPERATE ON AND THE FUNCTIONALITY THEY IMPLEMENT |
|
**/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final int getUniqueID() { |
|
return uniqueID; |
|
} |
|
|
|
|
|
*/ |
|
public final String getSignature() { |
|
return methodSignature; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final int getPrimTypeID() { |
|
return uniqueID >>> 24; |
|
} |
|
|
|
|
|
*/ |
|
public final long getNativePrim() { |
|
return pNativePrim; |
|
} |
|
|
|
|
|
*/ |
|
public final SurfaceType getSourceType() { |
|
return sourceType; |
|
} |
|
|
|
|
|
*/ |
|
public final CompositeType getCompositeType() { |
|
return compositeType; |
|
} |
|
|
|
|
|
*/ |
|
public final SurfaceType getDestType() { |
|
return destType; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public final boolean satisfies(String signature, |
|
SurfaceType srctype, |
|
CompositeType comptype, |
|
SurfaceType dsttype) |
|
{ |
|
if (signature != methodSignature) { |
|
return false; |
|
} |
|
while (true) { |
|
if (srctype == null) { |
|
return false; |
|
} |
|
if (srctype.equals(sourceType)) { |
|
break; |
|
} |
|
srctype = srctype.getSuperType(); |
|
} |
|
while (true) { |
|
if (comptype == null) { |
|
return false; |
|
} |
|
if (comptype.equals(compositeType)) { |
|
break; |
|
} |
|
comptype = comptype.getSuperType(); |
|
} |
|
while (true) { |
|
if (dsttype == null) { |
|
return false; |
|
} |
|
if (dsttype.equals(destType)) { |
|
break; |
|
} |
|
dsttype = dsttype.getSuperType(); |
|
} |
|
return true; |
|
} |
|
|
|
// |
|
// A version of satisfies used for regression testing |
|
|
|
final boolean satisfiesSameAs(GraphicsPrimitive other) { |
|
return (methodSignature == other.methodSignature && |
|
sourceType.equals(other.sourceType) && |
|
compositeType.equals(other.compositeType) && |
|
destType.equals(other.destType)); |
|
} |
|
|
|
public abstract GraphicsPrimitive makePrimitive(SurfaceType srctype, |
|
CompositeType comptype, |
|
SurfaceType dsttype); |
|
|
|
public abstract GraphicsPrimitive traceWrap(); |
|
|
|
static HashMap traceMap; |
|
|
|
public static int traceflags; |
|
public static String tracefile; |
|
public static PrintStream traceout; |
|
|
|
public static final int TRACELOG = 1; |
|
public static final int TRACETIMESTAMP = 2; |
|
public static final int TRACECOUNTS = 4; |
|
|
|
static { |
|
GetPropertyAction gpa = new GetPropertyAction("sun.java2d.trace"); |
|
String trace = AccessController.doPrivileged(gpa); |
|
if (trace != null) { |
|
boolean verbose = false; |
|
int traceflags = 0; |
|
StringTokenizer st = new StringTokenizer(trace, ","); |
|
while (st.hasMoreTokens()) { |
|
String tok = st.nextToken(); |
|
if (tok.equalsIgnoreCase("count")) { |
|
traceflags |= GraphicsPrimitive.TRACECOUNTS; |
|
} else if (tok.equalsIgnoreCase("log")) { |
|
traceflags |= GraphicsPrimitive.TRACELOG; |
|
} else if (tok.equalsIgnoreCase("timestamp")) { |
|
traceflags |= GraphicsPrimitive.TRACETIMESTAMP; |
|
} else if (tok.equalsIgnoreCase("verbose")) { |
|
verbose = true; |
|
} else if (tok.regionMatches(true, 0, "out:", 0, 4)) { |
|
tracefile = tok.substring(4); |
|
} else { |
|
if (!tok.equalsIgnoreCase("help")) { |
|
System.err.println("unrecognized token: "+tok); |
|
} |
|
System.err.println("usage: -Dsun.java2d.trace="+ |
|
"[log[,timestamp]],[count],"+ |
|
"[out:<filename>],[help],[verbose]"); |
|
} |
|
} |
|
if (verbose) { |
|
System.err.print("GraphicsPrimitive logging "); |
|
if ((traceflags & GraphicsPrimitive.TRACELOG) != 0) { |
|
System.err.println("enabled"); |
|
System.err.print("GraphicsPrimitive timetamps "); |
|
if ((traceflags & GraphicsPrimitive.TRACETIMESTAMP) != 0) { |
|
System.err.println("enabled"); |
|
} else { |
|
System.err.println("disabled"); |
|
} |
|
} else { |
|
System.err.println("[and timestamps] disabled"); |
|
} |
|
System.err.print("GraphicsPrimitive invocation counts "); |
|
if ((traceflags & GraphicsPrimitive.TRACECOUNTS) != 0) { |
|
System.err.println("enabled"); |
|
} else { |
|
System.err.println("disabled"); |
|
} |
|
System.err.print("GraphicsPrimitive trace output to "); |
|
if (tracefile == null) { |
|
System.err.println("System.err"); |
|
} else { |
|
System.err.println("file '"+tracefile+"'"); |
|
} |
|
} |
|
GraphicsPrimitive.traceflags = traceflags; |
|
} |
|
} |
|
|
|
public static boolean tracingEnabled() { |
|
return (traceflags != 0); |
|
} |
|
|
|
private static PrintStream getTraceOutputFile() { |
|
if (traceout == null) { |
|
if (tracefile != null) { |
|
FileOutputStream o = AccessController.doPrivileged( |
|
new PrivilegedAction<FileOutputStream>() { |
|
public FileOutputStream run() { |
|
try { |
|
return new FileOutputStream(tracefile); |
|
} catch (FileNotFoundException e) { |
|
return null; |
|
} |
|
} |
|
}); |
|
if (o != null) { |
|
traceout = new PrintStream(o); |
|
} else { |
|
traceout = System.err; |
|
} |
|
} else { |
|
traceout = System.err; |
|
} |
|
} |
|
return traceout; |
|
} |
|
|
|
public static class TraceReporter extends Thread { |
|
public static void setShutdownHook() { |
|
AccessController.doPrivileged(new PrivilegedAction<Void>() { |
|
public Void run() { |
|
TraceReporter t = new TraceReporter(); |
|
t.setContextClassLoader(null); |
|
Runtime.getRuntime().addShutdownHook(t); |
|
return null; |
|
} |
|
}); |
|
} |
|
|
|
public void run() { |
|
PrintStream ps = getTraceOutputFile(); |
|
Iterator iterator = traceMap.entrySet().iterator(); |
|
long total = 0; |
|
int numprims = 0; |
|
while (iterator.hasNext()) { |
|
Map.Entry me = (Map.Entry) iterator.next(); |
|
Object prim = me.getKey(); |
|
int[] count = (int[]) me.getValue(); |
|
if (count[0] == 1) { |
|
ps.print("1 call to "); |
|
} else { |
|
ps.print(count[0]+" calls to "); |
|
} |
|
ps.println(prim); |
|
numprims++; |
|
total += count[0]; |
|
} |
|
if (numprims == 0) { |
|
ps.println("No graphics primitives executed"); |
|
} else if (numprims > 1) { |
|
ps.println(total+" total calls to "+ |
|
numprims+" different primitives"); |
|
} |
|
} |
|
} |
|
|
|
public synchronized static void tracePrimitive(Object prim) { |
|
if ((traceflags & TRACECOUNTS) != 0) { |
|
if (traceMap == null) { |
|
traceMap = new HashMap(); |
|
TraceReporter.setShutdownHook(); |
|
} |
|
Object o = traceMap.get(prim); |
|
if (o == null) { |
|
o = new int[1]; |
|
traceMap.put(prim, o); |
|
} |
|
((int[]) o)[0]++; |
|
} |
|
if ((traceflags & TRACELOG) != 0) { |
|
PrintStream ps = getTraceOutputFile(); |
|
if ((traceflags & TRACETIMESTAMP) != 0) { |
|
ps.print(System.currentTimeMillis()+": "); |
|
} |
|
ps.println(prim); |
|
} |
|
} |
|
|
|
protected void setupGeneralBinaryOp(GeneralBinaryOp gbo) { |
|
int primID = gbo.getPrimTypeID(); |
|
String methodSignature = gbo.getSignature(); |
|
SurfaceType srctype = gbo.getSourceType(); |
|
CompositeType comptype = gbo.getCompositeType(); |
|
SurfaceType dsttype = gbo.getDestType(); |
|
Blit convertsrc, convertdst, convertres; |
|
GraphicsPrimitive performop; |
|
|
|
convertsrc = createConverter(srctype, SurfaceType.IntArgb); |
|
performop = GraphicsPrimitiveMgr.locatePrim(primID, |
|
SurfaceType.IntArgb, |
|
comptype, dsttype); |
|
if (performop != null) { |
|
convertdst = null; |
|
convertres = null; |
|
} else { |
|
performop = getGeneralOp(primID, comptype); |
|
if (performop == null) { |
|
throw new InternalError("Cannot construct general op for "+ |
|
methodSignature+" "+comptype); |
|
} |
|
convertdst = createConverter(dsttype, SurfaceType.IntArgb); |
|
convertres = createConverter(SurfaceType.IntArgb, dsttype); |
|
} |
|
|
|
gbo.setPrimitives(convertsrc, convertdst, performop, convertres); |
|
} |
|
|
|
protected void setupGeneralUnaryOp(GeneralUnaryOp guo) { |
|
int primID = guo.getPrimTypeID(); |
|
String methodSignature = guo.getSignature(); |
|
CompositeType comptype = guo.getCompositeType(); |
|
SurfaceType dsttype = guo.getDestType(); |
|
|
|
Blit convertdst = createConverter(dsttype, SurfaceType.IntArgb); |
|
GraphicsPrimitive performop = getGeneralOp(primID, comptype); |
|
Blit convertres = createConverter(SurfaceType.IntArgb, dsttype); |
|
if (convertdst == null || performop == null || convertres == null) { |
|
throw new InternalError("Cannot construct binary op for "+ |
|
comptype+" "+dsttype); |
|
} |
|
|
|
guo.setPrimitives(convertdst, performop, convertres); |
|
} |
|
|
|
protected static Blit createConverter(SurfaceType srctype, |
|
SurfaceType dsttype) |
|
{ |
|
if (srctype.equals(dsttype)) { |
|
return null; |
|
} |
|
Blit cv = Blit.getFromCache(srctype, CompositeType.SrcNoEa, dsttype); |
|
if (cv == null) { |
|
throw new InternalError("Cannot construct converter for "+ |
|
srctype+"=>"+dsttype); |
|
} |
|
return cv; |
|
} |
|
|
|
protected static SurfaceData convertFrom(Blit ob, SurfaceData srcData, |
|
int srcX, int srcY, int w, int h, |
|
SurfaceData dstData) |
|
{ |
|
return convertFrom(ob, srcData, |
|
srcX, srcY, w, h, dstData, |
|
BufferedImage.TYPE_INT_ARGB); |
|
} |
|
|
|
protected static SurfaceData convertFrom(Blit ob, SurfaceData srcData, |
|
int srcX, int srcY, int w, int h, |
|
SurfaceData dstData, int type) |
|
{ |
|
if (dstData != null) { |
|
Rectangle r = dstData.getBounds(); |
|
if (w > r.width || h > r.height) { |
|
dstData = null; |
|
} |
|
} |
|
if (dstData == null) { |
|
BufferedImage dstBI = new BufferedImage(w, h, type); |
|
dstData = BufImgSurfaceData.createData(dstBI); |
|
} |
|
ob.Blit(srcData, dstData, AlphaComposite.Src, null, |
|
srcX, srcY, 0, 0, w, h); |
|
return dstData; |
|
} |
|
|
|
protected static void convertTo(Blit ob, |
|
SurfaceData srcImg, SurfaceData dstImg, |
|
Region clip, |
|
int dstX, int dstY, int w, int h) |
|
{ |
|
if (ob != null) { |
|
ob.Blit(srcImg, dstImg, AlphaComposite.Src, clip, |
|
0, 0, dstX, dstY, w, h); |
|
} |
|
} |
|
|
|
protected static GraphicsPrimitive getGeneralOp(int primID, |
|
CompositeType comptype) |
|
{ |
|
return GraphicsPrimitiveMgr.locatePrim(primID, |
|
SurfaceType.IntArgb, |
|
comptype, |
|
SurfaceType.IntArgb); |
|
} |
|
|
|
public static String simplename(Field[] fields, Object o) { |
|
for (int i = 0; i < fields.length; i++) { |
|
Field f = fields[i]; |
|
try { |
|
if (o == f.get(null)) { |
|
return f.getName(); |
|
} |
|
} catch (Exception e) { |
|
} |
|
} |
|
return "\""+o.toString()+"\""; |
|
} |
|
|
|
public static String simplename(SurfaceType st) { |
|
return simplename(SurfaceType.class.getDeclaredFields(), st); |
|
} |
|
|
|
public static String simplename(CompositeType ct) { |
|
return simplename(CompositeType.class.getDeclaredFields(), ct); |
|
} |
|
|
|
private String cachedname; |
|
|
|
public String toString() { |
|
if (cachedname == null) { |
|
String sig = methodSignature; |
|
int index = sig.indexOf('('); |
|
if (index >= 0) { |
|
sig = sig.substring(0, index); |
|
} |
|
cachedname = (getClass().getName()+"::"+ |
|
sig+"("+ |
|
simplename(sourceType)+", "+ |
|
simplename(compositeType)+", "+ |
|
simplename(destType)+")"); |
|
} |
|
return cachedname; |
|
} |
|
} |