1 /* 2 * Copyright (c) 2007, 2008, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * 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) 38 extern 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 */ 51 JNIEXPORT jint JNICALL 52 Java_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 *bbuf; 63 jint *pBuf; 64 65 J2dTraceLn1(J2D_TRACE_INFO, 66 "BufferedMaskBlit_enqueueTile: bpos=%d", 67 bpos); 68 69 if (srcOps == NULL) { 70 J2dRlsTraceLn(J2D_TRACE_ERROR, 71 "BufferedMaskBlit_enqueueTile: srcOps is null"); 72 return bpos; 73 } 74 75 bbuf = (unsigned char *)jlong_to_ptr(buf); 76 if (bbuf == NULL) { 77 J2dRlsTraceLn(J2D_TRACE_ERROR, 78 "BufferedMaskBlit_enqueueTile: cannot get direct buffer address"); 79 return bpos; 80 } 81 pBuf = (jint *)(bbuf + bpos); 82 83 if (JNU_IsNull(env, maskArray)) { 84 J2dRlsTraceLn(J2D_TRACE_ERROR, 85 "BufferedMaskBlit_enqueueTile: mask array is null"); 86 return bpos; 87 } 88 89 if (masklen > MAX_MASK_LENGTH) { 90 // REMIND: this approach is seriously flawed if the mask 91 // length is ever greater than MAX_MASK_LENGTH (won't fit 92 // into the cached mask tile); so far this hasn't 93 // been a problem though... 94 J2dRlsTraceLn(J2D_TRACE_ERROR, 95 "BufferedMaskBlit_enqueueTile: mask array too large"); 96 return bpos; 97 } 98 99 srcInfo.bounds.x1 = srcx; 100 srcInfo.bounds.y1 = srcy; 101 srcInfo.bounds.x2 = srcx + width; 102 srcInfo.bounds.y2 = srcy + height; 103 104 if (srcOps->Lock(env, srcOps, &srcInfo, SD_LOCK_READ) != SD_SUCCESS) { 105 J2dRlsTraceLn(J2D_TRACE_WARNING, 106 "BufferedMaskBlit_enqueueTile: could not acquire lock"); 107 return bpos; 108 } 109 110 if (srcInfo.bounds.x2 > srcInfo.bounds.x1 && 111 srcInfo.bounds.y2 > srcInfo.bounds.y1) 112 { 113 srcOps->GetRasInfo(env, srcOps, &srcInfo); 114 if (srcInfo.rasBase) { 115 jint h; 116 jint srcScanStride = srcInfo.scanStride; 117 jint srcPixelStride = srcInfo.pixelStride; 118 jint *pSrc = (jint *) 119 PtrCoord(srcInfo.rasBase, 120 srcInfo.bounds.x1, srcInfo.pixelStride, 121 srcInfo.bounds.y1, srcInfo.scanStride); 122 unsigned char *pMask = 123 (*env)->GetPrimitiveArrayCritical(env, maskArray, 0); 124 if (pMask == NULL) { 125 J2dRlsTraceLn(J2D_TRACE_ERROR, 126 "BufferedMaskBlit_enqueueTile: cannot lock mask array"); 127 SurfaceData_InvokeRelease(env, srcOps, &srcInfo); 128 SurfaceData_InvokeUnlock(env, srcOps, &srcInfo); 129 return bpos; 130 } 131 132 width = srcInfo.bounds.x2 - srcInfo.bounds.x1; 133 height = srcInfo.bounds.y2 - srcInfo.bounds.y1; 134 maskoff += ((srcInfo.bounds.y1 - srcy) * maskscan + 135 (srcInfo.bounds.x1 - srcx)); 136 maskscan -= width; 137 pMask += maskoff; 138 srcScanStride -= width * srcPixelStride; 139 h = height; 140 141 J2dTraceLn4(J2D_TRACE_VERBOSE, 142 " sx=%d sy=%d w=%d h=%d", 143 srcInfo.bounds.x1, srcInfo.bounds.y1, width, height); 144 J2dTraceLn2(J2D_TRACE_VERBOSE, 145 " maskoff=%d maskscan=%d", 146 maskoff, maskscan); 147 J2dTraceLn2(J2D_TRACE_VERBOSE, 148 " pixstride=%d scanstride=%d", 149 srcPixelStride, srcScanStride); 150 151 // enqueue parameters 152 pBuf[0] = sun_java2d_pipe_BufferedOpCodes_MASK_BLIT; 153 pBuf[1] = dstx; 154 pBuf[2] = dsty; 155 pBuf[3] = width; 156 pBuf[4] = height; 157 pBuf += 5; 158 bpos += 5 * sizeof(jint); 159 160 // apply alpha values from mask to the source tile, and store 161 // resulting IntArgbPre pixels into RenderBuffer (there are 162 // separate inner loops for the most common source formats) 163 switch (srcType) { 164 case sun_java2d_pipe_BufferedMaskBlit_ST_INT_ARGB: 165 do { 166 jint w = width; 167 do { 168 jint pathA = *pMask++; 169 if (!pathA) { 170 pBuf[0] = 0; 171 } else { 172 jint pixel = pSrc[0]; 173 if (pathA == 0xff && (pixel >> 24) + 1 == 0) { 174 pBuf[0] = pixel; 175 } else { 176 jint r, g, b, a; 177 ExtractIntDcmComponents1234(pixel, a, r, g, b); 178 a = MUL8(pathA, a); 179 r = MUL8(a, r); 180 g = MUL8(a, g); 181 b = MUL8(a, b); 182 pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b; 183 } 184 } 185 pSrc = PtrAddBytes(pSrc, srcPixelStride); 186 pBuf++; 187 } while (--w > 0); 188 pSrc = PtrAddBytes(pSrc, srcScanStride); 189 pMask = PtrAddBytes(pMask, maskscan); 190 } while (--h > 0); 191 break; 192 193 case sun_java2d_pipe_BufferedMaskBlit_ST_INT_ARGB_PRE: 194 do { 195 jint w = width; 196 do { 197 jint pathA = *pMask++; 198 if (!pathA) { 199 pBuf[0] = 0; 200 } else if (pathA == 0xff) { 201 pBuf[0] = pSrc[0]; 202 } else { 203 jint r, g, b, a; 204 a = MUL8(pathA, (pSrc[0] >> 24) & 0xff); 205 r = MUL8(pathA, (pSrc[0] >> 16) & 0xff); 206 g = MUL8(pathA, (pSrc[0] >> 8) & 0xff); 207 b = MUL8(pathA, (pSrc[0] >> 0) & 0xff); 208 pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b; 209 } 210 pSrc = PtrAddBytes(pSrc, srcPixelStride); 211 pBuf++; 212 } while (--w > 0); 213 pSrc = PtrAddBytes(pSrc, srcScanStride); 214 pMask = PtrAddBytes(pMask, maskscan); 215 } while (--h > 0); 216 break; 217 218 case sun_java2d_pipe_BufferedMaskBlit_ST_INT_RGB: 219 do { 220 jint w = width; 221 do { 222 jint pathA = *pMask++; 223 if (!pathA) { 224 pBuf[0] = 0; 225 } else if (pathA == 0xff) { 226 pBuf[0] = pSrc[0] | 0xff000000; 227 } else { 228 jint r, g, b, a; 229 LoadIntRgbTo3ByteRgb(pSrc, c, 0, r, g, b); 230 a = pathA; 231 r = MUL8(a, r); 232 g = MUL8(a, g); 233 b = MUL8(a, b); 234 pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b; 235 } 236 pSrc = PtrAddBytes(pSrc, srcPixelStride); 237 pBuf++; 238 } while (--w > 0); 239 pSrc = PtrAddBytes(pSrc, srcScanStride); 240 pMask = PtrAddBytes(pMask, maskscan); 241 } while (--h > 0); 242 break; 243 244 case sun_java2d_pipe_BufferedMaskBlit_ST_INT_BGR: 245 do { 246 jint w = width; 247 do { 248 jint pathA = *pMask++; 249 if (!pathA) { 250 pBuf[0] = 0; 251 } else { 252 jint r, g, b, a; 253 LoadIntBgrTo3ByteRgb(pSrc, c, 0, r, g, b); 254 a = pathA; 255 r = MUL8(a, r); 256 g = MUL8(a, g); 257 b = MUL8(a, b); 258 pBuf[0] = (a << 24) | (r << 16) | (g << 8) | b; 259 } 260 pSrc = PtrAddBytes(pSrc, srcPixelStride); 261 pBuf++; 262 } while (--w > 0); 263 pSrc = PtrAddBytes(pSrc, srcScanStride); 264 pMask = PtrAddBytes(pMask, maskscan); 265 } while (--h > 0); 266 break; 267 268 default: 269 // should not get here, just no-op... 270 break; 271 } 272 273 // increment current byte position 274 bpos += width * height * sizeof(jint); 275 276 (*env)->ReleasePrimitiveArrayCritical(env, maskArray, 277 pMask, JNI_ABORT); 278 } 279 SurfaceData_InvokeRelease(env, srcOps, &srcInfo); 280 } 281 SurfaceData_InvokeUnlock(env, srcOps, &srcInfo); 282 283 // return the current byte position 284 return bpos; 285 }