1 /* 2 * Copyright (c) 2000, 2007, 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 <stdlib.h> 27 #include <jni.h> 28 #include <jlong.h> 29 #include "X11SurfaceData.h" 30 #include "Region.h" 31 32 JNIEXPORT void JNICALL 33 Java_sun_java2d_x11_X11PMBlitLoops_nativeBlit 34 (JNIEnv *env, jobject joSelf, 35 jlong srcData, jlong dstData, 36 jlong gc, jobject clip, 37 jint srcx, jint srcy, 38 jint dstx, jint dsty, 39 jint width, jint height) 40 { 41 #ifndef HEADLESS 42 X11SDOps *srcXsdo, *dstXsdo; 43 SurfaceDataBounds span, srcBounds; 44 RegionData clipInfo; 45 GC xgc; 46 47 if (width <= 0 || height <= 0) { 48 return; 49 } 50 51 srcXsdo = (X11SDOps *)jlong_to_ptr(srcData); 52 if (srcXsdo == NULL) { 53 return; 54 } 55 dstXsdo = (X11SDOps *)jlong_to_ptr(dstData); 56 if (dstXsdo == NULL) { 57 return; 58 } 59 if (Region_GetInfo(env, clip, &clipInfo)) { 60 return; 61 } 62 63 xgc = (GC)gc; 64 if (xgc == NULL) { 65 return; 66 } 67 68 #ifdef MITSHM 69 if (srcXsdo->isPixmap) { 70 X11SD_UnPuntPixmap(srcXsdo); 71 } 72 #endif /* MITSHM */ 73 74 /* clip the source rect to the source pixmap's dimensions */ 75 srcBounds.x1 = srcx; 76 srcBounds.y1 = srcy; 77 srcBounds.x2 = srcx + width; 78 srcBounds.y2 = srcy + height; 79 SurfaceData_IntersectBoundsXYXY(&srcBounds, 80 0, 0, srcXsdo->pmWidth, srcXsdo->pmHeight); 81 span.x1 = dstx; 82 span.y1 = dsty; 83 span.x2 = dstx + width; 84 span.y2 = dsty + height; 85 86 /* intersect the source and dest rects */ 87 SurfaceData_IntersectBlitBounds(&srcBounds, &span, 88 dstx - srcx, dsty - srcy); 89 srcx = srcBounds.x1; 90 srcy = srcBounds.y1; 91 dstx = span.x1; 92 dsty = span.y1; 93 94 if (srcXsdo->bitmask != 0) { 95 XSetClipOrigin(awt_display, xgc, dstx - srcx, dsty - srcy); 96 XSetClipMask(awt_display, xgc, srcXsdo->bitmask); 97 } 98 99 Region_IntersectBounds(&clipInfo, &span); 100 if (!Region_IsEmpty(&clipInfo)) { 101 Region_StartIteration(env, &clipInfo); 102 srcx -= dstx; 103 srcy -= dsty; 104 while (Region_NextIteration(&clipInfo, &span)) { 105 XCopyArea(awt_display, srcXsdo->drawable, dstXsdo->drawable, xgc, 106 srcx + span.x1, srcy + span.y1, 107 span.x2 - span.x1, span.y2 - span.y1, 108 span.x1, span.y1); 109 } 110 Region_EndIteration(env, &clipInfo); 111 } 112 113 if (srcXsdo->bitmask != 0) { 114 XSetClipMask(awt_display, xgc, None); 115 } 116 117 #ifdef MITSHM 118 if (srcXsdo->shmPMData.usingShmPixmap) { 119 srcXsdo->shmPMData.xRequestSent = JNI_TRUE; 120 } 121 #endif /* MITSHM */ 122 X11SD_DirectRenderNotify(env, dstXsdo); 123 #endif /* !HEADLESS */ 124 } 125 126 JNIEXPORT void JNICALL 127 Java_sun_java2d_x11_X11PMBlitBgLoops_nativeBlitBg 128 (JNIEnv *env, jobject joSelf, 129 jlong srcData, jlong dstData, 130 jlong xgc, jint pixel, 131 jint srcx, jint srcy, 132 jint dstx, jint dsty, 133 jint width, jint height) 134 { 135 #ifndef HEADLESS 136 X11SDOps *srcXsdo, *dstXsdo; 137 GC dstGC; 138 SurfaceDataBounds dstBounds, srcBounds; 139 Drawable srcDrawable; 140 141 if (width <= 0 || height <= 0) { 142 return; 143 } 144 145 srcXsdo = (X11SDOps *)jlong_to_ptr(srcData); 146 if (srcXsdo == NULL) { 147 return; 148 } 149 dstXsdo = (X11SDOps *)jlong_to_ptr(dstData); 150 if (dstXsdo == NULL) { 151 return; 152 } 153 154 dstGC = (GC)xgc; 155 if (dstGC == NULL) { 156 return; 157 } 158 159 #ifdef MITSHM 160 if (srcXsdo->isPixmap) { 161 X11SD_UnPuntPixmap(srcXsdo); 162 } 163 #endif /* MITSHM */ 164 165 srcDrawable = srcXsdo->GetPixmapWithBg(env, srcXsdo, pixel); 166 if (srcDrawable == 0) { 167 return; 168 } 169 170 /* clip the source rect to the source pixmap's dimensions */ 171 srcBounds.x1 = srcx; 172 srcBounds.y1 = srcy; 173 srcBounds.x2 = srcx + width; 174 srcBounds.y2 = srcy + height; 175 SurfaceData_IntersectBoundsXYXY(&srcBounds, 176 0, 0, srcXsdo->pmWidth, srcXsdo->pmHeight); 177 dstBounds.x1 = dstx; 178 dstBounds.y1 = dsty; 179 dstBounds.x2 = dstx + width; 180 dstBounds.y2 = dsty + height; 181 182 /* intersect the source and dest rects */ 183 SurfaceData_IntersectBlitBounds(&srcBounds, &dstBounds, 184 dstx - srcx, dsty - srcy); 185 srcx = srcBounds.x1; 186 srcy = srcBounds.y1; 187 dstx = dstBounds.x1; 188 dsty = dstBounds.y1; 189 width = srcBounds.x2 - srcBounds.x1; 190 height = srcBounds.y2 - srcBounds.y1; 191 192 /* do an unmasked copy as we've already filled transparent 193 pixels of the source image with the desired color */ 194 XCopyArea(awt_display, srcDrawable, dstXsdo->drawable, dstGC, 195 srcx, srcy, width, height, dstx, dsty); 196 197 srcXsdo->ReleasePixmapWithBg(env, srcXsdo); 198 X11SD_DirectRenderNotify(env, dstXsdo); 199 #endif /* !HEADLESS */ 200 } 201 202 /* 203 * Class: sun_java2d_x11_X11PMBlitLoops 204 * Method: updateBitmask 205 * Signature: (Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;)V 206 */ 207 JNIEXPORT void JNICALL 208 Java_sun_java2d_x11_X11PMBlitLoops_updateBitmask 209 (JNIEnv *env, jclass xpmbl, jobject srcsd, jobject dstsd, jboolean isICM) 210 { 211 #ifndef HEADLESS 212 SurfaceDataOps *srcOps = SurfaceData_GetOps(env, srcsd); 213 X11SDOps *xsdo = (X11SDOps *) SurfaceData_GetOps(env, dstsd); 214 SurfaceDataRasInfo srcInfo; 215 216 int flags; 217 int screen; 218 int width; 219 int height; 220 jint srcScan, dstScan; 221 int rowCount; 222 unsigned char *pDst; 223 XImage *image; 224 GC xgc; 225 226 if (srcOps == NULL || xsdo == NULL) { 227 JNU_ThrowNullPointerException(env, "Null BISD in updateMaskRegion"); 228 return; 229 } 230 231 AWT_LOCK(); 232 233 screen = xsdo->configData->awt_visInfo.screen; 234 width = xsdo->pmWidth; 235 height = xsdo->pmHeight; 236 237 if (xsdo->bitmask == 0) { 238 /* create the bitmask if it is not yet created */ 239 xsdo->bitmask = XCreatePixmap(awt_display, 240 RootWindow(awt_display, screen), 241 width, height, 1); 242 if (xsdo->bitmask == 0) { 243 AWT_UNLOCK(); 244 if (!(*env)->ExceptionCheck(env)) 245 { 246 JNU_ThrowOutOfMemoryError(env, 247 "Cannot create bitmask for " 248 "offscreen surface"); 249 } 250 return; 251 } 252 } 253 254 /* Create a bitmask image and then blit it to the pixmap. */ 255 image = XCreateImage(awt_display, DefaultVisual(awt_display, screen), 256 1, XYBitmap, 0, NULL, width, height, 32, 0); 257 if (image == NULL) { 258 AWT_UNLOCK(); 259 if (!(*env)->ExceptionCheck(env)) 260 { 261 JNU_ThrowOutOfMemoryError(env, "Cannot allocate bitmask for mask"); 262 } 263 return; 264 } 265 dstScan = image->bytes_per_line; 266 image->data = malloc(dstScan * height); 267 if (image->data == NULL) { 268 XFree(image); 269 AWT_UNLOCK(); 270 if (!(*env)->ExceptionCheck(env)) 271 { 272 JNU_ThrowOutOfMemoryError(env, "Cannot allocate bitmask for mask"); 273 } 274 return; 275 } 276 pDst = (unsigned char *)image->data; 277 278 srcInfo.bounds.x1 = 0; 279 srcInfo.bounds.y1 = 0; 280 srcInfo.bounds.x2 = width; 281 srcInfo.bounds.y2 = height; 282 283 flags = (isICM ? (SD_LOCK_LUT | SD_LOCK_READ) : SD_LOCK_READ); 284 if (srcOps->Lock(env, srcOps, &srcInfo, flags) != SD_SUCCESS) { 285 XDestroyImage(image); 286 AWT_UNLOCK(); 287 return; 288 } 289 srcOps->GetRasInfo(env, srcOps, &srcInfo); 290 291 rowCount = height; 292 if (isICM) { 293 unsigned char *pSrc; 294 jint *srcLut; 295 296 srcScan = srcInfo.scanStride; 297 srcLut = srcInfo.lutBase; 298 pSrc = (unsigned char *)srcInfo.rasBase; 299 300 if (image->bitmap_bit_order == MSBFirst) { 301 do { 302 int x = 0, bx = 0; 303 unsigned int pix = 0; 304 unsigned int bit = 0x80; 305 unsigned char *srcPixel = pSrc; 306 do { 307 if (bit == 0) { 308 pDst[bx++] = (unsigned char)pix; 309 pix = 0; 310 bit = 0x80; 311 } 312 pix |= bit & (srcLut[*srcPixel++] >> 31); 313 bit >>= 1; 314 } while (++x < width); 315 pDst[bx] = (unsigned char)pix; 316 pDst += dstScan; 317 pSrc = (unsigned char *) (((intptr_t)pSrc) + srcScan); 318 } while (--rowCount > 0); 319 } else { 320 do { 321 int x = 0, bx = 0; 322 unsigned int pix = 0; 323 unsigned int bit = 1; 324 unsigned char *srcPixel = pSrc; 325 do { 326 if ((bit >> 8) != 0) { 327 pDst[bx++] = (unsigned char) pix; 328 pix = 0; 329 bit = 1; 330 } 331 pix |= bit & (srcLut[*srcPixel++] >> 31); 332 bit <<= 1; 333 } while (++x < width); 334 pDst[bx] = (unsigned char) pix; 335 pDst += dstScan; 336 pSrc = (unsigned char *) (((intptr_t)pSrc) + srcScan); 337 } while (--rowCount > 0); 338 } 339 } else /*DCM with ARGB*/ { 340 unsigned int *pSrc; 341 342 /* this is a number of pixels in a row, not number of bytes */ 343 srcScan = srcInfo.scanStride; 344 pSrc = (unsigned int *)srcInfo.rasBase; 345 346 if (image->bitmap_bit_order == MSBFirst) { 347 do { 348 int x = 0, bx = 0; 349 unsigned int pix = 0; 350 unsigned int bit = 0x80; 351 int *srcPixel = (int *) pSrc; 352 do { 353 if (bit == 0) { 354 /* next word */ 355 pDst[bx++] = (unsigned char)pix; 356 pix = 0; 357 bit = 0x80; 358 } 359 if (*srcPixel++ & 0xff000000) { 360 /* if src pixel is opaque, set the bit in the bitmap */ 361 pix |= bit; 362 } 363 bit >>= 1; 364 } while (++x < width); 365 /* last pixels in a row */ 366 pDst[bx] = (unsigned char)pix; 367 368 pDst += dstScan; 369 pSrc = (unsigned int *) (((intptr_t)pSrc) + srcScan); 370 } while (--rowCount > 0); 371 } else { 372 do { 373 int x = 0, bx = 0; 374 unsigned int pix = 0; 375 unsigned int bit = 1; 376 int *srcPixel = (int *) pSrc; 377 do { 378 if ((bit >> 8) != 0) { 379 pDst[bx++] = (unsigned char)pix; 380 pix = 0; 381 bit = 1; 382 } 383 if (*srcPixel++ & 0xff000000) { 384 /* if src pixel is opaque, set the bit in the bitmap */ 385 pix |= bit; 386 } 387 bit <<= 1; 388 } while (++x < width); 389 pDst[bx] = (unsigned char)pix; 390 pDst += dstScan; 391 pSrc = (unsigned int *) (((intptr_t)pSrc) + srcScan); 392 } while (--rowCount > 0); 393 } 394 } 395 SurfaceData_InvokeRelease(env, srcOps, &srcInfo); 396 SurfaceData_InvokeUnlock(env, srcOps, &srcInfo); 397 398 xgc = XCreateGC(awt_display, xsdo->bitmask, 0L, NULL); 399 XSetForeground(awt_display, xgc, 1); 400 XSetBackground(awt_display, xgc, 0); 401 XPutImage(awt_display, xsdo->bitmask, xgc, 402 image, 0, 0, 0, 0, width, height); 403 404 XFreeGC(awt_display, xgc); 405 XDestroyImage(image); 406 407 AWT_UNLOCK(); 408 #endif /* !HEADLESS */ 409 }