blob: f6e32befa3a4d4a29e96a9e359fdeffb6d4faaeb [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.java2d.pipe;
27
28import java.awt.AlphaComposite;
29import java.awt.Composite;
30import sun.java2d.SurfaceData;
31import sun.java2d.loops.Blit;
32import sun.java2d.loops.CompositeType;
33import sun.java2d.loops.MaskBlit;
34import sun.java2d.loops.SurfaceType;
35import static sun.java2d.pipe.BufferedOpCodes.*;
36
37/**
38 * The MaskBlit operation is expressed as:
39 * dst = ((src <MODE> dst) * pathA) + (dst * (1 - pathA))
40 *
41 * The OGL/D3D implementation of the MaskBlit operation differs from the above
42 * equation because it is not possible to perform such a complex operation in
43 * OpenGL/Direct3D (without the use of advanced techniques like fragment
44 * shaders and multitexturing). Therefore, the BufferedMaskBlit operation
45 * is expressed as:
46 * dst = (src * pathA) <SrcOver> dst
47 *
48 * This simplified formula is only equivalent to the "true" MaskBlit equation
49 * in the following situations:
50 * - <MODE> is SrcOver
51 * - <MODE> is Src, extra alpha == 1.0, and the source surface is opaque
52 *
53 * Therefore, we register BufferedMaskBlit primitives for only the SurfaceType
54 * and CompositeType restrictions mentioned above. In addition for the Src
55 * case, we must override the composite with a SrcOver (no extra alpha)
56 * instance, so that we set up the OpenGL/Direct3D blending mode to match the
57 * BufferedMaskBlit equation.
58 */
59public abstract class BufferedMaskBlit extends MaskBlit {
60
61 private static final int ST_INT_ARGB = 0;
62 private static final int ST_INT_ARGB_PRE = 1;
63 private static final int ST_INT_RGB = 2;
64 private static final int ST_INT_BGR = 3;
65
66 private final RenderQueue rq;
67 private final int srcTypeVal;
68 private Blit blitop;
69
70 protected BufferedMaskBlit(RenderQueue rq,
71 SurfaceType srcType,
72 CompositeType compType,
73 SurfaceType dstType)
74 {
75 super(srcType, compType, dstType);
76 this.rq = rq;
77 if (srcType == SurfaceType.IntArgb) {
78 this.srcTypeVal = ST_INT_ARGB;
79 } else if (srcType == SurfaceType.IntArgbPre) {
80 this.srcTypeVal = ST_INT_ARGB_PRE;
81 } else if (srcType == SurfaceType.IntRgb) {
82 this.srcTypeVal = ST_INT_RGB;
83 } else if (srcType == SurfaceType.IntBgr) {
84 this.srcTypeVal = ST_INT_BGR;
85 } else {
86 throw new InternalError("unrecognized source surface type");
87 }
88 }
89
90 @Override
91 public void MaskBlit(SurfaceData src, SurfaceData dst,
92 Composite comp, Region clip,
93 int srcx, int srcy,
94 int dstx, int dsty,
95 int width, int height,
96 byte[] mask, int maskoff, int maskscan)
97 {
98 if (width <= 0 || height <= 0) {
99 return;
100 }
101
102 if (mask == null) {
103 // no mask involved; delegate to regular blit loop
104 if (blitop == null) {
105 blitop = Blit.getFromCache(src.getSurfaceType(),
106 CompositeType.AnyAlpha,
107 this.getDestType());
108 }
109 blitop.Blit(src, dst,
110 comp, clip,
111 srcx, srcy, dstx, dsty,
112 width, height);
113 return;
114 }
115
116 AlphaComposite acomp = (AlphaComposite)comp;
117 if (acomp.getRule() != AlphaComposite.SRC_OVER) {
118 comp = AlphaComposite.SrcOver;
119 }
120
121 rq.lock();
122 try {
123 validateContext(dst, comp, clip);
124
125 RenderBuffer buf = rq.getBuffer();
126 int totalBytesRequired = 20 + (width * height * 4);
127
128 /*
129 * REMIND: we should fix this so that it works with tiles that
130 * are larger than the entire buffer, but the native
131 * OGL/D3DMaskBlit isn't even prepared for tiles larger
132 * than 32x32 pixels, so there's no urgency here...
133 */
134 rq.ensureCapacity(totalBytesRequired);
135
136 // enqueue parameters and tile pixels
137 int newpos = enqueueTile(buf.getAddress(), buf.position(),
138 src, src.getNativeOps(), srcTypeVal,
139 mask, mask.length, maskoff, maskscan,
140 srcx, srcy, dstx, dsty,
141 width, height);
142
143 buf.position(newpos);
144 } finally {
145 rq.unlock();
146 }
147 }
148
149 private native int enqueueTile(long buf, int bpos,
150 SurfaceData srcData,
151 long pSrcOps, int srcType,
152 byte[] mask, int masklen,
153 int maskoff, int maskscan,
154 int srcx, int srcy, int dstx, int dsty,
155 int width, int height);
156
157 /**
158 * Validates the context state using the given destination surface
159 * and composite/clip values.
160 */
161 protected abstract void validateContext(SurfaceData dstData,
162 Composite comp, Region clip);
163}