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