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