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