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