Mercurial > hg > openjdk7.svn
view j2se/src/share/classes/sun/java2d/opengl/OGLMaskBlit.java @ 2:16f2b6c91171 trunk
[svn] Load openjdk/jdk7/b14 into jdk/trunk.
author | xiomara |
---|---|
date | Fri, 22 Jun 2007 00:46:43 +0000 |
parents | a4ed3fb96592 |
children | 27e0bf49438e |
line wrap: on
line source
/* * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Sun designates this * particular file as subject to the "Classpath" exception as provided * by Sun in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ package sun.java2d.opengl; import java.awt.AlphaComposite; import java.awt.Composite; import java.nio.ByteBuffer; import sun.java2d.SunGraphics2D; import sun.java2d.SurfaceData; import sun.java2d.loops.Blit; import sun.java2d.loops.CompositeType; import sun.java2d.loops.GraphicsPrimitive; import sun.java2d.loops.GraphicsPrimitiveMgr; import sun.java2d.loops.MaskBlit; import sun.java2d.loops.SurfaceType; import sun.java2d.pipe.Region; import sun.java2d.pipe.RenderBuffer; import sun.java2d.pipe.RenderQueue; import static sun.java2d.pipe.BufferedOpCodes.*; /** * The MaskBlit operation is expressed as: * dst = ((src <MODE> dst) * pathA) + (dst * (1 - pathA)) * * The OGL implementation of the MaskBlit operation differs from the above * equation because it is not possible to perform such a complex operation in * OpenGL (without the use of advanced techniques like fragment shaders and * multitexturing). Therefore, the OGLMaskBlit operation is expressed as: * dst = (src * pathA) <SrcOver> dst * * This simplified formula is only equivalent to the "true" MaskBlit equation * in the following situations: * - <MODE> is SrcOver * - <MODE> is Src, extra alpha == 1.0, and the source surface is opaque * * Therefore, we register OGLMaskBlit primitives for only the SurfaceType and * CompositeType restrictions mentioned above. In addition for the Src * case, we must override the composite with a SrcOver (no extra alpha) * instance, so that we set up the OpenGL blending mode to match the * OGLMaskBlit equation. */ class OGLMaskBlit extends MaskBlit { static void register() { GraphicsPrimitive[] primitives = { new OGLMaskBlit(SurfaceType.IntArgb, CompositeType.SrcOver, OGLSurfaceData.PF_INT_ARGB), new OGLMaskBlit(SurfaceType.IntRgb, CompositeType.SrcOver, OGLSurfaceData.PF_INT_RGB), new OGLMaskBlit(SurfaceType.IntRgb, CompositeType.SrcNoEa, OGLSurfaceData.PF_INT_RGB), new OGLMaskBlit(SurfaceType.IntBgr, CompositeType.SrcOver, OGLSurfaceData.PF_INT_BGR), new OGLMaskBlit(SurfaceType.IntBgr, CompositeType.SrcNoEa, OGLSurfaceData.PF_INT_BGR), }; GraphicsPrimitiveMgr.register(primitives); } private int typeval; private Blit blitop; private OGLMaskBlit(SurfaceType srcType, CompositeType compType, int typeval) { super(srcType, compType, OGLSurfaceData.OpenGLSurface); this.typeval = typeval; } @Override public void MaskBlit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int srcx, int srcy, int dstx, int dsty, int width, int height, byte[] mask, int maskoff, int maskscan) { if (mask == null) { // no mask involved; delegate to regular blit loop if (blitop == null) { blitop = Blit.getFromCache(src.getSurfaceType(), CompositeType.AnyAlpha, OGLSurfaceData.OpenGLSurface); } blitop.Blit(src, dst, comp, clip, srcx, srcy, dstx, dsty, width, height); return; } AlphaComposite acomp = (AlphaComposite)comp; if (acomp.getRule() != AlphaComposite.SRC_OVER) { comp = AlphaComposite.SrcOver; } OGLRenderQueue rq = OGLRenderQueue.getInstance(); rq.lock(); try { // make sure the RenderQueue keeps a hard reference to the // source (sysmem) SurfaceData to prevent it from being // disposed while the operation is processed on the QFT rq.addReference(src); OGLSurfaceData oglDst = (OGLSurfaceData)dst; OGLContext.validateContext(oglDst, oglDst, clip, comp, null, null, null, OGLContext.NO_CONTEXT_FLAGS); RenderBuffer buf = rq.getBuffer(); // we adjust the mask length so that the mask ends on a // 4-byte boundary int maskBytesRequired = (mask.length + 3) & (~3); int padding = maskBytesRequired - mask.length; int totalBytesRequired = 52 + maskBytesRequired; /* * REMIND: we should fix this so that it works with tiles that * are larger than the entire buffer, but the native * OGLMaskBlit isn't even prepared for tiles larger than * 1024 bytes, so there's no urgency here... */ rq.ensureCapacityAndAlignment(totalBytesRequired, 4); buf.putInt(MASK_BLIT); // enqueue parameters buf.putLong(src.getNativeOps()); buf.putInt(typeval); buf.putInt(srcx).putInt(srcy); buf.putInt(dstx).putInt(dsty); buf.putInt(width).putInt(height); buf.putInt(maskoff); buf.putInt(maskscan); buf.putInt(maskBytesRequired); // enqueue the mask buf.put(mask); if (padding != 0) { buf.position(buf.position() + padding); } // always flush immediately, since we (currently) have no means // of tracking changes to the source surface rq.flushNow(); } finally { rq.unlock(); } } }