Path: blob/master/src/java.desktop/share/classes/sun/java2d/pipe/BufferedMaskBlit.java
41159 views
/*1* Copyright (c) 2007, 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.pipe;2627import java.awt.AlphaComposite;28import java.awt.Composite;29import sun.java2d.SurfaceData;30import sun.java2d.loops.Blit;31import sun.java2d.loops.CompositeType;32import sun.java2d.loops.MaskBlit;33import sun.java2d.loops.SurfaceType;34import static sun.java2d.pipe.BufferedOpCodes.*;3536/**37* The MaskBlit operation is expressed as:38* dst = ((src <MODE> dst) * pathA) + (dst * (1 - pathA))39*40* The OGL/D3D implementation of the MaskBlit operation differs from the above41* equation because it is not possible to perform such a complex operation in42* OpenGL/Direct3D (without the use of advanced techniques like fragment43* shaders and multitexturing). Therefore, the BufferedMaskBlit operation44* is expressed as:45* dst = (src * pathA) <SrcOver> dst46*47* This simplified formula is only equivalent to the "true" MaskBlit equation48* in the following situations:49* - <MODE> is SrcOver50* - <MODE> is Src, extra alpha == 1.0, and the source surface is opaque51*52* Therefore, we register BufferedMaskBlit primitives for only the SurfaceType53* and CompositeType restrictions mentioned above. In addition for the Src54* case, we must override the composite with a SrcOver (no extra alpha)55* instance, so that we set up the OpenGL/Direct3D blending mode to match the56* BufferedMaskBlit equation.57*/58public abstract class BufferedMaskBlit extends MaskBlit {5960private static final int ST_INT_ARGB = 0;61private static final int ST_INT_ARGB_PRE = 1;62private static final int ST_INT_RGB = 2;63private static final int ST_INT_BGR = 3;6465private final RenderQueue rq;66private final int srcTypeVal;67private Blit blitop;6869protected BufferedMaskBlit(RenderQueue rq,70SurfaceType srcType,71CompositeType compType,72SurfaceType dstType)73{74super(srcType, compType, dstType);75this.rq = rq;76if (srcType == SurfaceType.IntArgb) {77this.srcTypeVal = ST_INT_ARGB;78} else if (srcType == SurfaceType.IntArgbPre) {79this.srcTypeVal = ST_INT_ARGB_PRE;80} else if (srcType == SurfaceType.IntRgb) {81this.srcTypeVal = ST_INT_RGB;82} else if (srcType == SurfaceType.IntBgr) {83this.srcTypeVal = ST_INT_BGR;84} else {85throw new InternalError("unrecognized source surface type");86}87}8889@Override90public void MaskBlit(SurfaceData src, SurfaceData dst,91Composite comp, Region clip,92int srcx, int srcy,93int dstx, int dsty,94int width, int height,95byte[] mask, int maskoff, int maskscan)96{97if (width <= 0 || height <= 0) {98return;99}100101if (mask == null) {102// no mask involved; delegate to regular blit loop103if (blitop == null) {104blitop = Blit.getFromCache(src.getSurfaceType(),105CompositeType.AnyAlpha,106this.getDestType());107}108blitop.Blit(src, dst,109comp, clip,110srcx, srcy, dstx, dsty,111width, height);112return;113}114115AlphaComposite acomp = (AlphaComposite)comp;116if (acomp.getRule() != AlphaComposite.SRC_OVER) {117comp = AlphaComposite.SrcOver;118}119120rq.lock();121try {122validateContext(dst, comp, clip);123124RenderBuffer buf = rq.getBuffer();125int totalBytesRequired = 20 + (width * height * 4);126127/*128* REMIND: we should fix this so that it works with tiles that129* are larger than the entire buffer, but the native130* OGL/D3DMaskBlit isn't even prepared for tiles larger131* than 32x32 pixels, so there's no urgency here...132*/133rq.ensureCapacity(totalBytesRequired);134135// enqueue parameters and tile pixels136int newpos = enqueueTile(buf.getAddress(), buf.position(),137src, src.getNativeOps(), srcTypeVal,138mask, mask.length, maskoff, maskscan,139srcx, srcy, dstx, dsty,140width, height);141142buf.position(newpos);143} finally {144rq.unlock();145}146}147148private native int enqueueTile(long buf, int bpos,149SurfaceData srcData,150long pSrcOps, int srcType,151byte[] mask, int masklen,152int maskoff, int maskscan,153int srcx, int srcy, int dstx, int dsty,154int width, int height);155156/**157* Validates the context state using the given destination surface158* and composite/clip values.159*/160protected abstract void validateContext(SurfaceData dstData,161Composite comp, Region clip);162}163164165