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