Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/java2d/xr/XRSurfaceData.java
32288 views
/*1* Copyright (c) 2010, 2013, 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*/2425package sun.java2d.xr;2627import java.awt.*;28import java.awt.geom.*;29import java.awt.image.*;30import sun.awt.*;31import sun.java2d.InvalidPipeException;32import sun.java2d.SunGraphics2D;33import sun.java2d.SurfaceData;34import sun.java2d.SurfaceDataProxy;35import sun.java2d.jules.*;36import sun.java2d.loops.*;37import sun.java2d.pipe.*;38import sun.java2d.x11.*;39import sun.font.FontManagerNativeLibrary;4041public abstract class XRSurfaceData extends XSurfaceData {42X11ComponentPeer peer;43XRGraphicsConfig graphicsConfig;44XRBackend renderQueue;4546private RenderLoops solidloops;4748protected int depth;4950private static native void initIDs();5152protected native void XRInitSurface(int depth, int width, int height,53long drawable, int pictFormat);5455native void initXRPicture(long xsdo, int pictForm);5657native void freeXSDOPicture(long xsdo);5859public static final String DESC_BYTE_A8_X11 = "Byte A8 Pixmap";60public static final String DESC_INT_RGB_X11 = "Integer RGB Pixmap";61public static final String DESC_INT_ARGB_X11 = "Integer ARGB-Pre Pixmap";6263public static final SurfaceType64ByteA8X11 = SurfaceType.ByteGray.deriveSubType(DESC_BYTE_A8_X11);65public static final SurfaceType66IntRgbX11 = SurfaceType.IntRgb.deriveSubType(DESC_INT_RGB_X11);67public static final SurfaceType68IntArgbPreX11 = SurfaceType.IntArgbPre.deriveSubType(DESC_INT_ARGB_X11);6970public Raster getRaster(int x, int y, int w, int h) {71throw new InternalError("not implemented yet");72}7374protected XRRenderer xrpipe;75protected PixelToShapeConverter xrtxpipe;76protected TextPipe xrtextpipe;77protected XRDrawImage xrDrawImage;7879protected ShapeDrawPipe aaShapePipe;80protected PixelToShapeConverter aaPixelToShapeConv;8182public static void initXRSurfaceData() {83if (!isX11SurfaceDataInitialized()) {84FontManagerNativeLibrary.load();85initIDs();86XRPMBlitLoops.register();87XRMaskFill.register();88XRMaskBlit.register();8990setX11SurfaceDataInitialized();91}92}9394/**95* Synchronized accessor method for isDrawableValid.96*/97protected boolean isXRDrawableValid() {98try {99SunToolkit.awtLock();100return isDrawableValid();101} finally {102SunToolkit.awtUnlock();103}104}105106@Override107public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {108return XRSurfaceDataProxy.createProxy(srcData, graphicsConfig);109}110111@Override112public void validatePipe(SunGraphics2D sg2d) {113TextPipe textpipe;114boolean validated = false;115116/*117* The textpipe for now can't handle TexturePaint when extra-alpha is118* specified nore XOR mode119*/120if ((textpipe = getTextPipe(sg2d)) == null)121{122super.validatePipe(sg2d);123textpipe = sg2d.textpipe;124validated = true;125}126127PixelToShapeConverter txPipe = null;128XRRenderer nonTxPipe = null;129130/*131* TODO: Can we rely on the GC for ARGB32 surfaces?132*/133if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) {134if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {135if (sg2d.compositeState <= SunGraphics2D.COMP_XOR) {136txPipe = xrtxpipe;137nonTxPipe = xrpipe;138}139} else if (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) {140if (XRPaints.isValid(sg2d)) {141txPipe = xrtxpipe;142nonTxPipe = xrpipe;143}144// custom paints handled by super.validatePipe() below145}146}147148if (sg2d.antialiasHint == SunHints.INTVAL_ANTIALIAS_ON &&149JulesPathBuf.isCairoAvailable())150{151sg2d.shapepipe = aaShapePipe;152sg2d.drawpipe = aaPixelToShapeConv;153sg2d.fillpipe = aaPixelToShapeConv;154} else {155if (txPipe != null) {156if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {157sg2d.drawpipe = txPipe;158sg2d.fillpipe = txPipe;159} else if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) {160sg2d.drawpipe = txPipe;161sg2d.fillpipe = nonTxPipe;162} else {163sg2d.drawpipe = nonTxPipe;164sg2d.fillpipe = nonTxPipe;165}166sg2d.shapepipe = nonTxPipe;167} else {168if (!validated) {169super.validatePipe(sg2d);170}171}172}173174// install the text pipe based on our earlier decision175sg2d.textpipe = textpipe;176177// always override the image pipe with the specialized XRender pipe178sg2d.imagepipe = xrDrawImage;179}180181protected TextPipe getTextPipe(SunGraphics2D sg2d) {182boolean supportedPaint = sg2d.compositeState <= SunGraphics2D.COMP_ALPHA183&& (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR || sg2d.composite == null);184185boolean supportedCompOp = false;186if (sg2d.composite instanceof AlphaComposite) {187int compRule = ((AlphaComposite) sg2d.composite).getRule();188supportedCompOp = XRUtils.isMaskEvaluated(XRUtils.j2dAlphaCompToXR(compRule))189|| (compRule == AlphaComposite.SRC190&& sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR);191}192193return (supportedPaint && supportedCompOp) ? xrtextpipe : null;194}195196protected MaskFill getMaskFill(SunGraphics2D sg2d) {197AlphaComposite aComp = null;198if(sg2d.composite != null199&& sg2d.composite instanceof AlphaComposite) {200aComp = (AlphaComposite) sg2d.composite;201}202203boolean supportedPaint = sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR204|| XRPaints.isValid(sg2d);205206boolean supportedCompOp = false;207if(aComp != null) {208int rule = aComp.getRule();209supportedCompOp = XRUtils.isMaskEvaluated(XRUtils.j2dAlphaCompToXR(rule));210}211212return (supportedPaint && supportedCompOp) ? super.getMaskFill(sg2d) : null;213}214215public RenderLoops getRenderLoops(SunGraphics2D sg2d) {216if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&217sg2d.compositeState <= SunGraphics2D.COMP_ALPHA)218{219return solidloops;220}221222return super.getRenderLoops(sg2d);223}224225public GraphicsConfiguration getDeviceConfiguration() {226return graphicsConfig;227}228229/**230* Method for instantiating a Window SurfaceData231*/232public static XRWindowSurfaceData createData(X11ComponentPeer peer) {233XRGraphicsConfig gc = getGC(peer);234return new XRWindowSurfaceData(peer, gc, gc.getSurfaceType());235}236237/**238* Method for instantiating a Pixmap SurfaceData (offscreen).239* If the surface * is opaque a 24-bit/RGB surface is chosen,240* otherwise a 32-bit ARGB surface.241*/242public static XRPixmapSurfaceData createData(XRGraphicsConfig gc,243int width, int height,244ColorModel cm, Image image,245long drawable,246int transparency) {247int depth;248// If we have a 32 bit color model for the window it needs249// alpha to support translucency of the window so we need250// to upgrade what was requested for the surface.251if (gc.getColorModel().getPixelSize() == 32) {252depth = 32;253transparency = Transparency.TRANSLUCENT;254} else {255depth = transparency > Transparency.OPAQUE ? 32 : 24;256}257258if (depth == 24) {259cm = new DirectColorModel(depth,2600x00FF0000, 0x0000FF00, 0x000000FF);261} else {262cm = new DirectColorModel(depth, 0x00FF0000, 0x0000FF00,2630x000000FF, 0xFF000000);264}265266return new XRPixmapSurfaceData267(gc, width, height, image, getSurfaceType(gc, transparency),268cm, drawable, transparency,269XRUtils.getPictureFormatForTransparency(transparency), depth);270}271272protected XRSurfaceData(X11ComponentPeer peer, XRGraphicsConfig gc,273SurfaceType sType, ColorModel cm, int depth, int transparency)274{275super(sType, cm);276this.peer = peer;277this.graphicsConfig = gc;278this.solidloops = graphicsConfig.getSolidLoops(sType);279this.depth = depth;280initOps(peer, graphicsConfig, depth);281282setBlitProxyKey(gc.getProxyKey());283}284285protected XRSurfaceData(XRBackend renderQueue) {286super(XRSurfaceData.IntRgbX11,287new DirectColorModel(24, 0x00FF0000, 0x0000FF00, 0x000000FF));288this.renderQueue = renderQueue;289}290291/**292* Inits the XRender-data-structures which belong to the XRSurfaceData.293*294* @param pictureFormat295*/296public void initXRender(int pictureFormat) {297try {298SunToolkit.awtLock();299initXRPicture(getNativeOps(), pictureFormat);300renderQueue = XRCompositeManager.getInstance(this).getBackend();301maskBuffer = XRCompositeManager.getInstance(this);302} catch (Throwable ex) {303ex.printStackTrace();304} finally {305SunToolkit.awtUnlock();306}307}308309public static XRGraphicsConfig getGC(X11ComponentPeer peer) {310if (peer != null) {311return (XRGraphicsConfig) peer.getGraphicsConfiguration();312} else {313GraphicsEnvironment env =314GraphicsEnvironment.getLocalGraphicsEnvironment();315GraphicsDevice gd = env.getDefaultScreenDevice();316return (XRGraphicsConfig) gd.getDefaultConfiguration();317}318}319320/**321* Returns a boolean indicating whether or not a copyArea from the given322* rectangle source coordinates might be incomplete and result in X11323* GraphicsExposure events being generated from XCopyArea. This method324* allows the SurfaceData copyArea method to determine if it needs to set325* the GraphicsExposures attribute of the X11 GC to True or False to receive326* or avoid the events.327*328* @return true if there is any chance that an XCopyArea from the given329* source coordinates could produce any X11 Exposure events.330*/331public abstract boolean canSourceSendExposures(int x, int y, int w, int h);332333/**334* CopyArea is implemented using the "old" X11 GC, therefor clip and335* needExposures have to be validated against that GC. Pictures and GCs336* don't share state.337*/338public void validateCopyAreaGC(Region gcClip, boolean needExposures) {339if (validatedGCClip != gcClip) {340if (gcClip != null)341renderQueue.setGCClipRectangles(xgc, gcClip);342validatedGCClip = gcClip;343}344345if (validatedExposures != needExposures) {346validatedExposures = needExposures;347renderQueue.setGCExposures(xgc, needExposures);348}349350if (validatedXorComp != null) {351renderQueue.setGCMode(xgc, true);352renderQueue.setGCForeground(xgc, validatedGCForegroundPixel);353validatedXorComp = null;354}355}356357public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h,358int dx, int dy) {359if (xrpipe == null) {360if (!isXRDrawableValid()) {361return true;362}363makePipes();364}365CompositeType comptype = sg2d.imageComp;366if (sg2d.transformState < SunGraphics2D.TRANSFORM_TRANSLATESCALE &&367(CompositeType.SrcOverNoEa.equals(comptype) ||368CompositeType.SrcNoEa.equals(comptype)))369{370x += sg2d.transX;371y += sg2d.transY;372try {373SunToolkit.awtLock();374boolean needExposures = canSourceSendExposures(x, y, w, h);375validateCopyAreaGC(sg2d.getCompClip(), needExposures);376renderQueue.copyArea(xid, xid, xgc, x, y, w, h, x + dx, y + dy);377} finally {378SunToolkit.awtUnlock();379}380return true;381}382return false;383}384385/**386* Returns the XRender SurfaceType which is able to fullfill the specified387* transparency requirement.388*/389public static SurfaceType getSurfaceType(XRGraphicsConfig gc,390int transparency) {391SurfaceType sType = null;392393switch (transparency) {394case Transparency.OPAQUE:395sType = XRSurfaceData.IntRgbX11;396break;397398case Transparency.BITMASK:399case Transparency.TRANSLUCENT:400sType = XRSurfaceData.IntArgbPreX11;401break;402}403404return sType;405}406407public void invalidate() {408if (isValid()) {409setInvalid();410super.invalidate();411}412}413414private long xgc; // GC is still used for copyArea415private int validatedGCForegroundPixel = 0;416private XORComposite validatedXorComp;417private int xid;418public int picture;419public XRCompositeManager maskBuffer;420421private Region validatedClip;422private Region validatedGCClip;423private boolean validatedExposures = true;424425boolean transformInUse = false;426AffineTransform validatedSourceTransform = new AffineTransform();427AffineTransform staticSrcTx = null;428int validatedRepeat = XRUtils.RepeatNone;429int validatedFilter = XRUtils.FAST;430431/**432* Validates an XRSurfaceData when used as source. Note that the clip is433* applied when used as source as well as destination.434*/435void validateAsSource(AffineTransform sxForm, int repeat, int filter) {436437if (validatedClip != null) {438validatedClip = null;439renderQueue.setClipRectangles(picture, null);440}441442if (validatedRepeat != repeat && repeat != -1) {443validatedRepeat = repeat;444renderQueue.setPictureRepeat(picture, repeat);445}446447if (sxForm == null) {448if (transformInUse) {449validatedSourceTransform.setToIdentity();450renderQueue.setPictureTransform(picture,451validatedSourceTransform);452transformInUse = false;453}454} else if (!transformInUse ||455(transformInUse && !sxForm.equals(validatedSourceTransform))) {456457validatedSourceTransform.setTransform(sxForm.getScaleX(),458sxForm.getShearY(),459sxForm.getShearX(),460sxForm.getScaleY(),461sxForm.getTranslateX(),462sxForm.getTranslateY());463464AffineTransform srcTransform = validatedSourceTransform;465if(staticSrcTx != null) {466// Apply static transform set when used as texture or gradient.467// Create a copy to not modify validatedSourceTransform as468// this would confuse the validation logic.469srcTransform = new AffineTransform(validatedSourceTransform);470srcTransform.preConcatenate(staticSrcTx);471}472473renderQueue.setPictureTransform(picture, srcTransform);474transformInUse = true;475}476477if (filter != validatedFilter && filter != -1) {478renderQueue.setFilter(picture, filter);479validatedFilter = filter;480}481}482483/**484* Validates the Surface when used as destination.485*/486public void validateAsDestination(SunGraphics2D sg2d, Region clip) {487if (!isValid()) {488throw new InvalidPipeException("bounds changed");489}490491boolean updateGCClip = false;492if (clip != validatedClip) {493renderQueue.setClipRectangles(picture, clip);494validatedClip = clip;495updateGCClip = true;496}497498if (sg2d != null && sg2d.compositeState == SunGraphics2D.COMP_XOR) {499if (validatedXorComp != sg2d.getComposite()) {500validatedXorComp = (XORComposite) sg2d.getComposite();501renderQueue.setGCMode(xgc, false);502}503504// validate pixel505int pixel = sg2d.pixel;506if (validatedGCForegroundPixel != pixel) {507int xorpixelmod = validatedXorComp.getXorPixel();508renderQueue.setGCForeground(xgc, pixel ^ xorpixelmod);509validatedGCForegroundPixel = pixel;510}511512if (updateGCClip) {513renderQueue.setGCClipRectangles(xgc, clip);514}515}516}517518public synchronized void makePipes() { /*519* TODO: Why is this synchronized,520* but access not?521*/522if (xrpipe == null) {523try {524SunToolkit.awtLock();525xgc = XCreateGC(getNativeOps());526527xrpipe = new XRRenderer(maskBuffer.getMaskBuffer());528xrtxpipe = new PixelToShapeConverter(xrpipe);529xrtextpipe = maskBuffer.getTextRenderer();530xrDrawImage = new XRDrawImage();531532if (JulesPathBuf.isCairoAvailable()) {533aaShapePipe =534new JulesShapePipe(XRCompositeManager.getInstance(this));535aaPixelToShapeConv = new PixelToShapeConverter(aaShapePipe);536}537} finally {538SunToolkit.awtUnlock();539}540}541}542543public static class XRWindowSurfaceData extends XRSurfaceData {544public XRWindowSurfaceData(X11ComponentPeer peer,545XRGraphicsConfig gc, SurfaceType sType) {546super(peer, gc, sType, peer.getColorModel(),547peer.getColorModel().getPixelSize(), Transparency.OPAQUE);548549if (isXRDrawableValid()) {550initXRender(XRUtils.551getPictureFormatForTransparency(Transparency.OPAQUE));552makePipes();553}554}555556public SurfaceData getReplacement() {557return peer.getSurfaceData();558}559560public Rectangle getBounds() {561Rectangle r = peer.getBounds();562r.x = r.y = 0;563return r;564}565566@Override567public boolean canSourceSendExposures(int x, int y, int w, int h) {568return true;569}570571/**572* Returns destination Component associated with this SurfaceData.573*/574public Object getDestination() {575return peer.getTarget();576}577578public void invalidate() {579try {580SunToolkit.awtLock();581freeXSDOPicture(getNativeOps());582}finally {583SunToolkit.awtUnlock();584}585586super.invalidate();587}588}589590public static class XRInternalSurfaceData extends XRSurfaceData {591public XRInternalSurfaceData(XRBackend renderQueue, int pictXid) {592super(renderQueue);593this.picture = pictXid;594this.transformInUse = false;595}596597public boolean canSourceSendExposures(int x, int y, int w, int h) {598return false;599}600601public Rectangle getBounds() {602return null;603}604605public Object getDestination() {606return null;607}608609public SurfaceData getReplacement() {610return null;611}612}613614public static class XRPixmapSurfaceData extends XRSurfaceData {615Image offscreenImage;616int width;617int height;618int transparency;619620public XRPixmapSurfaceData(XRGraphicsConfig gc, int width, int height,621Image image, SurfaceType sType,622ColorModel cm, long drawable,623int transparency, int pictFormat,624int depth) {625super(null, gc, sType, cm, depth, transparency);626this.width = width;627this.height = height;628offscreenImage = image;629this.transparency = transparency;630initSurface(depth, width, height, drawable, pictFormat);631632initXRender(pictFormat);633makePipes();634}635636public void initSurface(int depth, int width, int height,637long drawable, int pictFormat) {638try {639SunToolkit.awtLock();640XRInitSurface(depth, width, height, drawable, pictFormat);641} finally {642SunToolkit.awtUnlock();643}644}645646public SurfaceData getReplacement() {647return restoreContents(offscreenImage);648}649650/**651* Need this since the surface data is created with the color model of652* the target GC, which is always opaque. But in SunGraphics2D.blitSD we653* choose loops based on the transparency on the source SD, so it could654* choose wrong loop (blit instead of blitbg, for example).655*/656public int getTransparency() {657return transparency;658}659660public Rectangle getBounds() {661return new Rectangle(width, height);662}663664@Override665public boolean canSourceSendExposures(int x, int y, int w, int h) {666return (x < 0 || y < 0 || (x + w) > width || (y + h) > height);667}668669public void flush() {670/*671* We need to invalidate the surface before disposing the native672* Drawable and Picture. This way if an application tries to render673* to an already flushed XRSurfaceData, we will notice in the674* validate() method above that it has been invalidated, and we will675* avoid using those native resources that have already been676* disposed.677*/678invalidate();679flushNativeSurface();680}681682/**683* Returns destination Image associated with this SurfaceData.684*/685public Object getDestination() {686return offscreenImage;687}688}689690public long getGC() {691return xgc;692}693694public static class LazyPipe extends ValidatePipe {695public boolean validate(SunGraphics2D sg2d) {696XRSurfaceData xsd = (XRSurfaceData) sg2d.surfaceData;697if (!xsd.isXRDrawableValid()) {698return false;699}700xsd.makePipes();701return super.validate(sg2d);702}703}704705public int getPicture() {706return picture;707}708709public int getXid() {710return xid;711}712713public XRGraphicsConfig getGraphicsConfig() {714return graphicsConfig;715}716717public void setStaticSrcTx(AffineTransform staticSrcTx) {718this.staticSrcTx = staticSrcTx;719}720}721722723