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 JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); 458 if (xsdo->drawable) { 459 xsdo->shmPMData.usingShmPixmap = JNI_TRUE; 460 xsdo->shmPMData.shmPixmap = xsdo->drawable; 461 return JNI_TRUE; 462 } 463 } 464 #endif /* MITSHM */ 465 466 AWT_LOCK(); 467 xsdo->drawable = 468 XCreatePixmap(awt_display, 469 RootWindow(awt_display, 470 xsdo->configData->awt_visInfo.screen), 471 width, height, depth); 472 AWT_UNLOCK(); 473 JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); 474 #ifdef MITSHM 475 xsdo->shmPMData.usingShmPixmap = JNI_FALSE; 476 xsdo->shmPMData.pixmap = xsdo->drawable; 477 #endif /* MITSHM */ 478 } 479 if (xsdo->drawable == 0) { 480 JNU_ThrowOutOfMemoryError(env, 481 "Can't create offscreen surface"); 482 return JNI_FALSE; 483 } 484 485 #endif /* !HEADLESS */ 486 return JNI_TRUE; 487 } 488 489 490 /* 491 * Class: sun_java2d_x11_X11SurfaceData 492 * Method: initSurface 493 * Signature: ()V 494 */ 495 JNIEXPORT void JNICALL 496 Java_sun_java2d_x11_X11SurfaceData_initSurface(JNIEnv *env, jclass xsd, 497 jint depth, 498 jint width, jint height, 499 jlong drawable) 500 { 501 #ifndef HEADLESS 502 X11SDOps *xsdo = X11SurfaceData_GetOps(env, xsd); 503 if (xsdo == NULL) { 504 return; 505 } 506 507 if (xsdo->configData->awt_cmap == (Colormap)NULL) { 508 awtJNI_CreateColorData(env, xsdo->configData, 1); 509 JNU_CHECK_EXCEPTION(env); 510 } 511 /* color_data will be initialized in awtJNI_CreateColorData for 512 8-bit visuals */ 513 xsdo->cData = xsdo->configData->color_data; 514 515 XShared_initSurface(env, xsdo, depth, width, height, drawable); 516 xsdo->xrPic = None; 517 #endif /* !HEADLESS */ 518 } 519 520 #ifndef HEADLESS 521 522 #ifdef MITSHM 523 524 void X11SD_DropSharedSegment(XShmSegmentInfo *shminfo) 525 { 526 if (shminfo != NULL) { 527 XShmDetach(awt_display, shminfo); 528 shmdt(shminfo->shmaddr); 529 /* REMIND: we don't need shmctl(shminfo->shmid, IPC_RMID, 0); here. */ 530 /* Check X11SD_CreateSharedImage() for the explanation */ 531 } 532 } 533 534 XImage* X11SD_CreateSharedImage(X11SDOps *xsdo, 535 jint width, jint height) 536 { 537 XImage *img = NULL; 538 XShmSegmentInfo *shminfo; 539 540 shminfo = malloc(sizeof(XShmSegmentInfo)); 541 if (shminfo == NULL) { 542 return NULL; 543 } 544 memset(shminfo, 0, sizeof(XShmSegmentInfo)); 545 546 img = XShmCreateImage(awt_display, xsdo->configData->awt_visInfo.visual, 547 xsdo->depth, ZPixmap, NULL, shminfo, 548 width, height); 549 if (img == NULL) { 550 free((void *)shminfo); 551 return NULL; 552 } 553 shminfo->shmid = 554 shmget(IPC_PRIVATE, height * img->bytes_per_line, 555 IPC_CREAT|mitShmPermissionMask); 556 if (shminfo->shmid < 0) { 557 J2dRlsTraceLn1(J2D_TRACE_ERROR, 558 "X11SD_SetupSharedSegment shmget has failed: %s", 559 strerror(errno)); 560 free((void *)shminfo); 561 XDestroyImage(img); 562 return NULL; 563 } 564 565 shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); 566 if (shminfo->shmaddr == ((char *) -1)) { 567 shmctl(shminfo->shmid, IPC_RMID, 0); 568 J2dRlsTraceLn1(J2D_TRACE_ERROR, 569 "X11SD_SetupSharedSegment shmat has failed: %s", 570 strerror(errno)); 571 free((void *)shminfo); 572 XDestroyImage(img); 573 return NULL; 574 } 575 576 shminfo->readOnly = False; 577 578 resetXShmAttachFailed(); 579 EXEC_WITH_XERROR_HANDLER(XShmAttachXErrHandler, 580 XShmAttach(awt_display, shminfo)); 581 582 /* 583 * Once the XSync round trip has finished then we 584 * can get rid of the id so that this segment does not stick 585 * around after we go away, holding system resources. 586 */ 587 shmctl(shminfo->shmid, IPC_RMID, 0); 588 589 if (isXShmAttachFailed() == JNI_TRUE) { 590 J2dRlsTraceLn1(J2D_TRACE_ERROR, 591 "X11SD_SetupSharedSegment XShmAttach has failed: %s", 592 strerror(errno)); 593 shmdt(shminfo->shmaddr); 594 free((void *)shminfo); 595 XDestroyImage(img); 596 return NULL; 597 } 598 599 img->data = shminfo->shmaddr; 600 img->obdata = (char *)shminfo; 601 602 return img; 603 } 604 605 XImage* X11SD_GetSharedImage(X11SDOps *xsdo, jint width, jint height, 606 jint maxWidth, jint maxHeight, jboolean readBits) 607 { 608 XImage * retImage = NULL; 609 if (cachedXImage != NULL && 610 X11SD_CachedXImageFits(width, height, maxWidth, maxHeight, 611 xsdo->depth, readBits)) { 612 /* sync so previous data gets flushed */ 613 XSync(awt_display, False); 614 retImage = cachedXImage; 615 cachedXImage = (XImage *)NULL; 616 } else if (width * height * xsdo->depth > 0x10000) { 617 retImage = X11SD_CreateSharedImage(xsdo, width, height); 618 } 619 return retImage; 620 } 621 622 Drawable X11SD_CreateSharedPixmap(X11SDOps *xsdo) 623 { 624 XShmSegmentInfo *shminfo; 625 XImage *img = NULL; 626 Drawable pixmap; 627 int scan; 628 int width = xsdo->pmWidth; 629 int height = xsdo->pmHeight; 630 631 if (xsdo->shmPMData.pmSize < 0x10000) { 632 /* only use shared mem pixmaps for relatively big images */ 633 return 0; 634 } 635 636 /* need to create shared(!) image to get bytes_per_line */ 637 img = X11SD_CreateSharedImage(xsdo, width, height); 638 if (img == NULL) { 639 return 0; 640 } 641 scan = img->bytes_per_line; 642 shminfo = (XShmSegmentInfo*)img->obdata; 643 XFree(img); 644 645 pixmap = 646 XShmCreatePixmap(awt_display, 647 RootWindow(awt_display, 648 xsdo->configData->awt_visInfo.screen), 649 shminfo->shmaddr, shminfo, 650 width, height, xsdo->depth); 651 if (pixmap == 0) { 652 X11SD_DropSharedSegment(shminfo); 653 return 0; 654 } 655 656 xsdo->shmPMData.shmSegInfo = shminfo; 657 xsdo->shmPMData.bytesPerLine = scan; 658 return pixmap; 659 } 660 661 void X11SD_PuntPixmap(X11SDOps *xsdo, jint width, jint height) 662 { 663 664 if (useMitShmPixmaps != CAN_USE_MITSHM || forceSharedPixmaps) { 665 return; 666 } 667 668 /* we wouldn't be here if it's a shared pixmap, so no check 669 * for !usingShmPixmap. 670 */ 671 672 xsdo->shmPMData.numBltsSinceRead = 0; 673 674 xsdo->shmPMData.pixelsReadSinceBlt += width * height; 675 if (xsdo->shmPMData.pixelsReadSinceBlt > 676 xsdo->shmPMData.pixelsReadThreshold) { 677 if (!xsdo->shmPMData.shmPixmap) { 678 xsdo->shmPMData.shmPixmap = 679 X11SD_CreateSharedPixmap(xsdo); 680 } 681 if (xsdo->shmPMData.shmPixmap) { 682 GC xgc = XCreateGC(awt_display, xsdo->shmPMData.shmPixmap, 0L, NULL); 683 if (xgc != NULL) { 684 xsdo->shmPMData.usingShmPixmap = JNI_TRUE; 685 xsdo->drawable = xsdo->shmPMData.shmPixmap; 686 XCopyArea(awt_display, 687 xsdo->shmPMData.pixmap, xsdo->drawable, xgc, 688 0, 0, xsdo->pmWidth, xsdo->pmHeight, 0, 0); 689 XSync(awt_display, False); 690 xsdo->shmPMData.xRequestSent = JNI_FALSE; 691 XFreeGC(awt_display, xgc); 692 } 693 } 694 } 695 } 696 697 void X11SD_UnPuntPixmap(X11SDOps *xsdo) 698 { 699 if (useMitShmPixmaps != CAN_USE_MITSHM || forceSharedPixmaps) { 700 return; 701 } 702 xsdo->shmPMData.pixelsReadSinceBlt = 0; 703 if (xsdo->shmPMData.numBltsSinceRead >= 704 xsdo->shmPMData.numBltsThreshold) 705 { 706 if (xsdo->shmPMData.usingShmPixmap) { 707 if (!xsdo->shmPMData.pixmap) { 708 xsdo->shmPMData.pixmap = 709 XCreatePixmap(awt_display, 710 RootWindow(awt_display, 711 xsdo->configData->awt_visInfo.screen), 712 xsdo->pmWidth, xsdo->pmHeight, xsdo->depth); 713 } 714 if (xsdo->shmPMData.pixmap) { 715 GC xgc = XCreateGC(awt_display, xsdo->shmPMData.pixmap, 0L, NULL); 716 if (xgc != NULL) { 717 xsdo->drawable = xsdo->shmPMData.pixmap; 718 XCopyArea(awt_display, 719 xsdo->shmPMData.shmPixmap, xsdo->drawable, xgc, 720 0, 0, xsdo->pmWidth, xsdo->pmHeight, 0, 0); 721 XSync(awt_display, False); 722 XFreeGC(awt_display, xgc); 723 xsdo->shmPMData.xRequestSent = JNI_FALSE; 724 xsdo->shmPMData.usingShmPixmap = JNI_FALSE; 725 xsdo->shmPMData.numBltsThreshold *= 2; 726 } 727 } 728 } 729 } else { 730 xsdo->shmPMData.numBltsSinceRead++; 731 } 732 } 733 734 /** 735 * Determines if the cached image can be used for current operation. 736 * If the image is to be used to be read into by XShmGetImage, 737 * it must be close enough to avoid excessive reading from the screen; 738 * otherwise it should just be at least the size requested. 739 */ 740 jboolean X11SD_CachedXImageFits(jint width, jint height, jint maxWidth, 741 jint maxHeight, jint depth, jboolean readBits) 742 { 743 /* we assume here that the cached image exists */ 744 jint imgWidth = cachedXImage->width; 745 jint imgHeight = cachedXImage->height; 746 747 if (imgWidth < width || imgHeight < height || depth != cachedXImage->depth) { 748 /* doesn't fit if any of the cached image dimensions is smaller 749 or the depths are different */ 750 return JNI_FALSE; 751 } 752 753 if (!readBits) { 754 /* Not reading from this image, so any image at least of the 755 size requested will do */ 756 return JNI_TRUE; 757 } 758 759 if ((imgWidth < width + 64) && (imgHeight < height + 64) 760 && imgWidth <= maxWidth && imgHeight <= maxHeight) 761 { 762 /* Cached image's width/height shouldn't be more than 64 pixels 763 * larger than requested, because the region in XShmGetImage 764 * can't be specified and we don't want to read too much. 765 * Furthermore it has to be smaller than maxWidth/Height 766 * so drawables are not read out of bounds. 767 */ 768 return JNI_TRUE; 769 } 770 771 return JNI_FALSE; 772 } 773 #endif /* MITSHM */ 774 775 jint X11SD_InitWindow(JNIEnv *env, X11SDOps *xsdo) 776 { 777 if (xsdo->isPixmap == JNI_TRUE) { 778 return SD_FAILURE; 779 } 780 xsdo->cData = xsdo->configData->color_data; 781 782 return SD_SUCCESS; 783 } 784 785 static jint X11SD_Lock(JNIEnv *env, 786 SurfaceDataOps *ops, 787 SurfaceDataRasInfo *pRasInfo, 788 jint lockflags) 789 { 790 X11SDOps *xsdo = (X11SDOps *) ops; 791 X11RIPrivate *xpriv = (X11RIPrivate *) &(pRasInfo->priv); 792 int ret = SD_SUCCESS; 793 794 AWT_LOCK(); 795 796 if (xsdo->invalid) { 797 AWT_UNLOCK(); 798 SurfaceData_ThrowInvalidPipeException(env, "bounds changed"); 799 return SD_FAILURE; 800 } 801 xsdo->cData = xsdo->configData->color_data; 802 if (xsdo->drawable == 0 && X11SD_InitWindow(env, xsdo) == SD_FAILURE) { 803 AWT_UNLOCK(); 804 return SD_FAILURE; 805 } 806 if ((lockflags & SD_LOCK_LUT) != 0 && 807 (xsdo->cData == NULL || 808 xsdo->cData->awt_icmLUT == NULL)) 809 { 810 AWT_UNLOCK(); 811 if (!(*env)->ExceptionCheck(env)) 812 { 813 JNU_ThrowNullPointerException(env, "colormap lookup table"); 814 } 815 return SD_FAILURE; 816 } 817 if ((lockflags & SD_LOCK_INVCOLOR) != 0 && 818 (xsdo->cData == NULL || 819 xsdo->cData->img_clr_tbl == NULL || 820 xsdo->cData->img_oda_red == NULL || 821 xsdo->cData->img_oda_green == NULL || 822 xsdo->cData->img_oda_blue == NULL)) 823 { 824 AWT_UNLOCK(); 825 if (!(*env)->ExceptionCheck(env)) 826 { 827 JNU_ThrowNullPointerException(env, "inverse colormap lookup table"); 828 } 829 return SD_FAILURE; 830 } 831 if ((lockflags & SD_LOCK_INVGRAY) != 0 && 832 (xsdo->cData == NULL || 833 xsdo->cData->pGrayInverseLutData == NULL)) 834 { 835 AWT_UNLOCK(); 836 if (!(*env)->ExceptionCheck(env)) 837 { 838 JNU_ThrowNullPointerException(env, "inverse gray lookup table"); 839 } 840 return SD_FAILURE; 841 } 842 if (xsdo->dgaAvailable && (lockflags & (SD_LOCK_RD_WR))) { 843 int dgaret; 844 845 dgaret = (*pJDgaInfo->pGetLock)(env, awt_display, &xsdo->dgaDev, 846 xsdo->drawable, &xsdo->surfInfo, 847 pRasInfo->bounds.x1, 848 pRasInfo->bounds.y1, 849 pRasInfo->bounds.x2, 850 pRasInfo->bounds.y2); 851 if (dgaret == JDGA_SUCCESS) { 852 int wx = xsdo->surfInfo.window.lox; 853 int wy = xsdo->surfInfo.window.loy; 854 pRasInfo->bounds.x1 = xsdo->surfInfo.visible.lox - wx; 855 pRasInfo->bounds.y1 = xsdo->surfInfo.visible.loy - wy; 856 pRasInfo->bounds.x2 = xsdo->surfInfo.visible.hix - wx; 857 pRasInfo->bounds.y2 = xsdo->surfInfo.visible.hiy - wy; 858 xpriv->lockType = X11SD_LOCK_BY_DGA; 859 xpriv->lockFlags = lockflags; 860 return SD_SUCCESS; 861 } else if (dgaret == JDGA_UNAVAILABLE) { 862 xsdo->dgaAvailable = JNI_FALSE; 863 } 864 } 865 if (lockflags & SD_LOCK_RD_WR) { 866 if (lockflags & SD_LOCK_FASTEST) { 867 ret = SD_SLOWLOCK; 868 } 869 xpriv->lockType = X11SD_LOCK_BY_XIMAGE; 870 if (xsdo->isPixmap) { 871 #ifdef MITSHM 872 if (xsdo->shmPMData.usingShmPixmap) { 873 xpriv->lockType = X11SD_LOCK_BY_SHMEM; 874 } 875 #endif /* MITSHM */ 876 if (pRasInfo->bounds.x1 < 0) { 877 pRasInfo->bounds.x1 = 0; 878 } 879 if (pRasInfo->bounds.y1 < 0) { 880 pRasInfo->bounds.y1 = 0; 881 } 882 if (pRasInfo->bounds.x2 > xsdo->pmWidth) { 883 pRasInfo->bounds.x2 = xsdo->pmWidth; 884 } 885 if (pRasInfo->bounds.y2 > xsdo->pmHeight) { 886 pRasInfo->bounds.y2 = xsdo->pmHeight; 887 } 888 } 889 } else { 890 /* They didn't lock for anything - we won't give them anything */ 891 xpriv->lockType = X11SD_LOCK_BY_NULL; 892 } 893 xpriv->lockFlags = lockflags; 894 xpriv->img = NULL; 895 896 return ret; 897 /* AWT_UNLOCK() called in Unlock */ 898 } 899 900 static void X11SD_GetRasInfo(JNIEnv *env, 901 SurfaceDataOps *ops, 902 SurfaceDataRasInfo *pRasInfo) 903 { 904 X11SDOps *xsdo = (X11SDOps *) ops; 905 X11RIPrivate *xpriv = (X11RIPrivate *) &(pRasInfo->priv); 906 jint lockFlags = xpriv->lockFlags; 907 jint depth = xsdo->depth; 908 int mult = xsdo->configData->pixelStride; 909 910 if (xsdo->dgaAvailable && 911 xpriv->lockType == X11SD_LOCK_BY_XIMAGE && 912 (lockFlags & SD_LOCK_FASTEST)) 913 { 914 /* Try one more time to use DGA (now with smaller bounds)... */ 915 int dgaret; 916 917 dgaret = (*pJDgaInfo->pGetLock)(env, awt_display, &xsdo->dgaDev, 918 xsdo->drawable, &xsdo->surfInfo, 919 pRasInfo->bounds.x1, 920 pRasInfo->bounds.y1, 921 pRasInfo->bounds.x2, 922 pRasInfo->bounds.y2); 923 if (dgaret == JDGA_SUCCESS) { 924 int wx = xsdo->surfInfo.window.lox; 925 int wy = xsdo->surfInfo.window.loy; 926 pRasInfo->bounds.x1 = xsdo->surfInfo.visible.lox - wx; 927 pRasInfo->bounds.y1 = xsdo->surfInfo.visible.loy - wy; 928 pRasInfo->bounds.x2 = xsdo->surfInfo.visible.hix - wx; 929 pRasInfo->bounds.y2 = xsdo->surfInfo.visible.hiy - wy; 930 xpriv->lockType = X11SD_LOCK_BY_DGA; 931 } else if (dgaret == JDGA_UNAVAILABLE) { 932 xsdo->dgaAvailable = JNI_FALSE; 933 } 934 } 935 936 if (xpriv->lockType == X11SD_LOCK_BY_DGA) { 937 int scan = xsdo->surfInfo.surfaceScan; 938 int wx = xsdo->surfInfo.window.lox; 939 int wy = xsdo->surfInfo.window.loy; 940 pRasInfo->rasBase = 941 (void *)(((uintptr_t) xsdo->surfInfo.basePtr) + (scan*wy + wx) * mult); 942 pRasInfo->pixelStride = mult; 943 pRasInfo->pixelBitOffset = 0; 944 pRasInfo->scanStride = scan * mult; 945 #ifdef MITSHM 946 } else if (xpriv->lockType == X11SD_LOCK_BY_SHMEM) { 947 if (xsdo->shmPMData.xRequestSent == JNI_TRUE) { 948 /* need to sync before using shared mem pixmap 949 if any x calls were issued for this pixmap */ 950 XSync(awt_display, False); 951 xsdo->shmPMData.xRequestSent = JNI_FALSE; 952 } 953 xpriv->x = pRasInfo->bounds.x1; 954 xpriv->y = pRasInfo->bounds.y1; 955 pRasInfo->rasBase = xsdo->shmPMData.shmSegInfo->shmaddr; 956 pRasInfo->pixelStride = mult; 957 pRasInfo->pixelBitOffset = 0; 958 pRasInfo->scanStride = xsdo->shmPMData.bytesPerLine; 959 #endif /* MITSHM */ 960 } else if (xpriv->lockType == X11SD_LOCK_BY_XIMAGE) { 961 int x, y, w, h; 962 x = pRasInfo->bounds.x1; 963 y = pRasInfo->bounds.y1; 964 w = pRasInfo->bounds.x2 - x; 965 h = pRasInfo->bounds.y2 - y; 966 967 xpriv->img = X11SD_GetImage(env, xsdo, &pRasInfo->bounds, lockFlags); 968 if (xpriv->img) { 969 int scan = xpriv->img->bytes_per_line; 970 xpriv->x = x; 971 xpriv->y = y; 972 pRasInfo->rasBase = xpriv->img->data - x * mult - y * scan; 973 pRasInfo->pixelStride = mult; 974 pRasInfo->pixelBitOffset = 0; 975 pRasInfo->scanStride = scan; 976 } else { 977 pRasInfo->rasBase = NULL; 978 pRasInfo->pixelStride = 0; 979 pRasInfo->pixelBitOffset = 0; 980 pRasInfo->scanStride = 0; 981 } 982 } else { 983 /* They didn't lock for anything - we won't give them anything */ 984 pRasInfo->rasBase = NULL; 985 pRasInfo->pixelStride = 0; 986 pRasInfo->pixelBitOffset = 0; 987 pRasInfo->scanStride = 0; 988 } 989 if (lockFlags & SD_LOCK_LUT) { 990 pRasInfo->lutBase = (jint *) xsdo->cData->awt_icmLUT; 991 pRasInfo->lutSize = xsdo->cData->awt_numICMcolors; 992 } else { 993 pRasInfo->lutBase = NULL; 994 pRasInfo->lutSize = 0; 995 } 996 if (lockFlags & SD_LOCK_INVCOLOR) { 997 pRasInfo->invColorTable = xsdo->cData->img_clr_tbl; 998 pRasInfo->redErrTable = xsdo->cData->img_oda_red; 999 pRasInfo->grnErrTable = xsdo->cData->img_oda_green; 1000 pRasInfo->bluErrTable = xsdo->cData->img_oda_blue; 1001 } else { 1002 pRasInfo->invColorTable = NULL; 1003 pRasInfo->redErrTable = NULL; 1004 pRasInfo->grnErrTable = NULL; 1005 pRasInfo->bluErrTable = NULL; 1006 } 1007 if (lockFlags & SD_LOCK_INVGRAY) { 1008 pRasInfo->invGrayTable = xsdo->cData->pGrayInverseLutData; 1009 } else { 1010 pRasInfo->invGrayTable = NULL; 1011 } 1012 } 1013 1014 static void X11SD_Unlock(JNIEnv *env, 1015 SurfaceDataOps *ops, 1016 SurfaceDataRasInfo *pRasInfo) 1017 { 1018 X11SDOps *xsdo = (X11SDOps *) ops; 1019 X11RIPrivate *xpriv = (X11RIPrivate *) &(pRasInfo->priv); 1020 1021 if (xpriv->lockType == X11SD_LOCK_BY_DGA) { 1022 (*pJDgaInfo->pReleaseLock)(env, xsdo->dgaDev, xsdo->drawable); 1023 } else if (xpriv->lockType == X11SD_LOCK_BY_XIMAGE && 1024 xpriv->img != NULL) 1025 { 1026 if (xpriv->lockFlags & SD_LOCK_WRITE) { 1027 int x = xpriv->x; 1028 int y = xpriv->y; 1029 int w = pRasInfo->bounds.x2 - x; 1030 int h = pRasInfo->bounds.y2 - y; 1031 Drawable drawable = xsdo->drawable; 1032 GC xgc = xsdo->cachedGC; 1033 if (xgc == NULL) { 1034 xsdo->cachedGC = xgc = 1035 XCreateGC(awt_display, drawable, 0L, NULL); 1036 } 1037 1038 if (xpriv->img->byte_order != nativeByteOrder) { 1039 /* switching bytes back in 24 and 32 bpp cases. */ 1040 /* For 16 bit XLib will switch for us. */ 1041 if (xsdo->depth > 16) { 1042 X11SD_SwapBytes(xsdo, xpriv->img, xsdo->depth, 1043 xsdo->configData->awtImage->wsImageFormat.bits_per_pixel); 1044 } 1045 } 1046 1047 #ifdef MITSHM 1048 if (xpriv->img->obdata != NULL) { 1049 XShmPutImage(awt_display, drawable, xgc, 1050 xpriv->img, 0, 0, x, y, w, h, False); 1051 XFlush(awt_display); 1052 } else { 1053 XPutImage(awt_display, drawable, xgc, 1054 xpriv->img, 0, 0, x, y, w, h); 1055 } 1056 if (xsdo->shmPMData.usingShmPixmap) { 1057 xsdo->shmPMData.xRequestSent = JNI_TRUE; 1058 } 1059 #else 1060 XPutImage(awt_display, drawable, xgc, 1061 xpriv->img, 0, 0, x, y, w, h); 1062 #endif /* MITSHM */ 1063 1064 (*pJDgaInfo->pXRequestSent)(env, xsdo->dgaDev, drawable); 1065 } 1066 X11SD_DisposeOrCacheXImage(xpriv->img); 1067 xpriv->img = (XImage *)NULL; 1068 } 1069 /* the background pixel is not valid anymore */ 1070 if (xpriv->lockFlags & SD_LOCK_WRITE) { 1071 xsdo->isBgInitialized = JNI_FALSE; 1072 } 1073 xpriv->lockType = X11SD_LOCK_UNLOCKED; 1074 AWT_UNLOCK(); 1075 } 1076 1077 static int 1078 X11SD_ClipToRoot(SurfaceDataBounds *b, SurfaceDataBounds *bounds, 1079 X11SDOps *xsdo) 1080 { 1081 Position x1=0, y1=0, x2=0, y2=0; 1082 int tmpx, tmpy; 1083 Window tmpchild; 1084 1085 Window window = (Window)(xsdo->drawable); /* is always a Window */ 1086 XWindowAttributes winAttr; 1087 1088 Status status = XGetWindowAttributes(awt_display, window, &winAttr); 1089 if (status == 0) { 1090 /* Failure, X window no longer valid. */ 1091 return FALSE; 1092 } 1093 if (!XTranslateCoordinates(awt_display, window, 1094 RootWindowOfScreen(winAttr.screen), 1095 0, 0, &tmpx, &tmpy, &tmpchild)) { 1096 return FALSE; 1097 } 1098 1099 x1 = -(x1 + tmpx); 1100 y1 = -(y1 + tmpy); 1101 1102 x2 = x1 + DisplayWidth(awt_display, xsdo->configData->awt_visInfo.screen); 1103 y2 = y1 + DisplayHeight(awt_display, xsdo->configData->awt_visInfo.screen); 1104 1105 x1 = XSD_MAX(bounds->x1, x1); 1106 y1 = XSD_MAX(bounds->y1, y1); 1107 x2 = XSD_MIN(bounds->x2, x2); 1108 y2 = XSD_MIN(bounds->y2, y2); 1109 if ((x1 >= x2) || (y1 >= y2)) { 1110 return FALSE; 1111 } 1112 b->x1 = x1; 1113 b->y1 = y1; 1114 b->x2 = x2; 1115 b->y2 = y2; 1116 1117 return TRUE; 1118 } 1119 1120 /* 1121 * x1, y1, x2, y2 - our rectangle in the coord system of 1122 * the widget 1123 * px1, xy1, px2, py2 - current parent rect coords in the 1124 * same system 1125 */ 1126 static int 1127 X11SD_FindClip(SurfaceDataBounds *b, SurfaceDataBounds *bounds, X11SDOps *xsdo) 1128 { 1129 return TRUE; 1130 } 1131 1132 static void 1133 X11SD_SwapBytes(X11SDOps *xsdo, XImage * img, int depth, int bpp) { 1134 int lengthInBytes = img->height * img->bytes_per_line; 1135 int i; 1136 1137 switch (depth) { 1138 case 12: 1139 case 15: 1140 case 16: 1141 { 1142 /* AB -> BA */ 1143 unsigned short *d = (unsigned short *)img->data; 1144 unsigned short t; 1145 for (i = 0; i < lengthInBytes/2; i++) { 1146 t = *d; 1147 *d++ = (t >> 8) | (t << 8); 1148 } 1149 img->byte_order = nativeByteOrder; 1150 img->bitmap_bit_order = nativeByteOrder; 1151 break; 1152 } 1153 case 24: 1154 { 1155 /* ABC -> CBA */ 1156 if (bpp == 24) { 1157 // 4517321: Only swap if we have a "real" ThreeByteBgr 1158 // visual (denoted by a red_mask of 0xff). Due to ambiguity 1159 // in the X11 spec, it appears that the swap is not required 1160 // on Linux configurations that use 24 bits per pixel (denoted 1161 // by a red_mask of 0xff0000). 1162 if (xsdo->configData->awt_visInfo.red_mask == 0xff) { 1163 int scan = img->bytes_per_line; 1164 unsigned char *d = (unsigned char *) img->data; 1165 unsigned char *d1; 1166 unsigned int t; 1167 int j; 1168 1169 for (i = 0; i < img->height; i++, d += scan) { 1170 d1 = d; 1171 for (j = 0; j < img->width; j++, d1 += 3) { 1172 /* not obvious opt from XLib src */ 1173 t = d1[0]; d1[0] = d1[2]; d1[2] = t; 1174 } 1175 } 1176 } 1177 break; 1178 } 1179 } 1180 /* FALL THROUGH for 32-bit case */ 1181 case 32: 1182 { 1183 /* ABCD -> DCBA */ 1184 unsigned int *d = (unsigned int *) img->data; 1185 unsigned int t; 1186 for (i = 0; i < lengthInBytes/4; i++) { 1187 t = *d; 1188 *d++ = ((t >> 24) | 1189 ((t >> 8) & 0xff00) | 1190 ((t & 0xff00) << 8) | 1191 (t << 24)); 1192 } 1193 break; 1194 } 1195 } 1196 } 1197 1198 static XImage * X11SD_GetImage(JNIEnv *env, X11SDOps *xsdo, 1199 SurfaceDataBounds *bounds, 1200 jint lockFlags) 1201 { 1202 int x, y, w, h, maxWidth, maxHeight; 1203 int scan; 1204 XImage * img = NULL; 1205 Drawable drawable; 1206 int depth = xsdo->depth; 1207 int mult = xsdo->configData->pixelStride; 1208 int pad = (mult == 3) ? 32 : mult * 8; // pad must be 8, 16, or 32 1209 jboolean readBits = lockFlags & SD_LOCK_NEED_PIXELS; 1210 1211 x = bounds->x1; 1212 y = bounds->y1; 1213 w = bounds->x2 - x; 1214 h = bounds->y2 - y; 1215 1216 #ifdef MITSHM 1217 if (useMitShmExt == CAN_USE_MITSHM) { 1218 if (xsdo->isPixmap) { 1219 if (readBits) { 1220 X11SD_PuntPixmap(xsdo, w, h); 1221 } 1222 maxWidth = xsdo->pmWidth; 1223 maxHeight = xsdo->pmHeight; 1224 } else { 1225 XWindowAttributes winAttr; 1226 if (XGetWindowAttributes(awt_display, 1227 (Window) xsdo->drawable, &winAttr) != 0) { 1228 maxWidth = winAttr.width; 1229 maxHeight = winAttr.height; 1230 } else { 1231 /* XGWA failed which isn't a good thing. Defaulting to using 1232 * x,y means that after the subtraction of these we will use 1233 * w=0, h=0 which is a reasonable default on such a failure. 1234 */ 1235 maxWidth = x; 1236 maxHeight = y; 1237 } 1238 } 1239 maxWidth -= x; 1240 maxHeight -= y; 1241 1242 img = X11SD_GetSharedImage(xsdo, w, h, maxWidth, maxHeight, readBits); 1243 } 1244 #endif /* MITSHM */ 1245 drawable = xsdo->drawable; 1246 1247 if (readBits) { 1248 #ifdef MITSHM 1249 if (img != NULL) { 1250 if (!XShmGetImage(awt_display, drawable, img, x, y, -1)) { 1251 X11SD_DisposeOrCacheXImage(img); 1252 img = NULL; 1253 } 1254 } 1255 if (img == NULL) { 1256 img = XGetImage(awt_display, drawable, x, y, w, h, -1, ZPixmap); 1257 if (img != NULL) { 1258 img->obdata = NULL; 1259 } 1260 } 1261 #else 1262 img = XGetImage(awt_display, drawable, x, y, w, h, -1, ZPixmap); 1263 #endif /* MITSHM */ 1264 if (img == NULL) { 1265 SurfaceDataBounds temp; 1266 img = XCreateImage(awt_display, 1267 xsdo->configData->awt_visInfo.visual, 1268 depth, ZPixmap, 0, NULL, w, h, pad, 0); 1269 if (img == NULL) { 1270 return NULL; 1271 } 1272 1273 scan = img->bytes_per_line; 1274 img->data = malloc(h * scan); 1275 if (img->data == NULL) { 1276 XFree(img); 1277 return NULL; 1278 } 1279 1280 if (xsdo->isPixmap == JNI_FALSE && 1281 X11SD_ClipToRoot(&temp, bounds, xsdo)) { 1282 1283 XImage * temp_image; 1284 temp_image = XGetImage(awt_display, drawable, 1285 temp.x1, temp.y1, 1286 temp.x2 - temp.x1, 1287 temp.y2 - temp.y1, 1288 -1, ZPixmap); 1289 if (temp_image == NULL) { 1290 XGrabServer(awt_display); 1291 if (X11SD_FindClip(&temp, bounds, xsdo)) { 1292 temp_image = 1293 XGetImage(awt_display, drawable, 1294 temp.x1, temp.y1, 1295 temp.x2 - temp.x1, 1296 temp.y2 - temp.y1, 1297 -1, ZPixmap); 1298 } 1299 XUngrabServer(awt_display); 1300 /* Workaround for bug 5039226 */ 1301 XSync(awt_display, False); 1302 } 1303 if (temp_image != NULL) { 1304 int temp_scan, bytes_to_copy; 1305 char * img_addr, * temp_addr; 1306 int i; 1307 1308 img_addr = img->data + 1309 (temp.y1 - y) * scan + (temp.x1 - x) * mult; 1310 temp_scan = temp_image->bytes_per_line; 1311 temp_addr = temp_image->data; 1312 bytes_to_copy = (temp.x2 - temp.x1) * mult; 1313 for (i = temp.y1; i < temp.y2; i++) { 1314 memcpy(img_addr, temp_addr, bytes_to_copy); 1315 img_addr += scan; 1316 temp_addr += temp_scan; 1317 } 1318 XDestroyImage(temp_image); 1319 } 1320 } 1321 img->obdata = NULL; 1322 } 1323 if (depth > 8 && img->byte_order != nativeByteOrder) { 1324 X11SD_SwapBytes(xsdo, img, depth, 1325 xsdo->configData->awtImage->wsImageFormat.bits_per_pixel); 1326 } 1327 } else { 1328 /* 1329 * REMIND: This might be better to move to the Lock function 1330 * to avoid lengthy I/O pauses inside what may be a critical 1331 * section. This will be more critical when SD_LOCK_READ is 1332 * implemented. Another solution is to cache the pixels 1333 * to avoid reading for every operation. 1334 */ 1335 if (img == NULL) { 1336 img = XCreateImage(awt_display, 1337 xsdo->configData->awt_visInfo.visual, 1338 depth, ZPixmap, 0, NULL, w, h, pad, 0); 1339 if (img == NULL) { 1340 return NULL; 1341 } 1342 1343 img->data = malloc(h * img->bytes_per_line); 1344 if (img->data == NULL) { 1345 XFree(img); 1346 return NULL; 1347 } 1348 1349 img->obdata = NULL; 1350 1351 if (img->byte_order != nativeByteOrder && 1352 (depth == 15 || depth == 16 || depth == 12)) { 1353 /* bytes will be swapped by XLib. */ 1354 img->byte_order = nativeByteOrder; 1355 img->bitmap_bit_order = nativeByteOrder; 1356 } 1357 } 1358 } 1359 return img; 1360 } 1361 1362 void X11SD_DisposeOrCacheXImage(XImage * image) { 1363 /* REMIND: might want to check if the new image worth caching. */ 1364 /* Cache only shared images. Passed image is assumed to be non-null. */ 1365 if (image->obdata != NULL) { 1366 if (cachedXImage != NULL) { 1367 X11SD_DisposeXImage(cachedXImage); 1368 } 1369 cachedXImage = image; 1370 } else { 1371 X11SD_DisposeXImage(image); 1372 } 1373 } 1374 1375 void X11SD_DisposeXImage(XImage * image) { 1376 if (image != NULL) { 1377 #ifdef MITSHM 1378 if (image->obdata != NULL) { 1379 X11SD_DropSharedSegment((XShmSegmentInfo*)image->obdata); 1380 image->obdata = NULL; 1381 } 1382 #endif /* MITSHM */ 1383 XDestroyImage(image); 1384 } 1385 } 1386 1387 static JDgaStatus 1388 GetLockStub(JNIEnv *env, Display *display, void **dgaDev, 1389 Drawable d, JDgaSurfaceInfo *pSurface, 1390 jint lox, jint loy, jint hix, jint hiy) 1391 { 1392 return JDGA_UNAVAILABLE; 1393 } 1394 1395 static JDgaStatus 1396 ReleaseLockStub(JNIEnv *env, void *dgaDev, Drawable d) 1397 { 1398 return JDGA_FAILED; 1399 } 1400 1401 static void 1402 XRequestSentStub(JNIEnv *env, void *dgaDev, Drawable d) 1403 { 1404 } 1405 1406 static void 1407 LibDisposeStub(JNIEnv *env) 1408 { 1409 } 1410 1411 static JDgaLibInfo DgaLibInfoStub = { 1412 NULL, 1413 GetLockStub, 1414 ReleaseLockStub, 1415 XRequestSentStub, 1416 LibDisposeStub, 1417 }; 1418 1419 void X11SD_LibDispose(JNIEnv *env) { 1420 AWT_LOCK(); 1421 if (pJDgaInfo != NULL) { 1422 pJDgaInfo->pLibDispose(env); 1423 pJDgaInfo = &DgaLibInfoStub; 1424 } 1425 AWT_UNLOCK(); 1426 } 1427 1428 void 1429 X11SD_DirectRenderNotify(JNIEnv *env, X11SDOps *xsdo) 1430 { 1431 #ifdef MITSHM 1432 if (xsdo->shmPMData.usingShmPixmap) { 1433 xsdo->shmPMData.xRequestSent = JNI_TRUE; 1434 } 1435 #endif /* MITSHM */ 1436 (*pJDgaInfo->pXRequestSent)(env, xsdo->dgaDev, xsdo->drawable); 1437 awt_output_flush(); 1438 } 1439 1440 /* 1441 * Sets transparent pixels in the pixmap to 1442 * the specified solid background color and returns it. 1443 * Doesn't update source pixmap unless the color of the 1444 * transparent pixels is different from the specified color. 1445 * 1446 * Note: The AWT lock must be held by the current thread 1447 * while calling into this method. 1448 */ 1449 static Drawable 1450 X11SD_GetPixmapWithBg(JNIEnv *env, X11SDOps *xsdo, jint pixel) 1451 { 1452 /* assert AWT_CHECK_HAVE_LOCK(); */ 1453 1454 if (xsdo->invalid) { 1455 AWT_UNLOCK(); 1456 SurfaceData_ThrowInvalidPipeException(env, "bounds changed"); 1457 return 0; 1458 } 1459 1460 /* the image doesn't have transparency, just return it */ 1461 if (xsdo->bitmask == 0) { 1462 /* don't need to unlock here, the caller will unlock through 1463 the release call */ 1464 return xsdo->drawable; 1465 } 1466 1467 /* Check if current color of the transparent pixels is different 1468 from the specified one */ 1469 if (xsdo->isBgInitialized == JNI_FALSE || xsdo->bgPixel != pixel) { 1470 GC srcGC; 1471 GC bmGC; 1472 1473 if (xsdo->drawable == 0) { 1474 AWT_UNLOCK(); 1475 return 0; 1476 } 1477 1478 bmGC = XCreateGC(awt_display, xsdo->bitmask, 0, NULL); 1479 if (bmGC == NULL) { 1480 AWT_UNLOCK(); 1481 return 0; 1482 } 1483 1484 /* invert the bitmask */ 1485 XSetFunction(awt_display, bmGC, GXxor); 1486 XSetForeground(awt_display, bmGC, 1); 1487 XFillRectangle(awt_display, xsdo->bitmask, bmGC, 1488 0, 0, xsdo->pmWidth, xsdo->pmHeight); 1489 1490 srcGC = XCreateGC(awt_display, xsdo->drawable, 0L, NULL); 1491 if (srcGC == NULL) { 1492 XFreeGC(awt_display, bmGC); 1493 AWT_UNLOCK(); 1494 return 0; 1495 } 1496 1497 /* set transparent pixels in the source pm to the bg color */ 1498 XSetClipMask(awt_display, srcGC, xsdo->bitmask); 1499 XSetForeground(awt_display, srcGC, pixel); 1500 XFillRectangle(awt_display, xsdo->drawable, srcGC, 1501 0, 0, xsdo->pmWidth, xsdo->pmHeight); 1502 1503 /* invert the mask back */ 1504 XFillRectangle(awt_display, xsdo->bitmask, bmGC, 1505 0, 0, xsdo->pmWidth, xsdo->pmHeight); 1506 1507 XFreeGC(awt_display, bmGC); 1508 XFreeGC(awt_display, srcGC); 1509 xsdo->bgPixel = pixel; 1510 xsdo->isBgInitialized = JNI_TRUE; 1511 } 1512 1513 return xsdo->drawable; 1514 } 1515 1516 static void 1517 X11SD_ReleasePixmapWithBg(JNIEnv *env, X11SDOps *xsdo) 1518 { 1519 #ifdef MITSHM 1520 if (xsdo->shmPMData.usingShmPixmap) { 1521 xsdo->shmPMData.xRequestSent = JNI_TRUE; 1522 } 1523 #endif /* MITSHM */ 1524 } 1525 1526 #endif /* !HEADLESS */ 1527 1528 /* 1529 * Class: sun_java2d_x11_X11SurfaceData 1530 * Method: XCreateGC 1531 * Signature: (I)J 1532 */ 1533 JNIEXPORT jlong JNICALL 1534 Java_sun_java2d_x11_XSurfaceData_XCreateGC 1535 (JNIEnv *env, jclass xsd, jlong pXSData) 1536 { 1537 jlong ret; 1538 1539 #ifndef HEADLESS 1540 X11SDOps *xsdo; 1541 1542 J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XCreateGC"); 1543 1544 xsdo = (X11SDOps *) pXSData; 1545 if (xsdo == NULL) { 1546 return 0L; 1547 } 1548 1549 xsdo->javaGC = XCreateGC(awt_display, xsdo->drawable, 0, NULL); 1550 ret = (jlong) xsdo->javaGC; 1551 #else /* !HEADLESS */ 1552 ret = 0L; 1553 #endif /* !HEADLESS */ 1554 1555 return ret; 1556 } 1557 1558 /* 1559 * Class: sun_java2d_x11_X11SurfaceData 1560 * Method: XResetClip 1561 * Signature: (JIIIILsun/java2d/pipe/Region;)V 1562 */ 1563 JNIEXPORT void JNICALL 1564 Java_sun_java2d_x11_XSurfaceData_XResetClip 1565 (JNIEnv *env, jclass xsd, jlong xgc) 1566 { 1567 #ifndef HEADLESS 1568 J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XResetClip"); 1569 XSetClipMask(awt_display, (GC) xgc, None); 1570 #endif /* !HEADLESS */ 1571 } 1572 1573 /* 1574 * Class: sun_java2d_x11_X11SurfaceData 1575 * Method: XSetClip 1576 * Signature: (JIIIILsun/java2d/pipe/Region;)V 1577 */ 1578 JNIEXPORT void JNICALL 1579 Java_sun_java2d_x11_XSurfaceData_XSetClip 1580 (JNIEnv *env, jclass xsd, jlong xgc, 1581 jint x1, jint y1, jint x2, jint y2, 1582 jobject complexclip) 1583 { 1584 #ifndef HEADLESS 1585 int numrects; 1586 XRectangle rects[256]; 1587 XRectangle *pRect = rects; 1588 1589 J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XSetClip"); 1590 1591 numrects = RegionToYXBandedRectangles(env, 1592 x1, y1, x2, y2, complexclip, 1593 &pRect, 256); 1594 1595 XSetClipRectangles(awt_display, (GC) xgc, 0, 0, pRect, numrects, YXBanded); 1596 1597 if (pRect != rects) { 1598 free(pRect); 1599 } 1600 #endif /* !HEADLESS */ 1601 } 1602 1603 /* 1604 * Class: sun_java2d_x11_X11SurfaceData 1605 * Method: XSetCopyMode 1606 * Signature: (J)V 1607 */ 1608 JNIEXPORT void JNICALL 1609 Java_sun_java2d_x11_X11SurfaceData_XSetCopyMode 1610 (JNIEnv *env, jclass xsd, jlong xgc) 1611 { 1612 #ifndef HEADLESS 1613 J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XSetCopyMode"); 1614 XSetFunction(awt_display, (GC) xgc, GXcopy); 1615 #endif /* !HEADLESS */ 1616 } 1617 1618 /* 1619 * Class: sun_java2d_x11_X11SurfaceData 1620 * Method: XSetXorMode 1621 * Signature: (J)V 1622 */ 1623 JNIEXPORT void JNICALL 1624 Java_sun_java2d_x11_X11SurfaceData_XSetXorMode 1625 (JNIEnv *env, jclass xr, jlong xgc) 1626 { 1627 #ifndef HEADLESS 1628 J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XSetXorMode"); 1629 XSetFunction(awt_display, (GC) xgc, GXxor); 1630 #endif /* !HEADLESS */ 1631 } 1632 1633 /* 1634 * Class: sun_java2d_x11_X11SurfaceData 1635 * Method: XSetForeground 1636 * Signature: (JI)V 1637 */ 1638 JNIEXPORT void JNICALL 1639 Java_sun_java2d_x11_X11SurfaceData_XSetForeground 1640 (JNIEnv *env, jclass xsd, jlong xgc, jint pixel) 1641 { 1642 #ifndef HEADLESS 1643 J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XSetForeground"); 1644 XSetForeground(awt_display, (GC) xgc, pixel); 1645 #endif /* !HEADLESS */ 1646 } 1647 1648 /* 1649 * Class: sun_java2d_x11_X11SurfaceData 1650 * Method: XSetGraphicsExposures 1651 * Signature: (JZ)V 1652 */ 1653 JNIEXPORT void JNICALL 1654 Java_sun_java2d_x11_XSurfaceData_XSetGraphicsExposures 1655 (JNIEnv *env, jclass xsd, jlong xgc, jboolean needExposures) 1656 { 1657 #ifndef HEADLESS 1658 J2dTraceLn(J2D_TRACE_INFO, "in X11SurfaceData_XSetGraphicsExposures"); 1659 XSetGraphicsExposures(awt_display, (GC) xgc, needExposures ? True : False); 1660 #endif /* !HEADLESS */ 1661 }