blob: 42933cd0675a9d9cac3ea9a3b4e87e04a31fca2d [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
26#include <jni.h>
27#include <jlong.h>
28#include <jni_util.h>
29#include "sun_java2d_pipe_BufferedMaskBlit.h"
30#include "sun_java2d_pipe_BufferedOpCodes.h"
31#include "Trace.h"
32#include "GraphicsPrimitiveMgr.h"
33#include "IntArgb.h"
34#include "IntRgb.h"
35#include "IntBgr.h"
36
37#define MAX_MASK_LENGTH (32 * 32)
38extern unsigned char mul8table[256][256];
39
40/**
41 * This implementation of MaskBlit first combines the source system memory
42 * tile with the corresponding alpha mask and stores the resulting
43 * IntArgbPre pixels directly into the RenderBuffer. Those pixels are
44 * then eventually pulled off the RenderBuffer and copied to the destination
45 * surface in OGL/D3DMaskBlit.
46 *
47 * Note that currently there are only inner loops defined for IntArgb,
48 * IntArgbPre, IntRgb, and IntBgr, as those are the most commonly used
49 * formats for this operation.
50 */
51JNIEXPORT jint JNICALL
52Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile
53 (JNIEnv *env, jobject mb,
54 jlong buf, jint bpos,
55 jobject srcData, jlong pSrcOps, jint srcType,
56 jbyteArray maskArray, jint masklen, jint maskoff, jint maskscan,
57 jint srcx, jint srcy, jint dstx, jint dsty,
58 jint width, jint height)
59{
60 SurfaceDataOps *srcOps = (SurfaceDataOps *)jlong_to_ptr(pSrcOps);
61 SurfaceDataRasInfo srcInfo;
62 unsigned char *pMask;
63 unsigned char *bbuf;
64 jint *pBuf;
65
66 J2dTraceLn1(J2D_TRACE_INFO,
67 "BufferedMaskBlit_enqueueTile: bpos=%d",
68 bpos);
69
70 if (srcOps == NULL) {
71 J2dRlsTraceLn(J2D_TRACE_ERROR,
72 "BufferedMaskBlit_enqueueTile: srcOps is null");
73 return bpos;
74 }
75
76 bbuf = (unsigned char *)jlong_to_ptr(buf);
77 if (bbuf == NULL) {
78 J2dRlsTraceLn(J2D_TRACE_ERROR,
79 "BufferedMaskBlit_enqueueTile: cannot get direct buffer address");
80 return bpos;
81 }
82 pBuf = (jint *)(bbuf + bpos);
83
84 if (JNU_IsNull(env, maskArray)) {
85 J2dRlsTraceLn(J2D_TRACE_ERROR,
86 "BufferedMaskBlit_enqueueTile: mask array is null");
87 return bpos;
88 }
89
90 if (masklen > MAX_MASK_LENGTH) {
91 // REMIND: this approach is seriously flawed if the mask
92 // length is ever greater than MAX_MASK_LENGTH (won't fit
93 // into the cached mask tile); so far this hasn't
94 // been a problem though...
95 J2dRlsTraceLn(J2D_TRACE_ERROR,
96 "BufferedMaskBlit_enqueueTile: mask array too large");
97 return bpos;
98 }
99
100 pMask = (*env)->GetPrimitiveArrayCritical(env, maskArray, 0);
101 if (pMask == NULL) {
102 J2dRlsTraceLn(J2D_TRACE_ERROR,
103 "BufferedMaskBlit_enqueueTile: cannot lock mask array");
104 return bpos;
105 }
106
107 srcInfo.bounds.x1 = srcx;
108 srcInfo.bounds.y1 = srcy;
109 srcInfo.bounds.x2 = srcx + width;
110 srcInfo.bounds.y2 = srcy + height;
111
112 if (srcOps->Lock(env, srcOps, &srcInfo, SD_LOCK_READ) != SD_SUCCESS) {
113 J2dRlsTraceLn(J2D_TRACE_WARNING,
114 "BufferedMaskBlit_enqueueTile: could not acquire lock");
115 (*env)->ReleasePrimitiveArrayCritical(env, maskArray,
116 pMask, JNI_ABORT);
117 return bpos;
118 }
119
120 if (srcInfo.bounds.x2 > srcInfo.bounds.x1 &&
121 srcInfo.bounds.y2 > srcInfo.bounds.y1)
122 {
123 srcOps->GetRasInfo(env, srcOps, &srcInfo);
124 if (srcInfo.rasBase) {
125 jint h;
126 jint srcScanStride = srcInfo.scanStride;
127 jint srcPixelStride = srcInfo.pixelStride;
128 jint *pSrc = (jint *)
129 PtrCoord(srcInfo.rasBase,
130 srcInfo.bounds.x1, srcInfo.pixelStride,
131 srcInfo.bounds.y1, srcInfo.scanStride);
132
133 width = srcInfo.bounds.x2 - srcInfo.bounds.x1;
134 height = srcInfo.bounds.y2 - srcInfo.bounds.y1;
135 maskoff += ((srcInfo.bounds.y1 - srcy) * maskscan +
136 (srcInfo.bounds.x1 - srcx));
137 maskscan -= width;
138 pMask += maskoff;
139 srcScanStride -= width * srcPixelStride;
140 h = height;
141
142 J2dTraceLn4(J2D_TRACE_VERBOSE,
143 " sx=%d sy=%d w=%d h=%d",
144 srcInfo.bounds.x1, srcInfo.bounds.y1, width, height);
145 J2dTraceLn2(J2D_TRACE_VERBOSE,
146 " maskoff=%d maskscan=%d",
147 maskoff, maskscan);
148 J2dTraceLn2(J2D_TRACE_VERBOSE,
149 " pixstride=%d scanstride=%d",
150 srcPixelStride, srcScanStride);
151
152 // enqueue parameters
153 pBuf[0] = sun_java2d_pipe_BufferedOpCodes_MASK_BLIT;
154 pBuf[1] = dstx;
155 pBuf[2] = dsty;
156 pBuf[3] = width;
157 pBuf[4] = height;
158 pBuf += 5;
159 bpos += 5 * sizeof(jint);
160
161 // apply alpha values from mask to the source tile, and store
162 // resulting IntArgbPre pixels into RenderBuffer (there are
163 // separate inner loops for the most common source formats)
164 switch (srcType) {
165 case sun_java2d_pipe_BufferedMaskBlit_ST_INT_ARGB:
166 do {
167 jint w = width;
168 do {
169 jubyte pathA = *pMask++;
170 if (!pathA) {
171 pBuf[0] = 0;
172 } else {
173 jint cr, cg, cb, ca;
174 jubyte r, g, b, a;
175 LoadIntArgbTo4ByteArgb(pSrc, c, 0, ca, cr, cg, cb);
176 a = MUL8(ca, pathA);
177 r = MUL8(cr, a);
178 g = MUL8(cg, a);
179 b = MUL8(cb, a);
180 pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b;
181 }
182 pSrc = PtrAddBytes(pSrc, srcPixelStride);
183 pBuf++;
184 } while (--w > 0);
185 pSrc = PtrAddBytes(pSrc, srcScanStride);
186 pMask = PtrAddBytes(pMask, maskscan);
187 } while (--h > 0);
188 break;
189
190 case sun_java2d_pipe_BufferedMaskBlit_ST_INT_ARGB_PRE:
191 do {
192 jint w = width;
193 do {
194 jubyte pathA = *pMask++;
195 if (!pathA) {
196 pBuf[0] = 0;
197 } else if (pathA == 0xff) {
198 pBuf[0] = pSrc[0];
199 } else {
200 jubyte r, g, b, a;
201 a = MUL8((pSrc[0] >> 24) & 0xff, pathA);
202 r = MUL8((pSrc[0] >> 16) & 0xff, pathA);
203 g = MUL8((pSrc[0] >> 8) & 0xff, pathA);
204 b = MUL8((pSrc[0] >> 0) & 0xff, pathA);
205 pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b;
206 }
207 pSrc = PtrAddBytes(pSrc, srcPixelStride);
208 pBuf++;
209 } while (--w > 0);
210 pSrc = PtrAddBytes(pSrc, srcScanStride);
211 pMask = PtrAddBytes(pMask, maskscan);
212 } while (--h > 0);
213 break;
214
215 case sun_java2d_pipe_BufferedMaskBlit_ST_INT_RGB:
216 do {
217 jint w = width;
218 do {
219 jubyte pathA = *pMask++;
220 if (!pathA) {
221 pBuf[0] = 0;
222 } else {
223 jint cr, cg, cb;
224 jubyte r, g, b, a;
225 LoadIntRgbTo3ByteRgb(pSrc, c, 0, cr, cg, cb);
226 a = pathA;
227 r = MUL8(cr, a);
228 g = MUL8(cg, a);
229 b = MUL8(cb, a);
230 pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b;
231 }
232 pSrc = PtrAddBytes(pSrc, srcPixelStride);
233 pBuf++;
234 } while (--w > 0);
235 pSrc = PtrAddBytes(pSrc, srcScanStride);
236 pMask = PtrAddBytes(pMask, maskscan);
237 } while (--h > 0);
238 break;
239
240 case sun_java2d_pipe_BufferedMaskBlit_ST_INT_BGR:
241 do {
242 jint w = width;
243 do {
244 jubyte pathA = *pMask++;
245 if (!pathA) {
246 pBuf[0] = 0;
247 } else {
248 jint cr, cg, cb;
249 jubyte r, g, b, a;
250 LoadIntBgrTo3ByteRgb(pSrc, c, 0, cr, cg, cb);
251 a = pathA;
252 r = MUL8(cr, a);
253 g = MUL8(cg, a);
254 b = MUL8(cb, a);
255 pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b;
256 }
257 pSrc = PtrAddBytes(pSrc, srcPixelStride);
258 pBuf++;
259 } while (--w > 0);
260 pSrc = PtrAddBytes(pSrc, srcScanStride);
261 pMask = PtrAddBytes(pMask, maskscan);
262 } while (--h > 0);
263 break;
264
265 default:
266 // should not get here, just no-op...
267 break;
268 }
269
270 // increment current byte position
271 bpos += width * height * sizeof(jint);
272 }
273 SurfaceData_InvokeRelease(env, srcOps, &srcInfo);
274 }
275 SurfaceData_InvokeUnlock(env, srcOps, &srcInfo);
276
277 (*env)->ReleasePrimitiveArrayCritical(env, maskArray,
278 pMask, JNI_ABORT);
279
280 // return the current byte position
281 return bpos;
282}