Path: blob/master/src/java.desktop/unix/classes/sun/java2d/xr/XRSurfaceData.java
41159 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.AlphaComposite;28import java.awt.GraphicsConfiguration;29import java.awt.GraphicsDevice;30import java.awt.GraphicsEnvironment;31import java.awt.Image;32import java.awt.Rectangle;33import java.awt.Transparency;34import java.awt.geom.AffineTransform;35import java.awt.image.ColorModel;36import java.awt.image.DirectColorModel;37import java.awt.image.Raster;38import sun.awt.SunHints;39import sun.awt.SunToolkit;40import sun.awt.X11ComponentPeer;41import sun.awt.image.PixelConverter;42import sun.java2d.InvalidPipeException;43import sun.java2d.SunGraphics2D;44import sun.java2d.SurfaceData;45import sun.java2d.SurfaceDataProxy;46import sun.java2d.loops.CompositeType;47import sun.java2d.loops.MaskFill;48import sun.java2d.loops.RenderLoops;49import sun.java2d.loops.SurfaceType;50import sun.java2d.loops.XORComposite;51import sun.java2d.pipe.PixelToShapeConverter;52import sun.java2d.pipe.Region;53import sun.java2d.pipe.ShapeDrawPipe;54import sun.java2d.pipe.TextPipe;55import sun.java2d.pipe.ValidatePipe;56import sun.java2d.x11.XSurfaceData;57import sun.font.FontManagerNativeLibrary;5859public abstract class XRSurfaceData extends XSurfaceData {60X11ComponentPeer peer;61XRGraphicsConfig graphicsConfig;62XRBackend renderQueue;6364private RenderLoops solidloops;6566protected int depth;6768private static native void initIDs();6970protected native void XRInitSurface(int depth, int width, int height,71long drawable, int pictFormat);7273native void initXRPicture(long xsdo, int pictForm);7475native void freeXSDOPicture(long xsdo);7677public static final String DESC_BYTE_A8_X11 = "Byte A8 Pixmap";78public static final String DESC_INT_RGB_X11 = "Integer RGB Pixmap";79public static final String DESC_INT_ARGB_X11 = "Integer ARGB-Pre Pixmap";8081public static final SurfaceType82ByteA8X11 = SurfaceType.ByteGray.deriveSubType(DESC_BYTE_A8_X11);83public static final SurfaceType84IntRgbX11 = SurfaceType.IntRgb.deriveSubType(DESC_INT_RGB_X11,85PixelConverter.ArgbPre.instance);86public static final SurfaceType87IntArgbPreX11 = SurfaceType.IntArgbPre.deriveSubType(DESC_INT_ARGB_X11);8889public Raster getRaster(int x, int y, int w, int h) {90throw new InternalError("not implemented yet");91}9293protected XRRenderer xrpipe;94protected PixelToShapeConverter xrtxpipe;95protected TextPipe xrtextpipe;96protected XRDrawImage xrDrawImage;9798protected ShapeDrawPipe aaShapePipe;99protected PixelToShapeConverter aaPixelToShapeConv;100101public static void initXRSurfaceData() {102if (!isX11SurfaceDataInitialized()) {103FontManagerNativeLibrary.load();104initIDs();105XRPMBlitLoops.register();106XRMaskFill.register();107XRMaskBlit.register();108109setX11SurfaceDataInitialized();110}111}112113/**114* Synchronized accessor method for isDrawableValid.115*/116protected boolean isXRDrawableValid() {117try {118SunToolkit.awtLock();119return isDrawableValid();120} finally {121SunToolkit.awtUnlock();122}123}124125@Override126public SurfaceDataProxy makeProxyFor(SurfaceData srcData) {127return XRSurfaceDataProxy.createProxy(srcData, graphicsConfig);128}129130@Override131public void validatePipe(SunGraphics2D sg2d) {132TextPipe textpipe;133boolean validated = false;134135/*136* The textpipe for now can't handle TexturePaint when extra-alpha is137* specified nore XOR mode138*/139if ((textpipe = getTextPipe(sg2d)) == null)140{141super.validatePipe(sg2d);142textpipe = sg2d.textpipe;143validated = true;144}145146PixelToShapeConverter txPipe = null;147XRRenderer nonTxPipe = null;148149/*150* TODO: Can we rely on the GC for ARGB32 surfaces?151*/152if (sg2d.antialiasHint != SunHints.INTVAL_ANTIALIAS_ON) {153if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {154if (sg2d.compositeState <= SunGraphics2D.COMP_XOR) {155txPipe = xrtxpipe;156nonTxPipe = xrpipe;157}158} else if (sg2d.compositeState <= SunGraphics2D.COMP_ALPHA) {159if (XRPaints.isValid(sg2d)) {160txPipe = xrtxpipe;161nonTxPipe = xrpipe;162}163// custom paints handled by super.validatePipe() below164}165}166167if (txPipe != null) {168if (sg2d.transformState >= SunGraphics2D.TRANSFORM_TRANSLATESCALE) {169sg2d.drawpipe = txPipe;170sg2d.fillpipe = txPipe;171} else if (sg2d.strokeState != SunGraphics2D.STROKE_THIN) {172sg2d.drawpipe = txPipe;173sg2d.fillpipe = nonTxPipe;174} else {175sg2d.drawpipe = nonTxPipe;176sg2d.fillpipe = nonTxPipe;177}178sg2d.shapepipe = nonTxPipe;179} else {180if (!validated) {181super.validatePipe(sg2d);182}183}184185// install the text pipe based on our earlier decision186sg2d.textpipe = textpipe;187188// always override the image pipe with the specialized XRender pipe189sg2d.imagepipe = xrDrawImage;190}191192protected TextPipe getTextPipe(SunGraphics2D sg2d) {193boolean supportedPaint = sg2d.compositeState <= SunGraphics2D.COMP_ALPHA194&& (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR || sg2d.composite == null);195196boolean supportedCompOp = false;197if (sg2d.composite instanceof AlphaComposite) {198int compRule = ((AlphaComposite) sg2d.composite).getRule();199supportedCompOp = XRUtils.isMaskEvaluated(XRUtils.j2dAlphaCompToXR(compRule))200|| (compRule == AlphaComposite.SRC201&& sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR);202}203204return (supportedPaint && supportedCompOp) ? xrtextpipe : null;205}206207protected MaskFill getMaskFill(SunGraphics2D sg2d) {208AlphaComposite aComp = null;209if(sg2d.composite != null210&& sg2d.composite instanceof AlphaComposite) {211aComp = (AlphaComposite) sg2d.composite;212}213214boolean supportedPaint = sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR215|| XRPaints.isValid(sg2d);216217boolean supportedCompOp = false;218if(aComp != null) {219int rule = aComp.getRule();220supportedCompOp = XRUtils.isMaskEvaluated(XRUtils.j2dAlphaCompToXR(rule));221}222223return (supportedPaint && supportedCompOp) ? super.getMaskFill(sg2d) : null;224}225226public RenderLoops getRenderLoops(SunGraphics2D sg2d) {227if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR &&228sg2d.compositeState <= SunGraphics2D.COMP_ALPHA)229{230return solidloops;231}232233return super.getRenderLoops(sg2d);234}235236public GraphicsConfiguration getDeviceConfiguration() {237return graphicsConfig;238}239240/**241* Method for instantiating a Window SurfaceData242*/243public static XRWindowSurfaceData createData(X11ComponentPeer peer) {244XRGraphicsConfig gc = getGC(peer);245return new XRWindowSurfaceData(peer, gc, gc.getSurfaceType());246}247248/**249* Method for instantiating a Pixmap SurfaceData (offscreen).250* If the surface * is opaque a 24-bit/RGB surface is chosen,251* otherwise a 32-bit ARGB surface.252*/253public static XRPixmapSurfaceData createData(XRGraphicsConfig gc,254int width, int height,255ColorModel cm, Image image,256long drawable,257int transparency,258boolean isTexture) {259int depth;260// If we have a 32 bit color model for the window it needs261// alpha to support translucency of the window so we need262// to upgrade what was requested for the surface.263if (gc.getColorModel().getPixelSize() == 32) {264depth = 32;265transparency = Transparency.TRANSLUCENT;266} else {267depth = transparency > Transparency.OPAQUE ? 32 : 24;268}269270if (depth == 24) {271cm = new DirectColorModel(depth,2720x00FF0000, 0x0000FF00, 0x000000FF);273} else {274cm = new DirectColorModel(depth, 0x00FF0000, 0x0000FF00,2750x000000FF, 0xFF000000);276}277278return new XRPixmapSurfaceData279(gc, width, height, image, getSurfaceType(gc, transparency),280cm, drawable, transparency,281XRUtils.getPictureFormatForTransparency(transparency), depth, isTexture);282}283284protected XRSurfaceData(X11ComponentPeer peer, XRGraphicsConfig gc,285SurfaceType sType, ColorModel cm, int depth, int transparency)286{287super(sType, cm);288this.peer = peer;289this.graphicsConfig = gc;290this.solidloops = graphicsConfig.getSolidLoops(sType);291this.depth = depth;292initOps(peer, graphicsConfig, depth);293294setBlitProxyKey(gc.getProxyKey());295}296297protected XRSurfaceData(XRBackend renderQueue) {298super(XRSurfaceData.IntRgbX11,299new DirectColorModel(24, 0x00FF0000, 0x0000FF00, 0x000000FF));300this.renderQueue = renderQueue;301}302303/**304* Inits the XRender-data-structures which belong to the XRSurfaceData.305*306* @param pictureFormat307*/308public void initXRender(int pictureFormat) {309try {310SunToolkit.awtLock();311initXRPicture(getNativeOps(), pictureFormat);312renderQueue = XRCompositeManager.getInstance(this).getBackend();313maskBuffer = XRCompositeManager.getInstance(this);314} catch (Throwable ex) {315ex.printStackTrace();316} finally {317SunToolkit.awtUnlock();318}319}320321public static XRGraphicsConfig getGC(X11ComponentPeer peer) {322if (peer != null) {323return (XRGraphicsConfig) peer.getGraphicsConfiguration();324} else {325GraphicsEnvironment env =326GraphicsEnvironment.getLocalGraphicsEnvironment();327GraphicsDevice gd = env.getDefaultScreenDevice();328return (XRGraphicsConfig) gd.getDefaultConfiguration();329}330}331332/**333* Returns a boolean indicating whether or not a copyArea from the given334* rectangle source coordinates might be incomplete and result in X11335* GraphicsExposure events being generated from XCopyArea. This method336* allows the SurfaceData copyArea method to determine if it needs to set337* the GraphicsExposures attribute of the X11 GC to True or False to receive338* or avoid the events.339*340* @return true if there is any chance that an XCopyArea from the given341* source coordinates could produce any X11 Exposure events.342*/343public abstract boolean canSourceSendExposures(int x, int y, int w, int h);344345/**346* CopyArea is implemented using the "old" X11 GC, therefor clip and347* needExposures have to be validated against that GC. Pictures and GCs348* don't share state.349*/350public void validateCopyAreaGC(Region gcClip, boolean needExposures) {351if (validatedGCClip != gcClip) {352if (gcClip != null)353renderQueue.setGCClipRectangles(xgc, gcClip);354validatedGCClip = gcClip;355}356357if (validatedExposures != needExposures) {358validatedExposures = needExposures;359renderQueue.setGCExposures(xgc, needExposures);360}361362if (validatedXorComp != null) {363renderQueue.setGCMode(xgc, true);364renderQueue.setGCForeground(xgc, validatedGCForegroundPixel);365validatedXorComp = null;366}367}368369public boolean copyArea(SunGraphics2D sg2d, int x, int y, int w, int h,370int dx, int dy) {371if (xrpipe == null) {372if (!isXRDrawableValid()) {373return true;374}375makePipes();376}377CompositeType comptype = sg2d.imageComp;378if (CompositeType.SrcOverNoEa.equals(comptype) ||379CompositeType.SrcNoEa.equals(comptype))380{381try {382SunToolkit.awtLock();383boolean needExposures = canSourceSendExposures(x, y, w, h);384validateCopyAreaGC(sg2d.getCompClip(), needExposures);385renderQueue.copyArea(xid, xid, xgc, x, y, w, h, x + dx, y + dy);386} finally {387SunToolkit.awtUnlock();388}389return true;390}391return false;392}393394/**395* Returns the XRender SurfaceType which is able to fullfill the specified396* transparency requirement.397*/398public static SurfaceType getSurfaceType(XRGraphicsConfig gc,399int transparency) {400SurfaceType sType = null;401402switch (transparency) {403case Transparency.OPAQUE:404sType = XRSurfaceData.IntRgbX11;405break;406407case Transparency.BITMASK:408case Transparency.TRANSLUCENT:409sType = XRSurfaceData.IntArgbPreX11;410break;411}412413return sType;414}415416public void invalidate() {417if (isValid()) {418setInvalid();419super.invalidate();420}421}422423private long xgc; // GC is still used for copyArea424private int validatedGCForegroundPixel = 0;425private XORComposite validatedXorComp;426private int xid;427public int picture;428public XRCompositeManager maskBuffer;429430private Region validatedClip;431private Region validatedGCClip;432private boolean validatedExposures = true;433434boolean transformInUse = false;435AffineTransform validatedSourceTransform = new AffineTransform();436AffineTransform staticSrcTx = null;437int validatedRepeat = XRUtils.RepeatNone;438int validatedFilter = XRUtils.FAST;439440/**441* Validates an XRSurfaceData when used as source. Note that the clip is442* applied when used as source as well as destination.443*/444void validateAsSource(AffineTransform sxForm, int repeat, int filter) {445446if (validatedClip != null) {447validatedClip = null;448renderQueue.setClipRectangles(picture, null);449}450451if (validatedRepeat != repeat && repeat != -1) {452validatedRepeat = repeat;453renderQueue.setPictureRepeat(picture, repeat);454}455456if (sxForm == null) {457if (transformInUse) {458validatedSourceTransform.setToIdentity();459renderQueue.setPictureTransform(picture,460validatedSourceTransform);461transformInUse = false;462}463} else if (!transformInUse ||464(transformInUse && !sxForm.equals(validatedSourceTransform))) {465466validatedSourceTransform.setTransform(sxForm.getScaleX(),467sxForm.getShearY(),468sxForm.getShearX(),469sxForm.getScaleY(),470sxForm.getTranslateX(),471sxForm.getTranslateY());472473AffineTransform srcTransform = validatedSourceTransform;474if(staticSrcTx != null) {475// Apply static transform set when used as texture or gradient.476// Create a copy to not modify validatedSourceTransform as477// this would confuse the validation logic.478srcTransform = new AffineTransform(validatedSourceTransform);479srcTransform.preConcatenate(staticSrcTx);480}481482renderQueue.setPictureTransform(picture, srcTransform);483transformInUse = true;484}485486if (filter != validatedFilter && filter != -1) {487renderQueue.setFilter(picture, filter);488validatedFilter = filter;489}490}491492/**493* Validates the Surface when used as destination.494*/495public void validateAsDestination(SunGraphics2D sg2d, Region clip) {496if (!isValid()) {497throw new InvalidPipeException("bounds changed");498}499500boolean updateGCClip = false;501if (clip != validatedClip) {502renderQueue.setClipRectangles(picture, clip);503validatedClip = clip;504updateGCClip = true;505}506507if (sg2d != null && sg2d.compositeState == SunGraphics2D.COMP_XOR) {508if (validatedXorComp != sg2d.getComposite()) {509validatedXorComp = (XORComposite) sg2d.getComposite();510renderQueue.setGCMode(xgc, false);511}512513// validate pixel514int pixel = sg2d.pixel;515if (validatedGCForegroundPixel != pixel) {516int xorpixelmod = validatedXorComp.getXorPixel();517renderQueue.setGCForeground(xgc, pixel ^ xorpixelmod);518validatedGCForegroundPixel = pixel;519}520521if (updateGCClip) {522renderQueue.setGCClipRectangles(xgc, clip);523}524}525}526527public synchronized void makePipes() { /*528* TODO: Why is this synchronized,529* but access not?530*/531if (xrpipe == null) {532try {533SunToolkit.awtLock();534xgc = XCreateGC(getNativeOps());535536xrpipe = new XRRenderer(maskBuffer.getMaskBuffer());537xrtxpipe = new PixelToShapeConverter(xrpipe);538xrtextpipe = maskBuffer.getTextRenderer();539xrDrawImage = new XRDrawImage();540541} finally {542SunToolkit.awtUnlock();543}544}545}546547public static class XRWindowSurfaceData extends XRSurfaceData {548549protected final int scale;550551public XRWindowSurfaceData(X11ComponentPeer peer,552XRGraphicsConfig gc, SurfaceType sType) {553super(peer, gc, sType, peer.getColorModel(),554peer.getColorModel().getPixelSize(), Transparency.OPAQUE);555556this.scale = gc.getScale();557558if (isXRDrawableValid()) {559// If we have a 32 bit color model for the window it needs560// alpha to support translucency of the window so we need561// to get the ARGB32 XRender picture format else for562// 24 bit colormodel we need RGB24 or OPAQUE pictureformat.563if (peer.getColorModel().getPixelSize() == 32) {564initXRender(XRUtils.565getPictureFormatForTransparency(Transparency.TRANSLUCENT));566}567else {568initXRender(XRUtils.569getPictureFormatForTransparency(Transparency.OPAQUE));570}571makePipes();572}573}574575public SurfaceData getReplacement() {576return peer.getSurfaceData();577}578579public Rectangle getBounds() {580Rectangle r = peer.getBounds();581r.x = r.y = 0;582r.width *= scale;583r.height *= scale;584return r;585}586587@Override588public boolean canSourceSendExposures(int x, int y, int w, int h) {589return true;590}591592/**593* Returns destination Component associated with this SurfaceData.594*/595public Object getDestination() {596return peer.getTarget();597}598599public void invalidate() {600try {601SunToolkit.awtLock();602freeXSDOPicture(getNativeOps());603}finally {604SunToolkit.awtUnlock();605}606607super.invalidate();608}609610@Override611public double getDefaultScaleX() {612return scale;613}614615@Override616public double getDefaultScaleY() {617return scale;618}619}620621public static class XRInternalSurfaceData extends XRSurfaceData {622public XRInternalSurfaceData(XRBackend renderQueue, int pictXid) {623super(renderQueue);624this.picture = pictXid;625this.transformInUse = false;626}627628public boolean canSourceSendExposures(int x, int y, int w, int h) {629return false;630}631632public Rectangle getBounds() {633return null;634}635636public Object getDestination() {637return null;638}639640public SurfaceData getReplacement() {641return null;642}643}644645public static class XRPixmapSurfaceData extends XRSurfaceData {646Image offscreenImage;647int width;648int height;649int transparency;650private final int scale;651652public XRPixmapSurfaceData(XRGraphicsConfig gc, int width, int height,653Image image, SurfaceType sType,654ColorModel cm, long drawable,655int transparency, int pictFormat,656int depth, boolean isTexture) {657super(null, gc, sType, cm, depth, transparency);658this.scale = isTexture ? 1 : gc.getDevice().getScaleFactor();659this.width = width * scale;660this.height = height * scale;661offscreenImage = image;662this.transparency = transparency;663initSurface(depth, this.width, this.height, drawable, pictFormat);664665initXRender(pictFormat);666makePipes();667}668669public void initSurface(int depth, int width, int height,670long drawable, int pictFormat) {671try {672SunToolkit.awtLock();673XRInitSurface(depth, width, height, drawable, pictFormat);674} finally {675SunToolkit.awtUnlock();676}677}678679public SurfaceData getReplacement() {680return restoreContents(offscreenImage);681}682683/**684* Need this since the surface data is created with the color model of685* the target GC, which is always opaque. But in SunGraphics2D.blitSD we686* choose loops based on the transparency on the source SD, so it could687* choose wrong loop (blit instead of blitbg, for example).688*/689public int getTransparency() {690return transparency;691}692693public Rectangle getBounds() {694return new Rectangle(width, height);695}696697@Override698public boolean canSourceSendExposures(int x, int y, int w, int h) {699return (x < 0 || y < 0 || (x + w) > width || (y + h) > height);700}701702public void flush() {703/*704* We need to invalidate the surface before disposing the native705* Drawable and Picture. This way if an application tries to render706* to an already flushed XRSurfaceData, we will notice in the707* validate() method above that it has been invalidated, and we will708* avoid using those native resources that have already been709* disposed.710*/711invalidate();712flushNativeSurface();713}714715/**716* Returns destination Image associated with this SurfaceData.717*/718public Object getDestination() {719return offscreenImage;720}721722@Override723public double getDefaultScaleX() {724return scale;725}726727@Override728public double getDefaultScaleY() {729return scale;730}731}732733public long getGC() {734return xgc;735}736737public static class LazyPipe extends ValidatePipe {738public boolean validate(SunGraphics2D sg2d) {739XRSurfaceData xsd = (XRSurfaceData) sg2d.surfaceData;740if (!xsd.isXRDrawableValid()) {741return false;742}743xsd.makePipes();744return super.validate(sg2d);745}746}747748public int getPicture() {749return picture;750}751752public int getXid() {753return xid;754}755756public XRGraphicsConfig getGraphicsConfig() {757return graphicsConfig;758}759760public void setStaticSrcTx(AffineTransform staticSrcTx) {761this.staticSrcTx = staticSrcTx;762}763}764765766