001: /*
002: * Copyright 1997-2005 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: /*
027: * @author Charlton Innovations, Inc.
028: */
029:
030: package sun.java2d.loops;
031:
032: import java.awt.image.BufferedImage;
033: import java.awt.AlphaComposite;
034: import java.awt.Rectangle;
035: import sun.awt.image.BufImgSurfaceData;
036: import sun.java2d.SurfaceData;
037: import sun.java2d.pipe.Region;
038: import java.lang.reflect.Field;
039: import java.util.StringTokenizer;
040: import java.util.Iterator;
041: import java.util.HashMap;
042: import java.util.Map;
043: import java.io.PrintStream;
044: import java.io.OutputStream;
045: import java.io.FileOutputStream;
046: import java.io.FileNotFoundException;
047: import java.security.AccessController;
048: import java.security.PrivilegedAction;
049: import sun.security.action.GetPropertyAction;
050:
051: /**
052: * defines interface for primitives which can be placed into
053: * the graphic component manager framework
054: */
055: public abstract class GraphicsPrimitive {
056:
057: protected static interface GeneralBinaryOp {
058: /**
059: * This method allows the setupGeneralBinaryOp method to set
060: * the converters into the General version of the Primitive.
061: */
062: public void setPrimitives(Blit srcconverter, Blit dstconverter,
063: GraphicsPrimitive genericop, Blit resconverter);
064:
065: /**
066: * These 4 methods are implemented automatically for any
067: * GraphicsPrimitive. They are used by setupGeneralBinaryOp
068: * to retrieve the information needed to find the right
069: * converter primitives.
070: */
071: public SurfaceType getSourceType();
072:
073: public CompositeType getCompositeType();
074:
075: public SurfaceType getDestType();
076:
077: public String getSignature();
078:
079: public int getPrimTypeID();
080: }
081:
082: protected static interface GeneralUnaryOp {
083: /**
084: * This method allows the setupGeneralUnaryOp method to set
085: * the converters into the General version of the Primitive.
086: */
087: public void setPrimitives(Blit dstconverter,
088: GraphicsPrimitive genericop, Blit resconverter);
089:
090: /**
091: * These 3 methods are implemented automatically for any
092: * GraphicsPrimitive. They are used by setupGeneralUnaryOp
093: * to retrieve the information needed to find the right
094: * converter primitives.
095: */
096: public CompositeType getCompositeType();
097:
098: public SurfaceType getDestType();
099:
100: public String getSignature();
101:
102: public int getPrimTypeID();
103: }
104:
105: /**
106: * INSTANCE DATA MEMBERS DESCRIBING CHARACTERISTICS OF THIS PRIMITIVE
107: **/
108:
109: // Making these be instance data members (instead of virtual methods
110: // overridden by subclasses) is actually cheaper, since each class
111: // is a singleton. As instance data members with final accessors,
112: // accesses can be inlined.
113: private String methodSignature;
114: private int uniqueID;
115: private static int unusedPrimID = 1;
116:
117: private SurfaceType sourceType;
118: private CompositeType compositeType;
119: private SurfaceType destType;
120:
121: private long pNativePrim; // Native blit loop info
122:
123: public synchronized static final int makePrimTypeID() {
124: if (unusedPrimID > 255) {
125: throw new InternalError("primitive id overflow");
126: }
127: return unusedPrimID++;
128: }
129:
130: public synchronized static final int makeUniqueID(int primTypeID,
131: SurfaceType src, CompositeType cmp, SurfaceType dst) {
132: return (primTypeID << 24) | (dst.getUniqueID() << 16)
133: | (cmp.getUniqueID() << 8) | (src.getUniqueID());
134: }
135:
136: /**
137: * Create a new GraphicsPrimitive with all of the required
138: * descriptive information.
139: */
140: protected GraphicsPrimitive(String methodSignature, int primTypeID,
141: SurfaceType sourceType, CompositeType compositeType,
142: SurfaceType destType) {
143: this .methodSignature = methodSignature;
144: this .sourceType = sourceType;
145: this .compositeType = compositeType;
146: this .destType = destType;
147:
148: if (sourceType == null || compositeType == null
149: || destType == null) {
150: this .uniqueID = primTypeID << 24;
151: } else {
152: this .uniqueID = GraphicsPrimitive.makeUniqueID(primTypeID,
153: sourceType, compositeType, destType);
154: }
155: }
156:
157: /**
158: * Create a new GraphicsPrimitive for native invocation
159: * with all of the required descriptive information.
160: */
161: protected GraphicsPrimitive(long pNativePrim,
162: String methodSignature, int primTypeID,
163: SurfaceType sourceType, CompositeType compositeType,
164: SurfaceType destType) {
165: this .pNativePrim = pNativePrim;
166: this .methodSignature = methodSignature;
167: this .sourceType = sourceType;
168: this .compositeType = compositeType;
169: this .destType = destType;
170:
171: if (sourceType == null || compositeType == null
172: || destType == null) {
173: this .uniqueID = primTypeID << 24;
174: } else {
175: this .uniqueID = GraphicsPrimitive.makeUniqueID(primTypeID,
176: sourceType, compositeType, destType);
177: }
178: }
179:
180: /**
181: * METHODS TO DESCRIBE THE SURFACES PRIMITIVES
182: * CAN OPERATE ON AND THE FUNCTIONALITY THEY IMPLEMENT
183: **/
184:
185: /**
186: * Gets instance ID of this graphics primitive.
187: *
188: * Instance ID is comprised of four distinct ids (ORed together)
189: * that uniquely identify each instance of a GraphicsPrimitive
190: * object. The four ids making up instance ID are:
191: * 1. primitive id - identifier shared by all primitives of the
192: * same type (eg. all Blits have the same primitive id)
193: * 2. sourcetype id - identifies source surface type
194: * 3. desttype id - identifies destination surface type
195: * 4. compositetype id - identifies composite used
196: *
197: * @return instance ID
198: */
199: public final int getUniqueID() {
200: return uniqueID;
201: }
202:
203: /**
204: */
205: public final String getSignature() {
206: return methodSignature;
207: }
208:
209: /**
210: * Gets unique id for this GraphicsPrimitive type.
211: *
212: * This id is used to identify the TYPE of primitive (Blit vs. BlitBg)
213: * as opposed to INSTANCE of primitive.
214: *
215: * @return primitive ID
216: */
217: public final int getPrimTypeID() {
218: return uniqueID >>> 24;
219: }
220:
221: /**
222: */
223: public final long getNativePrim() {
224: return pNativePrim;
225: }
226:
227: /**
228: */
229: public final SurfaceType getSourceType() {
230: return sourceType;
231: }
232:
233: /**
234: */
235: public final CompositeType getCompositeType() {
236: return compositeType;
237: }
238:
239: /**
240: */
241: public final SurfaceType getDestType() {
242: return destType;
243: }
244:
245: /**
246: * Return true if this primitive can be used for the given signature
247: * surfaces, and composite.
248: *
249: * @param signature The signature of the given operation. Must be
250: * == (not just .equals) the signature string given by the
251: * abstract class that declares the operation.
252: * @param srctype The surface type for the source of the operation
253: * @param comptype The composite type for the operation
254: * @param dsttype The surface type for the destination of the operation
255: */
256: public final boolean satisfies(String signature,
257: SurfaceType srctype, CompositeType comptype,
258: SurfaceType dsttype) {
259: if (signature != methodSignature) {
260: return false;
261: }
262: while (true) {
263: if (srctype == null) {
264: return false;
265: }
266: if (srctype.equals(sourceType)) {
267: break;
268: }
269: srctype = srctype.getSuperType();
270: }
271: while (true) {
272: if (comptype == null) {
273: return false;
274: }
275: if (comptype.equals(compositeType)) {
276: break;
277: }
278: comptype = comptype.getSuperType();
279: }
280: while (true) {
281: if (dsttype == null) {
282: return false;
283: }
284: if (dsttype.equals(destType)) {
285: break;
286: }
287: dsttype = dsttype.getSuperType();
288: }
289: return true;
290: }
291:
292: //
293: // A version of satisfies used for regression testing
294: //
295: final boolean satisfiesSameAs(GraphicsPrimitive other) {
296: return (methodSignature == other.methodSignature
297: && sourceType.equals(other.sourceType)
298: && compositeType.equals(other.compositeType) && destType
299: .equals(other.destType));
300: }
301:
302: public abstract GraphicsPrimitive makePrimitive(
303: SurfaceType srctype, CompositeType comptype,
304: SurfaceType dsttype);
305:
306: public abstract GraphicsPrimitive traceWrap();
307:
308: static HashMap traceMap;
309:
310: public static int traceflags;
311: public static String tracefile;
312: public static PrintStream traceout;
313:
314: public static final int TRACELOG = 1;
315: public static final int TRACETIMESTAMP = 2;
316: public static final int TRACECOUNTS = 4;
317:
318: static {
319: GetPropertyAction gpa = new GetPropertyAction(
320: "sun.java2d.trace");
321: String trace = (String) AccessController.doPrivileged(gpa);
322: if (trace != null) {
323: boolean verbose = false;
324: int traceflags = 0;
325: StringTokenizer st = new StringTokenizer(trace, ",");
326: while (st.hasMoreTokens()) {
327: String tok = st.nextToken();
328: if (tok.equalsIgnoreCase("count")) {
329: traceflags |= GraphicsPrimitive.TRACECOUNTS;
330: } else if (tok.equalsIgnoreCase("log")) {
331: traceflags |= GraphicsPrimitive.TRACELOG;
332: } else if (tok.equalsIgnoreCase("timestamp")) {
333: traceflags |= GraphicsPrimitive.TRACETIMESTAMP;
334: } else if (tok.equalsIgnoreCase("verbose")) {
335: verbose = true;
336: } else if (tok.regionMatches(true, 0, "out:", 0, 4)) {
337: tracefile = tok.substring(4);
338: } else {
339: if (!tok.equalsIgnoreCase("help")) {
340: System.err
341: .println("unrecognized token: " + tok);
342: }
343: System.err.println("usage: -Dsun.java2d.trace="
344: + "[log[,timestamp]],[count],"
345: + "[out:<filename>],[help],[verbose]");
346: }
347: }
348: if (verbose) {
349: System.err.print("GraphicsPrimitive logging ");
350: if ((traceflags & GraphicsPrimitive.TRACELOG) != 0) {
351: System.err.println("enabled");
352: System.err.print("GraphicsPrimitive timetamps ");
353: if ((traceflags & GraphicsPrimitive.TRACETIMESTAMP) != 0) {
354: System.err.println("enabled");
355: } else {
356: System.err.println("disabled");
357: }
358: } else {
359: System.err.println("[and timestamps] disabled");
360: }
361: System.err
362: .print("GraphicsPrimitive invocation counts ");
363: if ((traceflags & GraphicsPrimitive.TRACECOUNTS) != 0) {
364: System.err.println("enabled");
365: } else {
366: System.err.println("disabled");
367: }
368: System.err.print("GraphicsPrimitive trace output to ");
369: if (tracefile == null) {
370: System.err.println("System.err");
371: } else {
372: System.err.println("file '" + tracefile + "'");
373: }
374: }
375: GraphicsPrimitive.traceflags = traceflags;
376: }
377: }
378:
379: public static boolean tracingEnabled() {
380: return (traceflags != 0);
381: }
382:
383: private static PrintStream getTraceOutputFile() {
384: if (traceout == null) {
385: if (tracefile != null) {
386: Object o = AccessController
387: .doPrivileged(new PrivilegedAction() {
388: public Object run() {
389: try {
390: return new FileOutputStream(
391: tracefile);
392: } catch (FileNotFoundException e) {
393: return null;
394: }
395: }
396: });
397: if (o != null) {
398: traceout = new PrintStream((OutputStream) o);
399: } else {
400: traceout = System.err;
401: }
402: } else {
403: traceout = System.err;
404: }
405: }
406: return traceout;
407: }
408:
409: public static class TraceReporter extends Thread {
410: public static void setShutdownHook() {
411: AccessController.doPrivileged(new PrivilegedAction() {
412: public Object run() {
413: Runtime.getRuntime().addShutdownHook(
414: new TraceReporter());
415: return null;
416: }
417: });
418: }
419:
420: public void run() {
421: PrintStream ps = getTraceOutputFile();
422: Iterator iterator = traceMap.entrySet().iterator();
423: long total = 0;
424: int numprims = 0;
425: while (iterator.hasNext()) {
426: Map.Entry me = (Map.Entry) iterator.next();
427: Object prim = me.getKey();
428: int[] count = (int[]) me.getValue();
429: if (count[0] == 1) {
430: ps.print("1 call to ");
431: } else {
432: ps.print(count[0] + " calls to ");
433: }
434: ps.println(prim);
435: numprims++;
436: total += count[0];
437: }
438: if (numprims == 0) {
439: ps.println("No graphics primitives executed");
440: } else if (numprims > 1) {
441: ps.println(total + " total calls to " + numprims
442: + " different primitives");
443: }
444: }
445: }
446:
447: public synchronized static void tracePrimitive(Object prim) {
448: if ((traceflags & TRACECOUNTS) != 0) {
449: if (traceMap == null) {
450: traceMap = new HashMap();
451: TraceReporter.setShutdownHook();
452: }
453: Object o = traceMap.get(prim);
454: if (o == null) {
455: o = new int[1];
456: traceMap.put(prim, o);
457: }
458: ((int[]) o)[0]++;
459: }
460: if ((traceflags & TRACELOG) != 0) {
461: PrintStream ps = getTraceOutputFile();
462: if ((traceflags & TRACETIMESTAMP) != 0) {
463: ps.print(System.currentTimeMillis() + ": ");
464: }
465: ps.println(prim);
466: }
467: }
468:
469: protected void setupGeneralBinaryOp(GeneralBinaryOp gbo) {
470: int primID = gbo.getPrimTypeID();
471: String methodSignature = gbo.getSignature();
472: SurfaceType srctype = gbo.getSourceType();
473: CompositeType comptype = gbo.getCompositeType();
474: SurfaceType dsttype = gbo.getDestType();
475: Blit convertsrc, convertdst, convertres;
476: GraphicsPrimitive performop;
477:
478: convertsrc = createConverter(srctype, SurfaceType.IntArgb);
479: performop = GraphicsPrimitiveMgr.locatePrim(primID,
480: SurfaceType.IntArgb, comptype, dsttype);
481: if (performop != null) {
482: convertdst = null;
483: convertres = null;
484: } else {
485: performop = getGeneralOp(primID, comptype);
486: if (performop == null) {
487: throw new InternalError(
488: "Cannot construct general op for "
489: + methodSignature + " " + comptype);
490: }
491: convertdst = createConverter(dsttype, SurfaceType.IntArgb);
492: convertres = createConverter(SurfaceType.IntArgb, dsttype);
493: }
494:
495: gbo
496: .setPrimitives(convertsrc, convertdst, performop,
497: convertres);
498: }
499:
500: protected void setupGeneralUnaryOp(GeneralUnaryOp guo) {
501: int primID = guo.getPrimTypeID();
502: String methodSignature = guo.getSignature();
503: CompositeType comptype = guo.getCompositeType();
504: SurfaceType dsttype = guo.getDestType();
505:
506: Blit convertdst = createConverter(dsttype, SurfaceType.IntArgb);
507: GraphicsPrimitive performop = getGeneralOp(primID, comptype);
508: Blit convertres = createConverter(SurfaceType.IntArgb, dsttype);
509: if (convertdst == null || performop == null
510: || convertres == null) {
511: throw new InternalError("Cannot construct binary op for "
512: + comptype + " " + dsttype);
513: }
514:
515: guo.setPrimitives(convertdst, performop, convertres);
516: }
517:
518: protected static Blit createConverter(SurfaceType srctype,
519: SurfaceType dsttype) {
520: if (srctype.equals(dsttype)) {
521: return null;
522: }
523: Blit cv = Blit.getFromCache(srctype, CompositeType.SrcNoEa,
524: dsttype);
525: if (cv == null) {
526: throw new InternalError("Cannot construct converter for "
527: + srctype + "=>" + dsttype);
528: }
529: return cv;
530: }
531:
532: protected static SurfaceData convertFrom(Blit ob,
533: SurfaceData srcData, int srcX, int srcY, int w, int h,
534: SurfaceData dstData) {
535: return convertFrom(ob, srcData, srcX, srcY, w, h, dstData,
536: BufferedImage.TYPE_INT_ARGB);
537: }
538:
539: protected static SurfaceData convertFrom(Blit ob,
540: SurfaceData srcData, int srcX, int srcY, int w, int h,
541: SurfaceData dstData, int type) {
542: if (dstData != null) {
543: Rectangle r = dstData.getBounds();
544: if (w > r.width || h > r.height) {
545: dstData = null;
546: }
547: }
548: if (dstData == null) {
549: BufferedImage dstBI = new BufferedImage(w, h, type);
550: dstData = BufImgSurfaceData.createData(dstBI);
551: }
552: ob.Blit(srcData, dstData, AlphaComposite.Src, null, srcX, srcY,
553: 0, 0, w, h);
554: return dstData;
555: }
556:
557: protected static void convertTo(Blit ob, SurfaceData srcImg,
558: SurfaceData dstImg, Region clip, int dstX, int dstY, int w,
559: int h) {
560: if (ob != null) {
561: ob.Blit(srcImg, dstImg, AlphaComposite.Src, clip, 0, 0,
562: dstX, dstY, w, h);
563: }
564: }
565:
566: protected static GraphicsPrimitive getGeneralOp(int primID,
567: CompositeType comptype) {
568: return GraphicsPrimitiveMgr.locatePrim(primID,
569: SurfaceType.IntArgb, comptype, SurfaceType.IntArgb);
570: }
571:
572: public static String simplename(Field[] fields, Object o) {
573: for (int i = 0; i < fields.length; i++) {
574: Field f = fields[i];
575: try {
576: if (o == f.get(null)) {
577: return f.getName();
578: }
579: } catch (Exception e) {
580: }
581: }
582: return "\"" + o.toString() + "\"";
583: }
584:
585: public static String simplename(SurfaceType st) {
586: return simplename(SurfaceType.class.getDeclaredFields(), st);
587: }
588:
589: public static String simplename(CompositeType ct) {
590: return simplename(CompositeType.class.getDeclaredFields(), ct);
591: }
592:
593: private String cachedname;
594:
595: public String toString() {
596: if (cachedname == null) {
597: String sig = methodSignature;
598: int index = sig.indexOf('(');
599: if (index >= 0) {
600: sig = sig.substring(0, index);
601: }
602: cachedname = (getClass().getName() + "::" + sig + "("
603: + simplename(sourceType) + ", "
604: + simplename(compositeType) + ", "
605: + simplename(destType) + ")");
606: }
607: return cachedname;
608: }
609: }
|