Path: blob/master/src/java.desktop/unix/classes/sun/java2d/xr/XRPMBlitLoops.java
41159 views
/*1* Copyright (c) 2010, 2020, 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 sun.awt.SunToolkit;28import sun.awt.image.*;29import sun.java2d.loops.*;30import sun.java2d.pipe.*;31import sun.java2d.*;32import java.awt.*;33import java.awt.geom.*;34import java.lang.ref.*;3536public final class XRPMBlitLoops {3738static WeakReference<SunVolatileImage> argbTmpPM = new WeakReference<SunVolatileImage>(null);39static WeakReference<SunVolatileImage> rgbTmpPM = new WeakReference<SunVolatileImage>(null);4041private XRPMBlitLoops() {42}4344public static void register() {45GraphicsPrimitive[] primitives = { new XRPMBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntRgbX11),46new XRPMBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntArgbPreX11),47new XRPMBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntRgbX11),48new XRPMBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntArgbPreX11),4950new XRPMScaledBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntRgbX11),51new XRPMScaledBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntArgbPreX11),52new XRPMScaledBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntRgbX11),53new XRPMScaledBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntArgbPreX11),5455new XRPMTransformedBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntRgbX11),56new XRPMTransformedBlit(XRSurfaceData.IntRgbX11, XRSurfaceData.IntArgbPreX11),57new XRPMTransformedBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntRgbX11),58new XRPMTransformedBlit(XRSurfaceData.IntArgbPreX11, XRSurfaceData.IntArgbPreX11),5960/* SW -> Surface Blits */61new XrSwToPMBlit(SurfaceType.IntArgb, XRSurfaceData.IntRgbX11),62new XrSwToPMBlit(SurfaceType.IntRgb, XRSurfaceData.IntRgbX11),63new XrSwToPMBlit(SurfaceType.IntBgr, XRSurfaceData.IntRgbX11),64new XrSwToPMBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntRgbX11),65new XrSwToPMBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntRgbX11),66new XrSwToPMBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntRgbX11),67new XrSwToPMBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntRgbX11),6869new XrSwToPMBlit(SurfaceType.IntArgb, XRSurfaceData.IntArgbPreX11),70new XrSwToPMBlit(SurfaceType.IntRgb, XRSurfaceData.IntArgbPreX11),71new XrSwToPMBlit(SurfaceType.IntBgr, XRSurfaceData.IntArgbPreX11),72new XrSwToPMBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntArgbPreX11),73new XrSwToPMBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntArgbPreX11),74new XrSwToPMBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntArgbPreX11),75new XrSwToPMBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntArgbPreX11),7677/* SW->Surface Scales */78new XrSwToPMScaledBlit(SurfaceType.IntArgb, XRSurfaceData.IntRgbX11),79new XrSwToPMScaledBlit(SurfaceType.IntRgb, XRSurfaceData.IntRgbX11),80new XrSwToPMScaledBlit(SurfaceType.IntBgr, XRSurfaceData.IntRgbX11),81new XrSwToPMScaledBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntRgbX11),82new XrSwToPMScaledBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntRgbX11),83new XrSwToPMScaledBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntRgbX11),84new XrSwToPMScaledBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntRgbX11),8586new XrSwToPMScaledBlit(SurfaceType.IntArgb, XRSurfaceData.IntArgbPreX11),87new XrSwToPMScaledBlit(SurfaceType.IntRgb, XRSurfaceData.IntArgbPreX11),88new XrSwToPMScaledBlit(SurfaceType.IntBgr, XRSurfaceData.IntArgbPreX11),89new XrSwToPMScaledBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntArgbPreX11),90new XrSwToPMScaledBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntArgbPreX11),91new XrSwToPMScaledBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntArgbPreX11),92new XrSwToPMScaledBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntArgbPreX11),9394/* SW->Surface Transforms */95new XrSwToPMTransformedBlit(SurfaceType.IntArgb, XRSurfaceData.IntRgbX11),96new XrSwToPMTransformedBlit(SurfaceType.IntRgb, XRSurfaceData.IntRgbX11),97new XrSwToPMTransformedBlit(SurfaceType.IntBgr, XRSurfaceData.IntRgbX11),98new XrSwToPMTransformedBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntRgbX11),99new XrSwToPMTransformedBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntRgbX11),100new XrSwToPMTransformedBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntRgbX11),101new XrSwToPMTransformedBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntRgbX11),102103new XrSwToPMTransformedBlit(SurfaceType.IntArgb, XRSurfaceData.IntArgbPreX11),104new XrSwToPMTransformedBlit(SurfaceType.IntRgb, XRSurfaceData.IntArgbPreX11),105new XrSwToPMTransformedBlit(SurfaceType.IntBgr, XRSurfaceData.IntArgbPreX11),106new XrSwToPMTransformedBlit(SurfaceType.ThreeByteBgr, XRSurfaceData.IntArgbPreX11),107new XrSwToPMTransformedBlit(SurfaceType.Ushort565Rgb, XRSurfaceData.IntArgbPreX11),108new XrSwToPMTransformedBlit(SurfaceType.Ushort555Rgb, XRSurfaceData.IntArgbPreX11),109new XrSwToPMTransformedBlit(SurfaceType.ByteIndexed, XRSurfaceData.IntArgbPreX11), };110GraphicsPrimitiveMgr.register(primitives);111}112113/**114* Caches a SW surface using a temporary pixmap. The pixmap is held by a WeakReference,115* allowing it to shrink again after some time.116*/117protected static XRSurfaceData cacheToTmpSurface(SurfaceData src, XRSurfaceData dst, int w, int h, int sx, int sy) {118SunVolatileImage vImg;119SurfaceType vImgSurfaceType;120121if (src.getTransparency() == Transparency.OPAQUE) {122vImg = rgbTmpPM.get();123vImgSurfaceType = SurfaceType.IntRgb;124} else {125vImg = argbTmpPM.get();126vImgSurfaceType = SurfaceType.IntArgbPre;127}128129if (vImg == null || vImg.getWidth() < w || vImg.getHeight() < h ||130// Sometimes we get volatile image of wrong dest surface type,131// so recreating it132!(vImg.getDestSurface() instanceof XRSurfaceData))133{134if (vImg != null) {135vImg.flush();136}137vImg = (SunVolatileImage) dst.getGraphicsConfig().createCompatibleVolatileImage(w, h, src.getTransparency());138vImg.setAccelerationPriority(1.0f);139140if (!(vImg.getDestSurface() instanceof XRSurfaceData)) {141throw new InvalidPipeException("Could not create XRSurfaceData");142}143if (src.getTransparency() == SurfaceData.OPAQUE) {144rgbTmpPM = new WeakReference<SunVolatileImage>(vImg);145} else {146argbTmpPM = new WeakReference<SunVolatileImage>(vImg);147}148}149150Blit swToSurfaceBlit = Blit.getFromCache(src.getSurfaceType(), CompositeType.SrcNoEa, vImgSurfaceType);151152if (!(vImg.getDestSurface() instanceof XRSurfaceData)) {153throw new InvalidPipeException("wrong surface data type: " + vImg.getDestSurface());154}155156XRSurfaceData vImgSurface = (XRSurfaceData) vImg.getDestSurface();157swToSurfaceBlit.Blit(src, vImgSurface, AlphaComposite.Src, null,158sx, sy, 0, 0, w, h);159160return vImgSurface;161}162}163164class XRPMBlit extends Blit {165public XRPMBlit(SurfaceType srcType, SurfaceType dstType) {166super(srcType, CompositeType.AnyAlpha, dstType);167}168169public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) {170try {171SunToolkit.awtLock();172173XRSurfaceData x11sdDst = (XRSurfaceData) dst;174x11sdDst.validateAsDestination(null, clip);175XRSurfaceData x11sdSrc = (XRSurfaceData) src;176x11sdSrc.validateAsSource(null, XRUtils.RepeatNone, XRUtils.FAST);177178x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null);179180x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, sx, sy, dx, dy, w, h);181} finally {182SunToolkit.awtUnlock();183}184}185}186187class XRPMScaledBlit extends ScaledBlit {188public XRPMScaledBlit(SurfaceType srcType, SurfaceType dstType) {189super(srcType, CompositeType.AnyAlpha, dstType);190}191192@SuppressWarnings("cast")193public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1,194double dx2, double dy2) {195try {196SunToolkit.awtLock();197198XRSurfaceData x11sdDst = (XRSurfaceData) dst;199x11sdDst.validateAsDestination(null, clip);200XRSurfaceData x11sdSrc = (XRSurfaceData) src;201x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null);202203double xScale = (dx2 - dx1) / (sx2 - sx1);204double yScale = (dy2 - dy1) / (sy2 - sy1);205206sx1 *= xScale;207sx2 *= xScale;208sy1 *= yScale;209sy2 *= yScale;210211dx1 = Math.ceil(dx1 - 0.5);212dy1 = Math.ceil(dy1 - 0.5);213dx2 = Math.ceil(dx2 - 0.5);214dy2 = Math.ceil(dy2 - 0.5);215216AffineTransform xForm = AffineTransform.getScaleInstance(1 / xScale, 1 / yScale);217218x11sdSrc.validateAsSource(xForm, XRUtils.RepeatNone, XRUtils.FAST);219x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, (int) sx1, (int) sy1, (int) dx1, (int) dy1, (int) (dx2 - dx1), (int) (dy2 - dy1));220} finally {221SunToolkit.awtUnlock();222}223}224}225226/**227* Called also if scale+transform is set228*229* @author Clemens Eisserer230*/231class XRPMTransformedBlit extends TransformBlit {232final Rectangle compositeBounds = new Rectangle();233final double[] srcCoords = new double[8];234final double[] dstCoords = new double[8];235236public XRPMTransformedBlit(SurfaceType srcType, SurfaceType dstType) {237super(srcType, CompositeType.AnyAlpha, dstType);238}239240/*241* Calculates the composition-rectangle required for transformed blits.242* For composite operations where the composition-rectangle defines243* the modified destination area, coordinates are rounded.244* Otherwise the composition window rectangle is sized large enough245* to not clip away any pixels.246*/247protected void adjustCompositeBounds(boolean isQuadrantRotated, AffineTransform tr,248int dstx, int dsty, int width, int height) {249srcCoords[0] = dstx;250srcCoords[1] = dsty;251srcCoords[2] = dstx + width;252srcCoords[3] = dsty + height;253254double minX, minY, maxX, maxY;255if (isQuadrantRotated) {256tr.transform(srcCoords, 0, dstCoords, 0, 2);257258minX = Math.min(dstCoords[0], dstCoords[2]);259minY = Math.min(dstCoords[1], dstCoords[3]);260maxX = Math.max(dstCoords[0], dstCoords[2]);261maxY = Math.max(dstCoords[1], dstCoords[3]);262263minX = Math.ceil(minX - 0.5);264minY = Math.ceil(minY - 0.5);265maxX = Math.ceil(maxX - 0.5);266maxY = Math.ceil(maxY - 0.5);267} else {268srcCoords[4] = dstx;269srcCoords[5] = dsty + height;270srcCoords[6] = dstx + width;271srcCoords[7] = dsty;272273tr.transform(srcCoords, 0, dstCoords, 0, 4);274275minX = Math.min(dstCoords[0], Math.min(dstCoords[2], Math.min(dstCoords[4], dstCoords[6])));276minY = Math.min(dstCoords[1], Math.min(dstCoords[3], Math.min(dstCoords[5], dstCoords[7])));277maxX = Math.max(dstCoords[0], Math.max(dstCoords[2], Math.max(dstCoords[4], dstCoords[6])));278maxY = Math.max(dstCoords[1], Math.max(dstCoords[3], Math.max(dstCoords[5], dstCoords[7])));279280minX = Math.floor(minX);281minY = Math.floor(minY);282maxX = Math.ceil(maxX);283maxY = Math.ceil(maxY);284}285286compositeBounds.x = (int) minX;287compositeBounds.y = (int) minY;288compositeBounds.width = (int) (maxX - minX);289compositeBounds.height = (int) (maxY - minY);290}291292public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform,293int hint, int srcx, int srcy, int dstx, int dsty, int width, int height) {294try {295SunToolkit.awtLock();296297XRSurfaceData x11sdDst = (XRSurfaceData) dst;298XRSurfaceData x11sdSrc = (XRSurfaceData) src;299XRCompositeManager xrMgr = XRCompositeManager.getInstance(x11sdSrc);300301float extraAlpha = ((AlphaComposite) comp).getAlpha();302int filter = XRUtils.ATransOpToXRQuality(hint);303boolean isQuadrantRotated = XRUtils.isTransformQuadrantRotated(xform);304305adjustCompositeBounds(isQuadrantRotated, xform, dstx, dsty, width, height);306307x11sdDst.validateAsDestination(null, clip);308x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null);309310AffineTransform trx = AffineTransform.getTranslateInstance(-compositeBounds.x, -compositeBounds.y);311trx.concatenate(xform);312AffineTransform maskTX = (AffineTransform) trx.clone();313trx.translate(-srcx, -srcy);314315try {316trx.invert();317} catch (NoninvertibleTransformException ex) {318trx.setToIdentity();319}320321if (filter != XRUtils.FAST && (!isQuadrantRotated || extraAlpha != 1.0f)) {322XRMaskImage mask = x11sdSrc.maskBuffer.getMaskImage();323324// For quadrant-transformed blits geometry is not stored inside the mask325// therefore we can use a repeating 1x1 mask for applying extra alpha.326int maskPicture = isQuadrantRotated ? xrMgr.getExtraAlphaMask()327: mask.prepareBlitMask(x11sdDst, maskTX, width, height);328329x11sdSrc.validateAsSource(trx, XRUtils.RepeatPad, filter);330x11sdDst.maskBuffer.con.renderComposite(xrMgr.getCompRule(), x11sdSrc.picture,331maskPicture, x11sdDst.picture, 0, 0, 0, 0, compositeBounds.x, compositeBounds.y,332compositeBounds.width, compositeBounds.height);333} else {334int repeat = filter == XRUtils.FAST ? XRUtils.RepeatNone : XRUtils.RepeatPad;335336x11sdSrc.validateAsSource(trx, repeat, filter);337338// compositeBlit takes care of extra alpha339x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, 0, 0, compositeBounds.x,340compositeBounds.y, compositeBounds.width, compositeBounds.height);341}342} finally {343SunToolkit.awtUnlock();344}345}346}347348class XrSwToPMBlit extends Blit {349Blit pmToSurfaceBlit;350351XrSwToPMBlit(SurfaceType srcType, SurfaceType dstType) {352super(srcType, CompositeType.AnyAlpha, dstType);353pmToSurfaceBlit = new XRPMBlit(dstType, dstType);354}355356public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) {357try {358SunToolkit.awtLock();359360XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx, sy);361pmToSurfaceBlit.Blit(vImgSurface, dst, comp, clip, 0, 0, dx, dy, w, h);362} finally {363SunToolkit.awtUnlock();364}365}366}367368class XrSwToPMScaledBlit extends ScaledBlit {369ScaledBlit pmToSurfaceBlit;370371XrSwToPMScaledBlit(SurfaceType srcType, SurfaceType dstType) {372super(srcType, CompositeType.AnyAlpha, dstType);373pmToSurfaceBlit = new XRPMScaledBlit(dstType, dstType);374}375376public void Scale(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx1, int sy1, int sx2, int sy2, double dx1, double dy1,377double dx2, double dy2) {378{379int w = sx2 - sx1;380int h = sy2 - sy1;381382try {383SunToolkit.awtLock();384XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx1, sy1);385pmToSurfaceBlit.Scale(vImgSurface, dst, comp, clip, 0, 0, w, h, dx1, dy1, dx2, dy2);386} finally {387SunToolkit.awtUnlock();388}389}390}391}392393class XrSwToPMTransformedBlit extends TransformBlit {394TransformBlit pmToSurfaceBlit;395396XrSwToPMTransformedBlit(SurfaceType srcType, SurfaceType dstType) {397super(srcType, CompositeType.AnyAlpha, dstType);398pmToSurfaceBlit = new XRPMTransformedBlit(dstType, dstType);399}400401public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform, int hint, int sx, int sy, int dstx,402int dsty, int w, int h) {403try {404SunToolkit.awtLock();405406XRSurfaceData vImgSurface = XRPMBlitLoops.cacheToTmpSurface(src, (XRSurfaceData) dst, w, h, sx, sy);407pmToSurfaceBlit.Transform(vImgSurface, dst, comp, clip, xform, hint, 0, 0, dstx, dsty, w, h);408} finally {409SunToolkit.awtUnlock();410}411}412}413414415