1 /* 2 * Copyright (c) 1999, 2013, 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 "X11SurfaceData.h" 27 #include "GraphicsPrimitiveMgr.h" 28 #include "Region.h" 29 #include "Trace.h" 30 31 /* Needed to define intptr_t */ 32 #include "gdefs.h" 33 34 #include "jni_util.h" 35 #include "jvm_md.h" 36 #include "awt_Component.h" 37 #include "awt_GraphicsEnv.h" 38 39 #include <dlfcn.h> 40 41 #ifndef HEADLESS 42 43 /** 44 * This file contains support code for loops using the SurfaceData 45 * interface to talk to an X11 drawable from native code. 46 */ 47 48 typedef struct _X11RIPrivate { 49 jint lockType; 50 jint lockFlags; 51 XImage *img; 52 int x, y; 53 } X11RIPrivate; 54 55 #define XSD_MAX(a,b) ((a) > (b) ? (a) : (b)) 56 #define XSD_MIN(a,b) ((a) < (b) ? (a) : (b)) 57 58 static LockFunc X11SD_Lock; 59 static GetRasInfoFunc X11SD_GetRasInfo; 60 static UnlockFunc X11SD_Unlock; 61 static DisposeFunc X11SD_Dispose; 62 static GetPixmapBgFunc X11SD_GetPixmapWithBg; 63 static ReleasePixmapBgFunc X11SD_ReleasePixmapWithBg; 64 extern int XShmAttachXErrHandler(Display *display, XErrorEvent *xerr); 65 extern AwtGraphicsConfigDataPtr 66 getGraphicsConfigFromComponentPeer(JNIEnv *env, jobject this); 67 extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs; 68 69 static int X11SD_FindClip(SurfaceDataBounds *b, SurfaceDataBounds *bounds, 70 X11SDOps *xsdo); 71 static int X11SD_ClipToRoot(SurfaceDataBounds *b, SurfaceDataBounds *bounds, 72 X11SDOps *xsdo); 73 static void X11SD_SwapBytes(X11SDOps *xsdo, XImage *img, int depth, int bpp); 74 static XImage * X11SD_GetImage(JNIEnv *env, X11SDOps *xsdo, 75 SurfaceDataBounds *bounds, 76 jint lockFlags); 77 78 extern jfieldID validID; 79 80 static int nativeByteOrder; 81 static jclass xorCompClass; 82 83 jint useMitShmExt = CANT_USE_MITSHM; 84 jint useMitShmPixmaps = CANT_USE_MITSHM; 85 jint forceSharedPixmaps = JNI_FALSE; 86 int mitShmPermissionMask = MITSHM_PERM_OWNER; 87 88 /* Cached shared image, one for all surface datas. */ 89 static XImage * cachedXImage; 90 91 #endif /* !HEADLESS */ 92 93 jboolean XShared_initIDs(JNIEnv *env, jboolean allowShmPixmaps) 94 { 95 #ifndef HEADLESS 96 union { 97 char c[4]; 98 int i; 99 } endian; 100 101 endian.i = 0xff000000; 102 nativeByteOrder = (endian.c[0]) ? MSBFirst : LSBFirst; 103 104 cachedXImage = NULL; 105 106 if (sizeof(X11RIPrivate) > SD_RASINFO_PRIVATE_SIZE) { 107 JNU_ThrowInternalError(env, "Private RasInfo structure too large!"); 108 return JNI_FALSE; 109 } 110 111 #ifdef MITSHM 112 if (getenv("NO_AWT_MITSHM") == NULL && 113 getenv("NO_J2D_MITSHM") == NULL) { 114 char * force; 115 char * permission = getenv("J2D_MITSHM_PERMISSION"); 116 if (permission != NULL) { 117 if (strcmp(permission, "common") == 0) { 118 mitShmPermissionMask = MITSHM_PERM_COMMON; 119 } 120 } 121 122 TryInitMITShm(env, &useMitShmExt, &useMitShmPixmaps); 123 124 if(allowShmPixmaps) { 125 useMitShmPixmaps = (useMitShmPixmaps == CAN_USE_MITSHM); 126 force = getenv("J2D_PIXMAPS"); 127 if (force != NULL) { 128 if (useMitShmPixmaps && (strcmp(force, "shared") == 0)) { 129 forceSharedPixmaps = JNI_TRUE; 130 } else if (strcmp(force, "server") == 0) { 131 useMitShmPixmaps = JNI_FALSE; 132 } 133 } 134 }else { 135 useMitShmPixmaps = JNI_FALSE; 136 } 137 } 138 #endif /* MITSHM */ 139 140 #endif /* !HEADLESS */ 141 142 return JNI_TRUE; 143 } 144 145 146 /* 147 * Class: sun_java2d_x11_X11SurfaceData 148 * Method: initIDs 149 * Signature: (Ljava/lang/Class;Z)V 150 */ 151 JNIEXPORT void JNICALL 152 Java_sun_java2d_x11_X11SurfaceData_initIDs(JNIEnv *env, jclass xsd, 153 jclass XORComp) 154 { 155 #ifndef HEADLESS 156 if(XShared_initIDs(env, JNI_TRUE)) 157 { 158 xorCompClass = (*env)->NewGlobalRef(env, XORComp); 159 } 160 #endif /* !HEADLESS */ 161 } 162 163 /* 164 * Class: sun_java2d_x11_X11SurfaceData 165 * Method: isDrawableValid 166 * Signature: ()Z 167 */ 168 JNIEXPORT jboolean JNICALL 169 Java_sun_java2d_x11_XSurfaceData_isDrawableValid(JNIEnv *env, jobject this) 170 { 171 jboolean ret = JNI_FALSE; 172 173 #ifndef HEADLESS 174 X11SDOps *xsdo = X11SurfaceData_GetOps(env, this); 175 176 AWT_LOCK(); 177 if (xsdo->drawable != 0 || X11SD_InitWindow(env, xsdo) == SD_SUCCESS) { 178 ret = JNI_TRUE; 179 } 180 AWT_UNLOCK(); 181 #endif /* !HEADLESS */ 182 183 return ret; 184 } 185 186 /* 187 * Class: sun_java2d_x11_X11SurfaceData 188 * Method: isShmPMAvailable 189 * Signature: ()Z 190 */ 191 JNIEXPORT jboolean JNICALL 192 Java_sun_java2d_x11_X11SurfaceData_isShmPMAvailable(JNIEnv *env, jobject this) 193 { 194 #if defined(HEADLESS) || !defined(MITSHM) 195 return JNI_FALSE; 196 #else 197 return (jboolean)useMitShmPixmaps; 198 #endif /* HEADLESS, MITSHM */ 199 } 200 201 /* 202 * Class: sun_java2d_x11_X11SurfaceData 203 * Method: initOps 204 * Signature: (Ljava/lang/Object;I)V 205 */ 206 JNIEXPORT void JNICALL 207 Java_sun_java2d_x11_XSurfaceData_initOps(JNIEnv *env, jobject xsd, 208 jobject peer, 209 jobject graphicsConfig, jint depth) 210 { 211 #ifndef HEADLESS 212 X11SDOps *xsdo = (X11SDOps*)SurfaceData_InitOps(env, xsd, sizeof(X11SDOps)); 213 jboolean hasException; 214 if (xsdo == NULL) { 215 JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed."); 216 return; 217 } 218 xsdo->sdOps.Lock = X11SD_Lock; 219 xsdo->sdOps.GetRasInfo = X11SD_GetRasInfo; 220 xsdo->sdOps.Unlock = X11SD_Unlock; 221 xsdo->sdOps.Dispose = X11SD_Dispose; 222 xsdo->GetPixmapWithBg = X11SD_GetPixmapWithBg; 223 xsdo->ReleasePixmapWithBg = X11SD_ReleasePixmapWithBg; 224 if (peer != NULL) { 225 xsdo->drawable = JNU_CallMethodByName(env, &hasException, peer, "getWindow", "()J").j; 226 if (hasException) { 227 return; 228 } 229 } else { 230 xsdo->drawable = 0; 231 } 232 xsdo->depth = depth; 233 xsdo->isPixmap = JNI_FALSE; 234 xsdo->bitmask = 0; 235 xsdo->bgPixel = 0; 236 xsdo->isBgInitialized = JNI_FALSE; 237 #ifdef MITSHM 238 xsdo->shmPMData.shmSegInfo = NULL; 239 xsdo->shmPMData.xRequestSent = JNI_FALSE; 240 xsdo->shmPMData.pmSize = 0; 241 xsdo->shmPMData.usingShmPixmap = JNI_FALSE; 242 xsdo->shmPMData.pixmap = 0; 243 xsdo->shmPMData.shmPixmap = 0; 244 xsdo->shmPMData.numBltsSinceRead = 0; 245 xsdo->shmPMData.pixelsReadSinceBlt = 0; 246 xsdo->shmPMData.numBltsThreshold = 2; 247 #endif /* MITSHM */ 248 249 xsdo->configData = (AwtGraphicsConfigDataPtr) 250 JNU_GetLongFieldAsPtr(env, 251 graphicsConfig, 252 x11GraphicsConfigIDs.aData); 253 if (xsdo->configData == NULL) { 254 JNU_ThrowNullPointerException(env, 255 "Native GraphicsConfig data block missing"); 256 return; 257 } 258 if (depth > 12) { 259 xsdo->pixelmask = (xsdo->configData->awt_visInfo.red_mask | 260 xsdo->configData->awt_visInfo.green_mask | 261 xsdo->configData->awt_visInfo.blue_mask); 262 } else if (depth == 12) { 263 xsdo->pixelmask = 0xfff; 264 } else { 265 xsdo->pixelmask = 0xff; 266 } 267 268 xsdo->xrPic = None; 269 #endif /* !HEADLESS */ 270 } 271 272 /* 273 * Class: sun_java2d_x11_X11SurfaceData 274 * Method: flushNativeSurface 275 * Signature: ()V 276 */ 277 JNIEXPORT void JNICALL 278 Java_sun_java2d_x11_XSurfaceData_flushNativeSurface(JNIEnv *env, jobject xsd) 279 { 280 #ifndef HEADLESS 281 SurfaceDataOps *ops = SurfaceData_GetOps(env, xsd); 282 283 if (ops != NULL) { 284 X11SD_Dispose(env, ops); 285 } 286 #endif /* !HEADLESS */ 287 } 288 289 290 JNIEXPORT X11SDOps * JNICALL 291 X11SurfaceData_GetOps(JNIEnv *env, jobject sData) 292 { 293 #ifdef HEADLESS 294 return NULL; 295 #else 296 SurfaceDataOps *ops = SurfaceData_GetOps(env, sData); 297 if (ops != NULL && ops->Lock != X11SD_Lock) { 298 SurfaceData_ThrowInvalidPipeException(env, "not an X11 SurfaceData"); 299 ops = NULL; 300 } 301 return (X11SDOps *) ops; 302 #endif /* !HEADLESS */ 303 } 304 305 /* 306 * Method for disposing X11SD-specific data 307 */ 308 static void 309 X11SD_Dispose(JNIEnv *env, SurfaceDataOps *ops) 310 { 311 #ifndef HEADLESS 312 /* ops is assumed non-null as it is checked in SurfaceData_DisposeOps */ 313 X11SDOps * xsdo = (X11SDOps*)ops; 314 315 AWT_LOCK(); 316 317 xsdo->invalid = JNI_TRUE; 318 319 if (xsdo->xrPic != None) { 320 XRenderFreePicture(awt_display, xsdo->xrPic); 321 xsdo->xrPic = None; 322 } 323 324 if (xsdo->isPixmap == JNI_TRUE && xsdo->drawable != 0) { 325 #ifdef MITSHM 326 if (xsdo->shmPMData.shmSegInfo != NULL) { 327 X11SD_DropSharedSegment(xsdo->shmPMData.shmSegInfo); 328 xsdo->shmPMData.shmSegInfo = NULL; 329 } 330 if (xsdo->shmPMData.pixmap) { 331 XFreePixmap(awt_display, xsdo->shmPMData.pixmap); 332 xsdo->shmPMData.pixmap = 0; 333 } 334 if (xsdo->shmPMData.shmPixmap) { 335 XFreePixmap(awt_display, xsdo->shmPMData.shmPixmap); 336 xsdo->shmPMData.shmPixmap = 0; 337 } 338 #else 339 XFreePixmap(awt_display, xsdo->drawable); 340 #endif /* MITSHM */ 341 xsdo->drawable = 0; 342 } 343 if (xsdo->bitmask != 0) { 344 XFreePixmap(awt_display, xsdo->bitmask); 345 xsdo->bitmask = 0; 346 } 347 if (xsdo->javaGC != NULL) { 348 XFreeGC(awt_display, xsdo->javaGC); 349 xsdo->javaGC = NULL; 350 } 351 if (xsdo->cachedGC != NULL) { 352 XFreeGC(awt_display, xsdo->cachedGC); 353 xsdo->cachedGC = NULL; 354 } 355 356 if(xsdo->xrPic != None) { 357 XRenderFreePicture(awt_display, xsdo->xrPic); 358 } 359 360 AWT_UNLOCK(); 361 #endif /* !HEADLESS */ 362 } 363 /* 364 * Class: sun_java2d_x11_X11SurfaceData 365 * Method: setInvalid 366 * Signature: ()V 367 */ 368 JNIEXPORT void JNICALL 369 Java_sun_java2d_x11_XSurfaceData_setInvalid(JNIEnv *env, jobject xsd) 370 { 371 #ifndef HEADLESS 372 X11SDOps *xsdo = (X11SDOps *) SurfaceData_GetOps(env, xsd); 373 374 if (xsdo != NULL) { 375 xsdo->invalid = JNI_TRUE; 376 } 377 #endif /* !HEADLESS */ 378 } 379 380 381 jboolean XShared_initSurface(JNIEnv *env, X11SDOps *xsdo, jint depth, jint width, jint height, jlong drawable) 382 { 383 #ifndef HEADLESS 384 385 if (drawable != (jlong)0) { 386 /* Double-buffering */ 387 xsdo->drawable = drawable; 388 xsdo->isPixmap = JNI_FALSE; 389 } else { 390 /* 391 * width , height must be nonzero otherwise XCreatePixmap 392 * generates BadValue in error_handler 393 */ 394 if (width <= 0 || height <= 0 || width > 32767 || height > 32767) { 395 JNU_ThrowOutOfMemoryError(env, 396 "Can't create offscreen surface"); 397 return JNI_FALSE; 398 } 399 xsdo->isPixmap = JNI_TRUE; 400 401 xsdo->pmWidth = width; 402 xsdo->pmHeight = height; 403 404 #ifdef MITSHM 405 xsdo->shmPMData.pmSize = width * height * depth; 406 xsdo->shmPMData.pixelsReadThreshold = width * height / 8; 407 if (forceSharedPixmaps) { 408 AWT_LOCK(); 409 xsdo->drawable = X11SD_CreateSharedPixmap(xsdo); 410 AWT_UNLOCK(); 411 JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); 412 if (xsdo->drawable) { 413 xsdo->shmPMData.usingShmPixmap = JNI_TRUE; 414 xsdo->shmPMData.shmPixmap = xsdo->drawable; 415 return JNI_TRUE; 416 } 417 } 418 #endif /* MITSHM */ 419 420 AWT_LOCK(); 421 xsdo->drawable = 422 XCreatePixmap(awt_display, 423 RootWindow(awt_display, 424 xsdo->configData->awt_visInfo.screen), 425 width, height, depth); 426 AWT_UNLOCK(); 427 JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); 428 #ifdef MITSHM 429 xsdo->shmPMData.usingShmPixmap = JNI_FALSE; 430 xsdo->shmPMData.pixmap = xsdo->drawable; 431 #endif /* MITSHM */ 432 } 433 if (xsdo->drawable == 0) { 434 JNU_ThrowOutOfMemoryError(env, 435 "Can't create offscreen surface"); 436 return JNI_FALSE; 437 } 438 439 #endif /* !HEADLESS */ 440 return JNI_TRUE; 441 } 442 443 444 /* 445 * Class: sun_java2d_x11_X11SurfaceData 446 * Method: initSurface 447 * Signature: ()V 448 */ 449 JNIEXPORT void JNICALL 450 Java_sun_java2d_x11_X11SurfaceData_initSurface(JNIEnv *env, jclass xsd, 451 jint depth, 452 jint width, jint height, 453 jlong drawable) 454 { 455 #ifndef HEADLESS 456 X11SDOps *xsdo = X11SurfaceData_GetOps(env, xsd); 457 if (xsdo == NULL) { 458 return; 459 } 460 461 if (xsdo->configData->awt_cmap == (Colormap)NULL) { 462 awtJNI_CreateColorData(env, xsdo->configData, 1); 463 JNU_CHECK_EXCEPTION(env); 464 } 465 /* color_data will be initialized in awtJNI_CreateColorData for 466 8-bit visuals */ 467 xsdo->cData = xsdo->configData->color_data; 468 469 XShared_initSurface(env, xsdo, depth, width, height, drawable); 470 xsdo->xrPic = None; 471 #endif /* !HEADLESS */ 472 } 473 474 #ifndef HEADLESS 475 476 #ifdef MITSHM 477 478 void X11SD_DropSharedSegment(XShmSegmentInfo *shminfo) 479 { 480 if (shminfo != NULL) { 481 XShmDetach(awt_display, shminfo); 482 shmdt(shminfo->shmaddr); 483 /* REMIND: we don't need shmctl(shminfo->shmid, IPC_RMID, 0); here. */ 484 /* Check X11SD_CreateSharedImage() for the explanation */ 485 } 486 } 487 488 XImage* X11SD_CreateSharedImage(X11SDOps *xsdo, 489 jint width, jint height) 490 { 491 XImage *img = NULL; 492 XShmSegmentInfo *shminfo; 493 494 shminfo = malloc(sizeof(XShmSegmentInfo)); 495 if (shminfo == NULL) { 496 return NULL; 497 } 498 memset(shminfo, 0, sizeof(XShmSegmentInfo)); 499 500 img = XShmCreateImage(awt_display, xsdo->configData->awt_visInfo.visual, 501 xsdo->depth, ZPixmap, NULL, shminfo, 502 width, height); 503 if (img == NULL) { 504 free((void *)shminfo); 505 return NULL; 506 } 507 shminfo->shmid = 508 shmget(IPC_PRIVATE, height * img->bytes_per_line, 509 IPC_CREAT|mitShmPermissionMask); 510 if (shminfo->shmid < 0) { 511 J2dRlsTraceLn1(J2D_TRACE_ERROR, 512 "X11SD_SetupSharedSegment shmget has failed: %s", 513 strerror(errno)); 514 free((void *)shminfo); 515 XDestroyImage(img); 516 return NULL; 517 } 518 519 shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); 520 if (shminfo->shmaddr == ((char *) -1)) { 521 shmctl(shminfo->shmid, IPC_RMID, 0); 522 J2dRlsTraceLn1(J2D_TRACE_ERROR, 523 "X11SD_SetupSharedSegment shmat has failed: %s", 524 strerror(errno)); 525 free((void *)shminfo); 526 XDestroyImage(img); 527 return NULL; 528 } 529 530 shminfo->readOnly = False; 531 532 resetXShmAttachFailed(); 533 EXEC_WITH_XERROR_HANDLER(XShmAttachXErrHandler, 534 XShmAttach(awt_display, shminfo)); 535 536 /* 537 * Once the XSync round trip has finished then we 538 * can get rid of the id so that this segment does not stick 539 * around after we go away, holding system resources. 540 */ 541 shmctl(shminfo->shmid, IPC_RMID, 0); 542 543 if (isXShmAttachFailed() == JNI_TRUE) { 544 J2dRlsTraceLn1(J2D_TRACE_ERROR, 545 "X11SD_SetupSharedSegment XShmAttach has failed: %s", 546 strerror(errno)); 547 shmdt(shminfo->shmaddr); 548 free((void *)shminfo); 549 XDestroyImage(img); 550 return NULL; 551 } 552 553 img->data = shminfo->shmaddr; 554 img->obdata = (char *)shminfo; 555 556 return img; 557 } 558 559 XImage* X11SD_GetSharedImage(X11SDOps *xsdo, jint width, jint height, 560 jint maxWidth, jint maxHeight, jboolean readBits) 561 { 562 XImage * retImage = NULL; 563 if (cachedXImage != NULL && 564 X11SD_CachedXImageFits(width, height, maxWidth, maxHeight, 565 xsdo->depth, readBits)) { 566 /* sync so previous data gets flushed */ 567 XSync(awt_display, False); 568 retImage = cachedXImage; 569 cachedXImage = (XImage *)NULL; 570 } else if (width * height * xsdo->depth > 0x10000) { 571 retImage = X11SD_CreateSharedImage(xsdo, width, height); 572 } 573 return retImage; 574 } 575 576 Drawable X11SD_CreateSharedPixmap(X11SDOps *xsdo) 577 { 578 XShmSegmentInfo *shminfo; 579 XImage *img = NULL; 580 Drawable pixmap; 581 int scan; 582 int width = xsdo->pmWidth; 583 int height = xsdo->pmHeight; 584 585 if (xsdo->shmPMData.pmSize < 0x10000) { 586 /* only use shared mem pixmaps for relatively big images */ 587 return 0; 588 } 589 590 /* need to create shared(!) image to get bytes_per_line */ 591 img = X11SD_CreateSharedImage(xsdo, width, height); 592 if (img == NULL) { 593 return 0; 594 } 595 scan = img->bytes_per_line; 596 shminfo = (XShmSegmentInfo*)img->obdata; 597 XFree(img); 598 599 pixmap = 600 XShmCreatePixmap(awt_display, 601 RootWindow(awt_display, 602 xsdo->configData->awt_visInfo.screen), 603 shminfo->shmaddr, shminfo, 604 width, height, xsdo->depth); 605 if (pixmap == 0) { 606 X11SD_DropSharedSegment(shminfo); 607 return 0; 608 } 609 610 xsdo->shmPMData.shmSegInfo = shminfo; 611 xsdo->shmPMData.bytesPerLine = scan; 612 return pixmap; 613 } 614 615 void X11SD_PuntPixmap(X11SDOps *xsdo, jint width, jint height) 616 { 617 618 if (useMitShmPixmaps != CAN_USE_MITSHM || forceSharedPixmaps) { 619 return; 620 } 621 622 /* we wouldn't be here if it's a shared pixmap, so no check 623 * for !usingShmPixmap. 624 */ 625 626 xsdo->shmPMData.numBltsSinceRead = 0; 627 628 xsdo->shmPMData.pixelsReadSinceBlt += width * height; 629 if (xsdo->shmPMData.pixelsReadSinceBlt > 630 xsdo->shmPMData.pixelsReadThreshold) { 631 if (!xsdo->shmPMData.shmPixmap) { 632 xsdo->shmPMData.shmPixmap = 633 X11SD_CreateSharedPixmap(xsdo); 634 } 635 if (xsdo->shmPMData.shmPixmap) { 636 GC xgc = XCreateGC(awt_display, xsdo->shmPMData.shmPixmap, 0L, NULL); 637 if (xgc != NULL) { 638 xsdo->shmPMData.usingShmPixmap = JNI_TRUE; 639 xsdo->drawable = xsdo->shmPMData.shmPixmap; 640 XCopyArea(awt_display, 641 xsdo->shmPMData.pixmap, xsdo->drawable, xgc, 642 0, 0, xsdo->pmWidth, xsdo->pmHeight, 0, 0); 643 XSync(awt_display, False); 644 xsdo->shmPMData.xRequestSent = JNI_FALSE; 645 XFreeGC(awt_display, xgc); 646 } 647 } 648 } 649 } 650 651 void X11SD_UnPuntPixmap(X11SDOps *xsdo) 652 { 653 if (useMitShmPixmaps != CAN_USE_MITSHM || forceSharedPixmaps) { 654 return; 655 } 656 xsdo->shmPMData.pixelsReadSinceBlt = 0; 657 if (xsdo->shmPMData.numBltsSinceRead >= 658 xsdo->shmPMData.numBltsThreshold) 659 { 660 if (xsdo->shmPMData.usingShmPixmap) { 661 if (!xsdo->shmPMData.pixmap) { 662 xsdo->shmPMData.pixmap = 663 XCreatePixmap(awt_display, 664 RootWindow(awt_display, 665 xsdo->configData->awt_visInfo.screen), 666 xsdo->pmWidth, xsdo->pmHeight, xsdo->depth); 667 } 668 if (xsdo->shmPMData.pixmap) { 669 GC xgc = XCreateGC(awt_display, xsdo->shmPMData.pixmap, 0L, NULL); 670 if (xgc != NULL) { 671 xsdo->drawable = xsdo->shmPMData.pixmap; 672 XCopyArea(awt_display, 673 xsdo->shmPMData.shmPixmap, xsdo->drawable, xgc, 674 0, 0, xsdo->pmWidth, xsdo->pmHeight, 0, 0); 675 XSync(awt_display, False); 676 XFreeGC(awt_display, xgc); 677 xsdo->shmPMData.xRequestSent = JNI_FALSE; 678 xsdo->shmPMData.usingShmPixmap = JNI_FALSE; 679 xsdo->shmPMData.numBltsThreshold *= 2; 680 } 681 } 682 } 683 } else { 684 xsdo->shmPMData.numBltsSinceRead++; 685 } 686 } 687 688 /** 689 * Determines if the cached image can be used for current operation. 690 * If the image is to be used to be read into by XShmGetImage, 691 * it must be close enough to avoid excessive reading from the screen; 692 * otherwise it should just be at least the size requested. 693 */ 694 jboolean X11SD_CachedXImageFits(jint width, jint height, jint maxWidth, 695 jint maxHeight, jint depth, jboolean readBits) 696 { 697 /* we assume here that the cached image exists */ 698 jint imgWidth = cachedXImage->width; 699 jint imgHeight = cachedXImage->height; 700 701 if (imgWidth < width || imgHeight < height || depth != cachedXImage->depth) { 702 /* doesn't fit if any of the cached image dimensions is smaller 703 or the depths are different */ 704 return JNI_FALSE; 705 } 706 707 if (!readBits) { 708 /* Not reading from this image, so any image at least of the 709 size requested will do */ 710 return JNI_TRUE; 711 } 712 713 if ((imgWidth < width + 64) && (imgHeight < height + 64) 714 && imgWidth <= maxWidth && imgHeight <= maxHeight) 715 { 716 /* Cached image's width/height shouldn't be more than 64 pixels 717 * larger than requested, because the region in XShmGetImage 718 * can't be specified and we don't want to read too much. 719 * Furthermore it has to be smaller than maxWidth/Height 720 * so drawables are not read out of bounds. 721 */ 722 return JNI_TRUE; 723 } 724 725 return JNI_FALSE; 726 } 727 #endif /* MITSHM */ 728 729 jint X11SD_InitWindow(JNIEnv *env, X11SDOps *xsdo) 730 { 731 if (xsdo->isPixmap == JNI_TRUE) { 732 return SD_FAILURE; 733 } 734 xsdo->cData = xsdo->configData->color_data; 735 736 return SD_SUCCESS; 737 } 738 739 static jint X11SD_Lock(JNIEnv *env, 740 SurfaceDataOps *ops, 741 SurfaceDataRasInfo *pRasInfo, 742 jint lockflags) 743 { 744 X11SDOps *xsdo = (X11SDOps *) ops; 745 X11RIPrivate *xpriv = (X11RIPrivate *) &(pRasInfo->priv); 746 int ret = SD_SUCCESS; 747 748 AWT_LOCK(); 749 750 if (xsdo->invalid) { 751 AWT_UNLOCK(); 752 SurfaceData_ThrowInvalidPipeException(env, "bounds changed"); 753 return SD_FAILURE; 754 } 755 xsdo->cData = xsdo->configData->color_data; 756 if (xsdo->drawable == 0 && X11SD_InitWindow(env, xsdo) == SD_FAILURE) { 757 AWT_UNLOCK(); 758 return SD_FAILURE; 759 } 760 if ((lockflags & SD_LOCK_LUT) != 0 && 761 (xsdo->cData == NULL || 762 xsdo->cData->awt_icmLUT == NULL)) 763 { 764 AWT_UNLOCK(); 765 if (!(*env)->ExceptionCheck(env)) 766 { 767 JNU_ThrowNullPointerException(env, "colormap lookup table"); 768 } 769 return SD_FAILURE; 770 } 771 if ((lockflags & SD_LOCK_INVCOLOR) != 0 && 772 (xsdo->cData == NULL || 773 xsdo->cData->img_clr_tbl == NULL || 774 xsdo->cData->img_oda_red == NULL || 775 xsdo->cData->img_oda_green == NULL || 776 xsdo->cData->img_oda_blue == NULL)) 777 { 778 AWT_UNLOCK(); 779 if (!(*env)->ExceptionCheck(env)) 780 { 781 JNU_ThrowNullPointerException(env, "inverse colormap lookup table"); 782 } 783 return SD_FAILURE; 784 } 785 if ((lockflags & SD_LOCK_INVGRAY) != 0 && 786 (xsdo->cData == NULL || 787 xsdo->cData->pGrayInverseLutData == NULL)) 788 { 789 AWT_UNLOCK(); 790 if (!(*env)->ExceptionCheck(env)) 791 { 792 JNU_ThrowNullPointerException(env, "inverse gray lookup table"); 793 } 794 return SD_FAILURE; 795 } 796 if (lockflags & SD_LOCK_RD_WR) { 797 if (lockflags & SD_LOCK_FASTEST) { 798 ret = SD_SLOWLOCK; 799 } 800 xpriv->lockType = X11SD_LOCK_BY_XIMAGE; 801 if (xsdo->isPixmap) { 802 #ifdef MITSHM 803 if (xsdo->shmPMData.usingShmPixmap) { 804 xpriv->lockType = X11SD_LOCK_BY_SHMEM; 805 } 806 #endif /* MITSHM */ 807 if (pRasInfo->bounds.x1 < 0) { 808 pRasInfo->bounds.x1 = 0; 809 } 810 if (pRasInfo->bounds.y1 < 0) { 811 pRasInfo->bounds.y1 = 0; 812 } 813 if (pRasInfo->bounds.x2 > xsdo->pmWidth) { 814 pRasInfo->bounds.x2 = xsdo->pmWidth; 815 } 816 if (pRasInfo->bounds.y2 > xsdo->pmHeight) { 817 pRasInfo->bounds.y2 = xsdo->pmHeight; 818 } 819 } 820 } else { 821 /* They didn't lock for anything - we won't give them anything */ 822 xpriv->lockType = X11SD_LOCK_BY_NULL; 823 } 824 xpriv->lockFlags = lockflags; 825 xpriv->img = NULL; 826 827 return ret; 828 /* AWT_UNLOCK() called in Unlock */ 829 } 830 831 static void X11SD_GetRasInfo(JNIEnv *env, 832 SurfaceDataOps *ops, 833 SurfaceDataRasInfo *pRasInfo) 834 { 835 X11SDOps *xsdo = (X11SDOps *) ops; 836 X11RIPrivate *xpriv = (X11RIPrivate *) &(pRasInfo->priv); 837 jint lockFlags = xpriv->lockFlags; 838 jint depth = xsdo->depth; 839 int mult = xsdo->configData->pixelStride; 840 841 842 #ifdef MITSHM 843 if (xpriv->lockType == X11SD_LOCK_BY_SHMEM) { 844 if (xsdo->shmPMData.xRequestSent == JNI_TRUE) { 845 /* need to sync before using shared mem pixmap 846 if any x calls were issued for this pixmap */ 847 XSync(awt_display, False); 848 xsdo->shmPMData.xRequestSent = JNI_FALSE; 849 } 850 xpriv->x = pRasInfo->bounds.x1; 851 xpriv->y = pRasInfo->bounds.y1; 852 pRasInfo->rasBase = xsdo->shmPMData.shmSegInfo->shmaddr; 853 pRasInfo->pixelStride = mult; 854 pRasInfo->pixelBitOffset = 0; 855 pRasInfo->scanStride = xsdo->shmPMData.bytesPerLine; 856 } else 857 #endif /* MITSHM */ 858 if (xpriv->lockType == X11SD_LOCK_BY_XIMAGE) { 859 int x, y, w, h; 860 x = pRasInfo->bounds.x1; 861 y = pRasInfo->bounds.y1; 862 w = pRasInfo->bounds.x2 - x; 863 h = pRasInfo->bounds.y2 - y; 864 865 xpriv->img = X11SD_GetImage(env, xsdo, &pRasInfo->bounds, lockFlags); 866 if (xpriv->img) { 867 int scan = xpriv->img->bytes_per_line; 868 xpriv->x = x; 869 xpriv->y = y; 870 pRasInfo->rasBase = xpriv->img->data - x * mult - y * scan; 871 pRasInfo->pixelStride = mult; 872 pRasInfo->pixelBitOffset = 0; 873 pRasInfo->scanStride = scan; 874 } else { 875 pRasInfo->rasBase = NULL; 876 pRasInfo->pixelStride = 0; 877 pRasInfo->pixelBitOffset = 0; 878 pRasInfo->scanStride = 0; 879 } 880 } else { 881 /* They didn't lock for anything - we won't give them anything */ 882 pRasInfo->rasBase = NULL; 883 pRasInfo->pixelStride = 0; 884 pRasInfo->pixelBitOffset = 0; 885 pRasInfo->scanStride = 0; 886 } 887 if (lockFlags & SD_LOCK_LUT) { 888 pRasInfo->lutBase = (jint *) xsdo->cData->awt_icmLUT; 889 pRasInfo->lutSize = xsdo->cData->awt_numICMcolors; 890 } else { 891 pRasInfo->lutBase = NULL; 892 pRasInfo->lutSize = 0; 893 } 894 if (lockFlags & SD_LOCK_INVCOLOR) { 895 pRasInfo->invColorTable = xsdo->cData->img_clr_tbl; 896 pRasInfo->redErrTable = xsdo->cData->img_oda_red; 897 pRasInfo->grnErrTable = xsdo->cData->img_oda_green; 898 pRasInfo->bluErrTable = xsdo->cData->img_oda_blue; 899 } else { 900 pRasInfo->invColorTable = NULL; 901 pRasInfo->redErrTable = NULL; 902 pRasInfo->grnErrTable = NULL; 903 pRasInfo->bluErrTable = NULL; 904 } 905 if (lockFlags & SD_LOCK_INVGRAY) { 906 pRasInfo->invGrayTable = xsdo->cData->pGrayInverseLutData; 907 } else { 908 pRasInfo->invGrayTable = NULL; 909 } 910 } 911 912 static void X11SD_Unlock(JNIEnv *env, 913 SurfaceDataOps *ops, 914 SurfaceDataRasInfo *pRasInfo) 915 { 916 X11SDOps *xsdo = (X11SDOps *) ops; 917 X11RIPrivate *xpriv = (X11RIPrivate *) &(pRasInfo->priv); 918 919 if (xpriv->lockType == X11SD_LOCK_BY_XIMAGE && 920 xpriv->img != NULL) 921 { 922 if (xpriv->lockFlags & SD_LOCK_WRITE) { 923 int x = xpriv->x; 924 int y = xpriv->y; 925 int w = pRasInfo->bounds.x2 - x; 926 int h = pRasInfo->bounds.y2 - y; 927 Drawable drawable = xsdo->drawable; 928 GC xgc = xsdo->cachedGC; 929 if (xgc == NULL) { 930 xsdo->cachedGC = xgc = 931 XCreateGC(awt_display, drawable, 0L, NULL); 932 } 933 934 if (xpriv->img->byte_order != nativeByteOrder) { 935 /* switching bytes back in 24 and 32 bpp cases. */ 936 /* For 16 bit XLib will switch for us. */ 937 if (xsdo->depth > 16) { 938 X11SD_SwapBytes(xsdo, xpriv->img, xsdo->depth, 939 xsdo->configData->awtImage->wsImageFormat.bits_per_pixel); 940 } 941 } 942 943 #ifdef MITSHM 944 if (xpriv->img->obdata != NULL) { 945 XShmPutImage(awt_display, drawable, xgc, 946 xpriv->img, 0, 0, x, y, w, h, False); 947 XFlush(awt_display); 948 } else { 949 XPutImage(awt_display, drawable, xgc, 950 xpriv->img, 0, 0, x, y, w, h); 951 } 952 if (xsdo->shmPMData.usingShmPixmap) { 953 xsdo->shmPMData.xRequestSent = JNI_TRUE; 954 } 955 #else 956 XPutImage(awt_display, drawable, xgc, 957 xpriv->img, 0, 0, x, y, w, h); 958 #endif /* MITSHM */ 959 960 } 961 X11SD_DisposeOrCacheXImage(xpriv->img); 962 xpriv->img = (XImage *)NULL; 963 } 964 /* the background pixel is not valid anymore */ 965 if (xpriv->lockFlags & SD_LOCK_WRITE) { 966 xsdo->isBgInitialized = JNI_FALSE; 967 } 968 xpriv->lockType = X11SD_LOCK_UNLOCKED; 969 AWT_UNLOCK(); 970 } 971 972 static int 973 X11SD_ClipToRoot(SurfaceDataBounds *b, SurfaceDataBounds *bounds, 974 X11SDOps *xsdo) 975 { 976 short x1=0, y1=0, x2=0, y2=0; 977 int tmpx, tmpy; 978 Window tmpchild; 979 980 Window window = (Window)(xsdo->drawable); /* is always a Window */ 981 XWindowAttributes winAttr; 982 983 Status status = XGetWindowAttributes(awt_display, window, &winAttr); 984 if (status == 0) { 985 /* Failure, X window no longer valid. */ 986 return FALSE; 987 } 988 if (!XTranslateCoordinates(awt_display, window, 989 RootWindowOfScreen(winAttr.screen), 990 0, 0, &tmpx, &tmpy, &tmpchild)) { 991 return FALSE; 992 } 993 994 x1 = -(x1 + tmpx); 995 y1 = -(y1 + tmpy); 996 997 x2 = x1 + DisplayWidth(awt_display, xsdo->configData->awt_visInfo.screen); 998 y2 = y1 + DisplayHeight(awt_display, xsdo->configData->awt_visInfo.screen); 999 1000 x1 = XSD_MAX(bounds->x1, x1); 1001 y1 = XSD_MAX(bounds->y1, y1); 1002 x2 = XSD_MIN(bounds->x2, x2); 1003 y2 = XSD_MIN(bounds->y2, y2); 1004 if ((x1 >= x2) || (y1 >= y2)) { 1005 return FALSE; 1006 } 1007 b->x1 = x1; 1008 b->y1 = y1; 1009 b->x2 = x2; 1010 b->y2 = y2; 1011 1012 return TRUE; 1013 } 1014 1015 /* 1016 * x1, y1, x2, y2 - our rectangle in the coord system of 1017 * the widget 1018 * px1, xy1, px2, py2 - current parent rect coords in the 1019 * same system 1020 */ 1021 static int 1022 X11SD_FindClip(SurfaceDataBounds *b, SurfaceDataBounds *bounds, X11SDOps *xsdo) 1023 { 1024 return TRUE; 1025 } 1026 1027 static void 1028 X11SD_SwapBytes(X11SDOps *xsdo, XImage * img, int depth, int bpp) { 1029 int lengthInBytes = img->height * img->bytes_per_line; 1030 int i; 1031 1032 switch (depth) { 1033 case 12: 1034 case 15: 1035 case 16: 1036 { 1037 /* AB -> BA */ 1038 unsigned short *d = (unsigned short *)img->data; 1039 unsigned short t; 1040 for (i = 0; i < lengthInBytes/2; i++) { 1041 t = *d; 1042 *d++ = (t >> 8) | (t << 8); 1043 } 1044 img->byte_order = nativeByteOrder; 1045 img->bitmap_bit_order = nativeByteOrder; 1046 break; 1047 } 1048 case 24: 1049 { 1050 /* ABC -> CBA */ 1051 if (bpp == 24) { 1052 // 4517321: Only swap if we have a "real" ThreeByteBgr 1053 // visual (denoted by a red_mask of 0xff). Due to ambiguity 1054 // in the X11 spec, it appears that the swap is not required 1055 // on Linux configurations that use 24 bits per pixel (denoted 1056 // by a red_mask of 0xff0000). 1057 if (xsdo->configData->awt_visInfo.red_mask == 0xff) { 1058 int scan = img->bytes_per_line; 1059 unsigned char *d = (unsigned char *) img->data; 1060 unsigned char *d1; 1061 unsigned int t; 1062 int j; 1063 1064 for (i = 0; i < img->height; i++, d += scan) { 1065 d1 = d; 1066 for (j = 0; j < img->width; j++, d1 += 3) { 1067 /* not obvious opt from XLib src */ 1068 t = d1[0]; d1[0] = d1[2]; d1[2] = t; 1069 } 1070 } 1071 } 1072 break; 1073 } 1074 } 1075 /* FALL THROUGH for 32-bit case */ 1076 case 32: 1077 { 1078 /* ABCD -> DCBA */ 1079 unsigned int *d = (unsigned int *) img->data; 1080 unsigned int t; 1081 for (i = 0; i < lengthInBytes/4; i++) { 1082 t = *d; 1083 *d++ = ((t >> 24) | 1084 ((t >> 8) & 0xff00) | 1085 ((t & 0xff00) << 8) | 1086 (t << 24)); 1087 } 1088 break; 1089 } 1090 } 1091 } 1092 1093 static XImage * X11SD_GetImage(JNIEnv *env, X11SDOps *xsdo, 1094 SurfaceDataBounds *bounds, 1095 jint lockFlags) 1096 { 1097 int x, y, w, h, maxWidth, maxHeight; 1098 int scan; 1099 XImage * img = NULL; 1100 Drawable drawable; 1101 int depth = xsdo->depth; 1102 int mult = xsdo->configData->pixelStride; 1103 int pad = (mult == 3) ? 32 : mult * 8; // pad must be 8, 16, or 32 1104 jboolean readBits = lockFlags & SD_LOCK_NEED_PIXELS; 1105 1106 x = bounds->x1; 1107 y = bounds->y1; 1108 w = bounds->x2 - x; 1109 h = bounds->y2 - y; 1110 1111 #ifdef MITSHM 1112 if (useMitShmExt == CAN_USE_MITSHM) { 1113 if (xsdo->isPixmap) { 1114 if (readBits) { 1115 X11SD_PuntPixmap(xsdo, w, h); 1116 } 1117 maxWidth = xsdo->pmWidth; 1118 maxHeight = xsdo->pmHeight; 1119 } else { 1120 XWindowAttributes winAttr; 1121 if (XGetWindowAttributes(awt_display, 1122 (Window) xsdo->drawable, &winAttr) != 0) { 1123 maxWidth = winAttr.width; 1124 maxHeight = winAttr.height; 1125 } else { 1126 /* XGWA failed which isn't a good thing. Defaulting to using 1127 * x,y means that after the subtraction of these we will use 1128 * w=0, h=0 which is a reasonable default on such a failure. 1129 */ 1130 maxWidth = x; 1131 maxHeight = y; 1132 } 1133 } 1134 maxWidth -= x; 1135 maxHeight -= y; 1136 1137 img = X11SD_GetSharedImage(xsdo, w, h, maxWidth, maxHeight, readBits); 1138 } 1139 #endif /* MITSHM */ 1140 drawable = xsdo->drawable; 1141 1142 if (readBits) { 1143 #ifdef MITSHM 1144 if (img != NULL) { 1145 if (!XShmGetImage(awt_display, drawable, img, x, y, -1)) { 1146 X11SD_DisposeOrCacheXImage(img); 1147 img = NULL; 1148 } 1149 } 1150 if (img == NULL) { 1151 img = XGetImage(awt_display, drawable, x, y, w, h, -1, ZPixmap); 1152 if (img != NULL) { 1153 img->obdata = NULL; 1154 } 1155 } 1156 #else 1157 img = XGetImage(awt_display, drawable, x, y, w, h, -1, ZPixmap); 1158 #endif /* MITSHM */ 1159 if (img == NULL) { 1160 SurfaceDataBounds temp; 1161 img = XCreateImage(awt_display, 1162 xsdo->configData->awt_visInfo.visual, 1163 depth, ZPixmap, 0, NULL, w, h, pad, 0); 1164 if (img == NULL) { 1165 return NULL; 1166 } 1167 1168 scan = img->bytes_per_line; 1169 img->data = malloc(h * scan); 1170 if (img->data == NULL) { 1171 XFree(img); 1172 return NULL; 1173 } 1174 1175 if (xsdo->isPixmap == JNI_FALSE && 1176 X11SD_ClipToRoot(&temp, bounds, xsdo)) { 1177 1178 XImage * temp_image; 1179 temp_image = XGetImage(awt_display, drawable, 1180 temp.x1, temp.y1, 1181 temp.x2 - temp.x1, 1182 temp.y2 - temp.y1, 1183 -1, ZPixmap); 1184 if (temp_image == NULL) { 1185 XGrabServer(awt_display); 1186 if (X11SD_FindClip(&temp, bounds, xsdo)) { 1187 temp_image = 1188 XGetImage(awt_display, drawable, 1189 temp.x1, temp.y1, 1190 temp.x2 - temp.x1, 1191 temp.y2 - temp.y1, 1192 -1, ZPixmap); 1193 } 1194 XUngrabServer(awt_display); 1195 /* Workaround for bug 5039226 */ 1196 XSync(awt_display, False); 1197 } 1198 if (temp_image != NULL) { 1199 int temp_scan, bytes_to_copy; 1200 char * img_addr, * temp_addr; 1201 int i; 1202 1203 img_addr = img->data + 1204 (temp.y1 - y) * scan + (temp.x1 - x) * mult; 1205 temp_scan = temp_image->bytes_per_line; 1206 temp_addr = temp_image->data; 1207 bytes_to_copy = (temp.x2 - temp.x1) * mult; 1208 for (i = temp.y1; i < temp.y2; i++) { 1209 memcpy(img_addr, temp_addr, bytes_to_copy); 1210 img_addr += scan; 1211 temp_addr += temp_scan; 1212 } 1213 XDestroyImage(temp_image); 1214 } 1215 } 1216 img->obdata = NULL; 1217 } 1218 if (depth > 8 && img->byte_order != nativeByteOrder) { 1219 X11SD_SwapBytes(xsdo, img, depth, 1220 xsdo->configData->awtImage->wsImageFormat.bits_per_pixel); 1221 } 1222 } else { 1223 /* 1224 * REMIND: This might be better to move to the Lock function 1225 * to avoid lengthy I/O pauses inside what may be a critical 1226 * section. This will be more critical when SD_LOCK_READ is 1227 * implemented. Another solution is to cache the pixels 1228 * to avoid reading for every operation. 1229 */ 1230 if (img == NULL) { 1231 img = XCreateImage(awt_display, 1232 xsdo->configData->awt_visInfo.visual, 1233 depth, ZPixmap, 0, NULL, w, h, pad, 0); 1234 if (img == NULL) { 1235 return NULL; 1236 } 1237 1238 img->data = malloc(h * img->bytes_per_line); 1239 if (img->data == NULL) { 1240 XFree(img); 1241 return NULL; 1242 } 1243 1244 img->obdata = NULL; 1245 1246 if (img->byte_order != nativeByteOrder && 1247 (depth == 15 || depth == 16 || depth == 12)) { 1248 /* bytes will be swapped by XLib. */ 1249 img->byte_order = nativeByteOrder; 1250 img->bitmap_bit_order = nativeByteOrder; 1251 } 1252 } 1253 } 1254 return img; 1255 } 1256 1257 void X11SD_DisposeOrCacheXImage(XImage * image) { 1258 /* REMIND: might want to check if the new image worth caching. */ 1259 /* Cache only shared images. Passed image is assumed to be non-null. */ 1260 if (image->obdata != NULL) { 1261 if (cachedXImage != NULL) { 1262 X11SD_DisposeXImage(cachedXImage); 1263 } 1264 cachedXImage = image; 1265 } else { 1266 X11SD_DisposeXImage(image); 1267 } 1268 } 1269 1270 void X11SD_DisposeXImage(XImage * image) { 1271 if (image != NULL) { 1272 #ifdef MITSHM 1273 if (image->obdata != NULL) { 1274 X11SD_DropSharedSegment((XShmSegmentInfo*)image->obdata); 1275 image->obdata = NULL; 1276 } 1277 #endif /* MITSHM */ 1278 XDestroyImage(image); 1279 } 1280 } 1281 1282 void 1283 X11SD_DirectRenderNotify(JNIEnv *env, X11SDOps *xsdo) 1284 { 1285 #ifdef MITSHM 1286 if (xsdo->shmPMData.usingShmPixmap) { 1287 xsdo->shmPMData.xRequestSent = JNI_TRUE; 1288 } 1289 #endif /* MITSHM */ 1290 awt_output_flush(); 1291 } 1292 1293 /* 1294 * Sets transparent pixels in the pixmap to 1295 * the specified solid background color and returns it. 1296 * Doesn't update source pixmap unless the color of the 1297 * transparent pixels is different from the specified color. 1298 * 1299 * Note: The AWT lock must be held by the current thread 1300 * while calling into this method. 1301 */ 1302 static Drawable 1303 X11SD_GetPixmapWithBg(JNIEnv *env, X11SDOps *xsdo, jint pixel) 1304 { 1305 /* assert AWT_CHECK_HAVE_LOCK(); */ 1306 1307 if (xsdo->invalid) { 1308 AWT_UNLOCK(); 1309 SurfaceData_ThrowInvalidPipeException(env, "bounds changed"); 1310 return 0; 1311 } 1312 1313 /* the image doesn't have transparency, just return it */ 1314 if (xsdo->bitmask == 0) { 1315 /* don't need to unlock here, the caller will unlock through 1316 the release call */ 1317 return xsdo->drawable; 1318 } 1319 1320 /* Check if current color of the transparent pixels is different 1321 from the specified one */ 1322 if (xsdo->isBgInitialized == JNI_FALSE || xsdo->bgPixel != pixel) { 1323 GC srcGC; 1324 GC bmGC; 1325 1326 if (xsdo->drawable == 0) { 1327 AWT_UNLOCK(); 1328 return 0; 1329 } 1330 1331 bmGC = XCreateGC(awt_display, xsdo->bitmask, 0, NULL); 1332 if (bmGC == NULL) { 1333 AWT_UNLOCK(); 1334 return 0; 1335 } 1336 1337 /* invert the bitmask */ 1338 XSetFunction(awt_display, bmGC, GXxor); 1339 XSetForeground(awt_display, bmGC, 1); 1340 XFillRectangle(awt_display, xsdo->bitmask, bmGC, 1341 0, 0, xsdo->pmWidth, xsdo->pmHeight); 1342 1343 srcGC = XCreateGC(awt_display, xsdo->drawable, 0L, NULL); 1344 if (srcGC == NULL) { 1345 XFreeGC(awt_display, bmGC); 1346 AWT_UNLOCK(); 1347 return 0; 1348 } 1349 1350 /* set transparent pixels in the source pm to the bg color */ 1351 XSetClipMask(awt_display, srcGC, xsdo->bitmask); 1352 XSetForeground(awt_display, srcGC, pixel); 1353 XFillRectangle(awt_display, xsdo->drawable, srcGC, 1354 0, 0, xsdo->pmWidth, xsdo->pmHeight); 1355 1356 /* invert the mask back */ 1357 XFillRectangle(awt_display, xsdo->bitmask, bmGC, 1358 0, 0, xsdo->pmWidth, xsdo->pmHeight); 1359 1360 XFreeGC(awt_display, bmGC); 1361 XFreeGC(awt_display, srcGC); 1362 xsdo->bgPixel = pixel; 1363 xsdo->isBgInitialized = JNI_TRUE; 1364 } 1365 1366 return xsdo->drawable; 1367 } 1368 1369 static void 1370 X11SD_ReleasePixmapWithBg(JNIEnv *env, X11SDOps *xsdo) 1371 { 1372 #ifdef MITSHM 1373 if (xsdo->shmPMData.usingShmPixmap) { 1374 xsdo->shmPMData.xRequestSent = JNI_TRUE; 1375 } 1376 #endif /* MITSHM */ 1377 } 1378 1379 #endif /* !HEADLESS */ 1380 1381 /* 1382 * Class: sun_java2d_x11_X11SurfaceData 1383 * Method: XCreateGC 1384 * Signature: (I)J 1385 */ 1386 JNIEXPORT jlong JNICALL 1387 Java_sun_java2d_x11_XSurfaceData_XCreateGC 1388 (JNIEnv *env, jclass xsd, jlong pXSData) 1389 { 1390 jlong ret; 1391 1392 #ifndef HEADLESS 1393 X11SDOps *xsdo; 1394 1395 J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XCreateGC"); 1396 1397 xsdo = (X11SDOps *) pXSData; 1398 if (xsdo == NULL) { 1399 return 0L; 1400 } 1401 1402 xsdo->javaGC = XCreateGC(awt_display, xsdo->drawable, 0, NULL); 1403 ret = (jlong) xsdo->javaGC; 1404 #else /* !HEADLESS */ 1405 ret = 0L; 1406 #endif /* !HEADLESS */ 1407 1408 return ret; 1409 } 1410 1411 /* 1412 * Class: sun_java2d_x11_X11SurfaceData 1413 * Method: XResetClip 1414 * Signature: (JIIIILsun/java2d/pipe/Region;)V 1415 */ 1416 JNIEXPORT void JNICALL 1417 Java_sun_java2d_x11_XSurfaceData_XResetClip 1418 (JNIEnv *env, jclass xsd, jlong xgc) 1419 { 1420 #ifndef HEADLESS 1421 J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XResetClip"); 1422 XSetClipMask(awt_display, (GC) xgc, None); 1423 #endif /* !HEADLESS */ 1424 } 1425 1426 /* 1427 * Class: sun_java2d_x11_X11SurfaceData 1428 * Method: XSetClip 1429 * Signature: (JIIIILsun/java2d/pipe/Region;)V 1430 */ 1431 JNIEXPORT void JNICALL 1432 Java_sun_java2d_x11_XSurfaceData_XSetClip 1433 (JNIEnv *env, jclass xsd, jlong xgc, 1434 jint x1, jint y1, jint x2, jint y2, 1435 jobject complexclip) 1436 { 1437 #ifndef HEADLESS 1438 int numrects; 1439 XRectangle rects[256]; 1440 XRectangle *pRect = rects; 1441 1442 J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XSetClip"); 1443 1444 numrects = RegionToYXBandedRectangles(env, 1445 x1, y1, x2, y2, complexclip, 1446 &pRect, 256); 1447 1448 XSetClipRectangles(awt_display, (GC) xgc, 0, 0, pRect, numrects, YXBanded); 1449 1450 if (pRect != rects) { 1451 free(pRect); 1452 } 1453 #endif /* !HEADLESS */ 1454 } 1455 1456 /* 1457 * Class: sun_java2d_x11_X11SurfaceData 1458 * Method: XSetCopyMode 1459 * Signature: (J)V 1460 */ 1461 JNIEXPORT void JNICALL 1462 Java_sun_java2d_x11_X11SurfaceData_XSetCopyMode 1463 (JNIEnv *env, jclass xsd, jlong xgc) 1464 { 1465 #ifndef HEADLESS 1466 J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XSetCopyMode"); 1467 XSetFunction(awt_display, (GC) xgc, GXcopy); 1468 #endif /* !HEADLESS */ 1469 } 1470 1471 /* 1472 * Class: sun_java2d_x11_X11SurfaceData 1473 * Method: XSetXorMode 1474 * Signature: (J)V 1475 */ 1476 JNIEXPORT void JNICALL 1477 Java_sun_java2d_x11_X11SurfaceData_XSetXorMode 1478 (JNIEnv *env, jclass xr, jlong xgc) 1479 { 1480 #ifndef HEADLESS 1481 J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XSetXorMode"); 1482 XSetFunction(awt_display, (GC) xgc, GXxor); 1483 #endif /* !HEADLESS */ 1484 } 1485 1486 /* 1487 * Class: sun_java2d_x11_X11SurfaceData 1488 * Method: XSetForeground 1489 * Signature: (JI)V 1490 */ 1491 JNIEXPORT void JNICALL 1492 Java_sun_java2d_x11_X11SurfaceData_XSetForeground 1493 (JNIEnv *env, jclass xsd, jlong xgc, jint pixel) 1494 { 1495 #ifndef HEADLESS 1496 J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XSetForeground"); 1497 XSetForeground(awt_display, (GC) xgc, pixel); 1498 #endif /* !HEADLESS */ 1499 } 1500 1501 /* 1502 * Class: sun_java2d_x11_X11SurfaceData 1503 * Method: XSetGraphicsExposures 1504 * Signature: (JZ)V 1505 */ 1506 JNIEXPORT void JNICALL 1507 Java_sun_java2d_x11_XSurfaceData_XSetGraphicsExposures 1508 (JNIEnv *env, jclass xsd, jlong xgc, jboolean needExposures) 1509 { 1510 #ifndef HEADLESS 1511 J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XSetGraphicsExposures"); 1512 XSetGraphicsExposures(awt_display, (GC) xgc, needExposures ? True : False); 1513 #endif /* !HEADLESS */ 1514 }