Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/java2d/loops/GraphicsPrimitive.java
38918 views
/*1* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425/*26* @author Charlton Innovations, Inc.27*/2829package sun.java2d.loops;3031import java.awt.image.BufferedImage;32import java.awt.AlphaComposite;33import java.awt.Rectangle;34import sun.awt.image.BufImgSurfaceData;35import sun.java2d.SurfaceData;36import sun.java2d.pipe.Region;37import java.lang.reflect.Field;38import java.util.StringTokenizer;39import java.util.Iterator;40import java.util.HashMap;41import java.util.Map;42import java.io.PrintStream;43import java.io.OutputStream;44import java.io.FileOutputStream;45import java.io.FileNotFoundException;46import java.security.AccessController;47import java.security.PrivilegedAction;48import sun.security.action.GetPropertyAction;4950/**51* defines interface for primitives which can be placed into52* the graphic component manager framework53*/54public abstract class GraphicsPrimitive {5556protected static interface GeneralBinaryOp {57/**58* This method allows the setupGeneralBinaryOp method to set59* the converters into the General version of the Primitive.60*/61public void setPrimitives(Blit srcconverter,62Blit dstconverter,63GraphicsPrimitive genericop,64Blit resconverter);6566/**67* These 4 methods are implemented automatically for any68* GraphicsPrimitive. They are used by setupGeneralBinaryOp69* to retrieve the information needed to find the right70* converter primitives.71*/72public SurfaceType getSourceType();73public CompositeType getCompositeType();74public SurfaceType getDestType();75public String getSignature();76public int getPrimTypeID();77}7879protected static interface GeneralUnaryOp {80/**81* This method allows the setupGeneralUnaryOp method to set82* the converters into the General version of the Primitive.83*/84public void setPrimitives(Blit dstconverter,85GraphicsPrimitive genericop,86Blit resconverter);8788/**89* These 3 methods are implemented automatically for any90* GraphicsPrimitive. They are used by setupGeneralUnaryOp91* to retrieve the information needed to find the right92* converter primitives.93*/94public CompositeType getCompositeType();95public SurfaceType getDestType();96public String getSignature();97public int getPrimTypeID();98}99100/**101* INSTANCE DATA MEMBERS DESCRIBING CHARACTERISTICS OF THIS PRIMITIVE102**/103104// Making these be instance data members (instead of virtual methods105// overridden by subclasses) is actually cheaper, since each class106// is a singleton. As instance data members with final accessors,107// accesses can be inlined.108private String methodSignature;109private int uniqueID;110private static int unusedPrimID = 1;111112private SurfaceType sourceType;113private CompositeType compositeType;114private SurfaceType destType;115116private long pNativePrim; // Native blit loop info117118public synchronized static final int makePrimTypeID() {119if (unusedPrimID > 255) {120throw new InternalError("primitive id overflow");121}122return unusedPrimID++;123}124125public synchronized static final int makeUniqueID(int primTypeID,126SurfaceType src,127CompositeType cmp,128SurfaceType dst)129{130return (primTypeID << 24) |131(dst.getUniqueID() << 16) |132(cmp.getUniqueID() << 8) |133(src.getUniqueID());134}135136/**137* Create a new GraphicsPrimitive with all of the required138* descriptive information.139*/140protected GraphicsPrimitive(String methodSignature,141int primTypeID,142SurfaceType sourceType,143CompositeType compositeType,144SurfaceType destType)145{146this.methodSignature = methodSignature;147this.sourceType = sourceType;148this.compositeType = compositeType;149this.destType = destType;150151if(sourceType == null || compositeType == null || destType == null) {152this.uniqueID = primTypeID << 24;153} else {154this.uniqueID = GraphicsPrimitive.makeUniqueID(primTypeID,155sourceType,156compositeType,157destType);158}159}160161/**162* Create a new GraphicsPrimitive for native invocation163* with all of the required descriptive information.164*/165protected GraphicsPrimitive(long pNativePrim,166String methodSignature,167int primTypeID,168SurfaceType sourceType,169CompositeType compositeType,170SurfaceType destType)171{172this.pNativePrim = pNativePrim;173this.methodSignature = methodSignature;174this.sourceType = sourceType;175this.compositeType = compositeType;176this.destType = destType;177178if(sourceType == null || compositeType == null || destType == null) {179this.uniqueID = primTypeID << 24;180} else {181this.uniqueID = GraphicsPrimitive.makeUniqueID(primTypeID,182sourceType,183compositeType,184destType);185}186}187188/**189* METHODS TO DESCRIBE THE SURFACES PRIMITIVES190* CAN OPERATE ON AND THE FUNCTIONALITY THEY IMPLEMENT191**/192193/**194* Gets instance ID of this graphics primitive.195*196* Instance ID is comprised of four distinct ids (ORed together)197* that uniquely identify each instance of a GraphicsPrimitive198* object. The four ids making up instance ID are:199* 1. primitive id - identifier shared by all primitives of the200* same type (eg. all Blits have the same primitive id)201* 2. sourcetype id - identifies source surface type202* 3. desttype id - identifies destination surface type203* 4. compositetype id - identifies composite used204*205* @return instance ID206*/207public final int getUniqueID() {208return uniqueID;209}210211/**212*/213public final String getSignature() {214return methodSignature;215}216217/**218* Gets unique id for this GraphicsPrimitive type.219*220* This id is used to identify the TYPE of primitive (Blit vs. BlitBg)221* as opposed to INSTANCE of primitive.222*223* @return primitive ID224*/225public final int getPrimTypeID() {226return uniqueID >>> 24;227}228229/**230*/231public final long getNativePrim() {232return pNativePrim;233}234235/**236*/237public final SurfaceType getSourceType() {238return sourceType;239}240241/**242*/243public final CompositeType getCompositeType() {244return compositeType;245}246247/**248*/249public final SurfaceType getDestType() {250return destType;251}252253/**254* Return true if this primitive can be used for the given signature255* surfaces, and composite.256*257* @param signature The signature of the given operation. Must be258* == (not just .equals) the signature string given by the259* abstract class that declares the operation.260* @param srctype The surface type for the source of the operation261* @param comptype The composite type for the operation262* @param dsttype The surface type for the destination of the operation263*/264public final boolean satisfies(String signature,265SurfaceType srctype,266CompositeType comptype,267SurfaceType dsttype)268{269if (signature != methodSignature) {270return false;271}272while (true) {273if (srctype == null) {274return false;275}276if (srctype.equals(sourceType)) {277break;278}279srctype = srctype.getSuperType();280}281while (true) {282if (comptype == null) {283return false;284}285if (comptype.equals(compositeType)) {286break;287}288comptype = comptype.getSuperType();289}290while (true) {291if (dsttype == null) {292return false;293}294if (dsttype.equals(destType)) {295break;296}297dsttype = dsttype.getSuperType();298}299return true;300}301302//303// A version of satisfies used for regression testing304//305final boolean satisfiesSameAs(GraphicsPrimitive other) {306return (methodSignature == other.methodSignature &&307sourceType.equals(other.sourceType) &&308compositeType.equals(other.compositeType) &&309destType.equals(other.destType));310}311312public abstract GraphicsPrimitive makePrimitive(SurfaceType srctype,313CompositeType comptype,314SurfaceType dsttype);315316public abstract GraphicsPrimitive traceWrap();317318static HashMap traceMap;319320public static int traceflags;321public static String tracefile;322public static PrintStream traceout;323324public static final int TRACELOG = 1;325public static final int TRACETIMESTAMP = 2;326public static final int TRACECOUNTS = 4;327328static {329GetPropertyAction gpa = new GetPropertyAction("sun.java2d.trace");330String trace = AccessController.doPrivileged(gpa);331if (trace != null) {332boolean verbose = false;333int traceflags = 0;334StringTokenizer st = new StringTokenizer(trace, ",");335while (st.hasMoreTokens()) {336String tok = st.nextToken();337if (tok.equalsIgnoreCase("count")) {338traceflags |= GraphicsPrimitive.TRACECOUNTS;339} else if (tok.equalsIgnoreCase("log")) {340traceflags |= GraphicsPrimitive.TRACELOG;341} else if (tok.equalsIgnoreCase("timestamp")) {342traceflags |= GraphicsPrimitive.TRACETIMESTAMP;343} else if (tok.equalsIgnoreCase("verbose")) {344verbose = true;345} else if (tok.regionMatches(true, 0, "out:", 0, 4)) {346tracefile = tok.substring(4);347} else {348if (!tok.equalsIgnoreCase("help")) {349System.err.println("unrecognized token: "+tok);350}351System.err.println("usage: -Dsun.java2d.trace="+352"[log[,timestamp]],[count],"+353"[out:<filename>],[help],[verbose]");354}355}356if (verbose) {357System.err.print("GraphicsPrimitive logging ");358if ((traceflags & GraphicsPrimitive.TRACELOG) != 0) {359System.err.println("enabled");360System.err.print("GraphicsPrimitive timetamps ");361if ((traceflags & GraphicsPrimitive.TRACETIMESTAMP) != 0) {362System.err.println("enabled");363} else {364System.err.println("disabled");365}366} else {367System.err.println("[and timestamps] disabled");368}369System.err.print("GraphicsPrimitive invocation counts ");370if ((traceflags & GraphicsPrimitive.TRACECOUNTS) != 0) {371System.err.println("enabled");372} else {373System.err.println("disabled");374}375System.err.print("GraphicsPrimitive trace output to ");376if (tracefile == null) {377System.err.println("System.err");378} else {379System.err.println("file '"+tracefile+"'");380}381}382GraphicsPrimitive.traceflags = traceflags;383}384}385386public static boolean tracingEnabled() {387return (traceflags != 0);388}389390private static PrintStream getTraceOutputFile() {391if (traceout == null) {392if (tracefile != null) {393FileOutputStream o = AccessController.doPrivileged(394new PrivilegedAction<FileOutputStream>() {395public FileOutputStream run() {396try {397return new FileOutputStream(tracefile);398} catch (FileNotFoundException e) {399return null;400}401}402});403if (o != null) {404traceout = new PrintStream(o);405} else {406traceout = System.err;407}408} else {409traceout = System.err;410}411}412return traceout;413}414415public static class TraceReporter extends Thread {416public static void setShutdownHook() {417AccessController.doPrivileged(new PrivilegedAction<Void>() {418public Void run() {419TraceReporter t = new TraceReporter();420t.setContextClassLoader(null);421Runtime.getRuntime().addShutdownHook(t);422return null;423}424});425}426427public void run() {428PrintStream ps = getTraceOutputFile();429Iterator iterator = traceMap.entrySet().iterator();430long total = 0;431int numprims = 0;432while (iterator.hasNext()) {433Map.Entry me = (Map.Entry) iterator.next();434Object prim = me.getKey();435int[] count = (int[]) me.getValue();436if (count[0] == 1) {437ps.print("1 call to ");438} else {439ps.print(count[0]+" calls to ");440}441ps.println(prim);442numprims++;443total += count[0];444}445if (numprims == 0) {446ps.println("No graphics primitives executed");447} else if (numprims > 1) {448ps.println(total+" total calls to "+449numprims+" different primitives");450}451}452}453454public synchronized static void tracePrimitive(Object prim) {455if ((traceflags & TRACECOUNTS) != 0) {456if (traceMap == null) {457traceMap = new HashMap();458TraceReporter.setShutdownHook();459}460Object o = traceMap.get(prim);461if (o == null) {462o = new int[1];463traceMap.put(prim, o);464}465((int[]) o)[0]++;466}467if ((traceflags & TRACELOG) != 0) {468PrintStream ps = getTraceOutputFile();469if ((traceflags & TRACETIMESTAMP) != 0) {470ps.print(System.currentTimeMillis()+": ");471}472ps.println(prim);473}474}475476protected void setupGeneralBinaryOp(GeneralBinaryOp gbo) {477int primID = gbo.getPrimTypeID();478String methodSignature = gbo.getSignature();479SurfaceType srctype = gbo.getSourceType();480CompositeType comptype = gbo.getCompositeType();481SurfaceType dsttype = gbo.getDestType();482Blit convertsrc, convertdst, convertres;483GraphicsPrimitive performop;484485convertsrc = createConverter(srctype, SurfaceType.IntArgb);486performop = GraphicsPrimitiveMgr.locatePrim(primID,487SurfaceType.IntArgb,488comptype, dsttype);489if (performop != null) {490convertdst = null;491convertres = null;492} else {493performop = getGeneralOp(primID, comptype);494if (performop == null) {495throw new InternalError("Cannot construct general op for "+496methodSignature+" "+comptype);497}498convertdst = createConverter(dsttype, SurfaceType.IntArgb);499convertres = createConverter(SurfaceType.IntArgb, dsttype);500}501502gbo.setPrimitives(convertsrc, convertdst, performop, convertres);503}504505protected void setupGeneralUnaryOp(GeneralUnaryOp guo) {506int primID = guo.getPrimTypeID();507String methodSignature = guo.getSignature();508CompositeType comptype = guo.getCompositeType();509SurfaceType dsttype = guo.getDestType();510511Blit convertdst = createConverter(dsttype, SurfaceType.IntArgb);512GraphicsPrimitive performop = getGeneralOp(primID, comptype);513Blit convertres = createConverter(SurfaceType.IntArgb, dsttype);514if (convertdst == null || performop == null || convertres == null) {515throw new InternalError("Cannot construct binary op for "+516comptype+" "+dsttype);517}518519guo.setPrimitives(convertdst, performop, convertres);520}521522protected static Blit createConverter(SurfaceType srctype,523SurfaceType dsttype)524{525if (srctype.equals(dsttype)) {526return null;527}528Blit cv = Blit.getFromCache(srctype, CompositeType.SrcNoEa, dsttype);529if (cv == null) {530throw new InternalError("Cannot construct converter for "+531srctype+"=>"+dsttype);532}533return cv;534}535536protected static SurfaceData convertFrom(Blit ob, SurfaceData srcData,537int srcX, int srcY, int w, int h,538SurfaceData dstData)539{540return convertFrom(ob, srcData,541srcX, srcY, w, h, dstData,542BufferedImage.TYPE_INT_ARGB);543}544545protected static SurfaceData convertFrom(Blit ob, SurfaceData srcData,546int srcX, int srcY, int w, int h,547SurfaceData dstData, int type)548{549if (dstData != null) {550Rectangle r = dstData.getBounds();551if (w > r.width || h > r.height) {552dstData = null;553}554}555if (dstData == null) {556BufferedImage dstBI = new BufferedImage(w, h, type);557dstData = BufImgSurfaceData.createData(dstBI);558}559ob.Blit(srcData, dstData, AlphaComposite.Src, null,560srcX, srcY, 0, 0, w, h);561return dstData;562}563564protected static void convertTo(Blit ob,565SurfaceData srcImg, SurfaceData dstImg,566Region clip,567int dstX, int dstY, int w, int h)568{569if (ob != null) {570ob.Blit(srcImg, dstImg, AlphaComposite.Src, clip,5710, 0, dstX, dstY, w, h);572}573}574575protected static GraphicsPrimitive getGeneralOp(int primID,576CompositeType comptype)577{578return GraphicsPrimitiveMgr.locatePrim(primID,579SurfaceType.IntArgb,580comptype,581SurfaceType.IntArgb);582}583584public static String simplename(Field[] fields, Object o) {585for (int i = 0; i < fields.length; i++) {586Field f = fields[i];587try {588if (o == f.get(null)) {589return f.getName();590}591} catch (Exception e) {592}593}594return "\""+o.toString()+"\"";595}596597public static String simplename(SurfaceType st) {598return simplename(SurfaceType.class.getDeclaredFields(), st);599}600601public static String simplename(CompositeType ct) {602return simplename(CompositeType.class.getDeclaredFields(), ct);603}604605private String cachedname;606607public String toString() {608if (cachedname == null) {609String sig = methodSignature;610int index = sig.indexOf('(');611if (index >= 0) {612sig = sig.substring(0, index);613}614cachedname = (getClass().getName()+"::"+615sig+"("+616simplename(sourceType)+", "+617simplename(compositeType)+", "+618simplename(destType)+")");619}620return cachedname;621}622}623624625