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