1 /* 2 * Copyright (c) 1999, 2011, 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 27 28 /** 29 * This class holds the information for a particular graphics device. 30 * Since a display change can cause the creation of new devices 31 * at any time, there is no referencing of the devices array allowed. 32 * Instead, anyone wishing to reference a device in the array (e.g., 33 * the current default device or a device for a given hWnd) must 34 * call one of the static methods of this class with the index of 35 * the device in question. Those methods will then lock the devices 36 * array and forward the request to the current device at that 37 * array index. 38 */ 39 40 #include <awt.h> 41 #include <sun_awt_Win32GraphicsDevice.h> 42 #include "awt_Canvas.h" 43 #include "awt_Win32GraphicsDevice.h" 44 #include "awt_Window.h" 45 #include "java_awt_Transparency.h" 46 #include "java_awt_color_ColorSpace.h" 47 #include "sun_awt_Win32GraphicsDevice.h" 48 #include "java_awt_image_DataBuffer.h" 49 #include "dither.h" 50 #include "img_util_md.h" 51 #include "Devices.h" 52 #include <d2d1.h> 53 #pragma comment(lib, "d2d1") 54 55 #ifndef MDT_Effective_DPI 56 #define MDT_Effective_DPI 0 57 #endif 58 59 uns_ordered_dither_array img_oda_alpha; 60 61 jclass AwtWin32GraphicsDevice::indexCMClass; 62 jclass AwtWin32GraphicsDevice::wToolkitClass; 63 jfieldID AwtWin32GraphicsDevice::dynamicColorModelID; 64 jfieldID AwtWin32GraphicsDevice::indexCMrgbID; 65 jfieldID AwtWin32GraphicsDevice::indexCMcacheID; 66 jmethodID AwtWin32GraphicsDevice::paletteChangedMID; 67 BOOL AwtWin32GraphicsDevice::primaryPalettized; 68 int AwtWin32GraphicsDevice::primaryIndex = 0; 69 70 71 /** 72 * Construct this device. Store the screen (index into the devices 73 * array of this object), the array (used in static references via 74 * particular device indices), the monitor/pMonitorInfo (which other 75 * classes will inquire of this device), the bits per pixel of this 76 * device, and information on whether the primary device is palettized. 77 */ 78 AwtWin32GraphicsDevice::AwtWin32GraphicsDevice(int screen, 79 HMONITOR mhnd, Devices *arr) 80 { 81 this->screen = screen; 82 this->devicesArray = arr; 83 this->scaleX = 1; 84 this->scaleY = 1; 85 javaDevice = NULL; 86 colorData = new ImgColorData; 87 colorData->grayscale = GS_NOTGRAY; 88 palette = NULL; 89 cData = NULL; 90 gpBitmapInfo = NULL; 91 monitor = mhnd; 92 pMonitorInfo = new MONITORINFOEX; 93 pMonitorInfo->cbSize = sizeof(MONITORINFOEX); 94 ::GetMonitorInfo(monitor, pMonitorInfo); 95 96 // Set primary device info: other devices will need to know 97 // whether the primary is palettized during the initialization 98 // process 99 HDC hDC = this->GetDC(); 100 colorData->bitsperpixel = ::GetDeviceCaps(hDC, BITSPIXEL); 101 this->ReleaseDC(hDC); 102 if (MONITORINFOF_PRIMARY & pMonitorInfo->dwFlags) { 103 primaryIndex = screen; 104 if (colorData->bitsperpixel > 8) { 105 primaryPalettized = FALSE; 106 } else { 107 primaryPalettized = TRUE; 108 } 109 } 110 } 111 112 AwtWin32GraphicsDevice::~AwtWin32GraphicsDevice() 113 { 114 delete colorData; 115 if (gpBitmapInfo) { 116 free(gpBitmapInfo); 117 } 118 if (palette) { 119 delete palette; 120 } 121 if (pMonitorInfo) { 122 delete pMonitorInfo; 123 } 124 if (javaDevice) { 125 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 126 env->DeleteWeakGlobalRef(javaDevice); 127 } 128 if (cData != NULL) { 129 freeICMColorData(cData); 130 } 131 } 132 133 HDC AwtWin32GraphicsDevice::MakeDCFromMonitor(HMONITOR hmMonitor) { 134 HDC retCode = NULL; 135 if (NULL != hmMonitor) { 136 MONITORINFOEX mieInfo; 137 138 memset((void*)(&mieInfo), 0, sizeof(MONITORINFOEX)); 139 mieInfo.cbSize = sizeof(MONITORINFOEX); 140 141 if (TRUE == ::GetMonitorInfo(hmMonitor, (LPMONITORINFOEX)(&mieInfo))) { 142 HDC hDC = CreateDC(mieInfo.szDevice, NULL, NULL, NULL); 143 if (NULL != hDC) { 144 retCode = hDC; 145 } 146 } 147 } 148 return retCode; 149 } 150 151 HDC AwtWin32GraphicsDevice::GetDC() 152 { 153 return MakeDCFromMonitor(monitor); 154 } 155 156 void AwtWin32GraphicsDevice::ReleaseDC(HDC hDC) 157 { 158 if (hDC != NULL) { 159 ::DeleteDC(hDC); 160 } 161 } 162 163 /** 164 * Init this device. This creates the bitmap structure 165 * used to hold the device color data and initializes any 166 * appropriate palette structures. 167 */ 168 void AwtWin32GraphicsDevice::Initialize() 169 { 170 unsigned int ri, gi, bi; 171 if (colorData->bitsperpixel < 8) { 172 // REMIND: how to handle? 173 } 174 175 // Create a BitmapInfo object for color data 176 if (!gpBitmapInfo) { 177 try { 178 gpBitmapInfo = (BITMAPINFO *) 179 safe_Malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)); 180 } catch (std::bad_alloc&) { 181 throw; 182 } 183 gpBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 184 } 185 gpBitmapInfo->bmiHeader.biBitCount = 0; 186 HDC hBMDC = this->GetDC(); 187 HBITMAP hBM = ::CreateCompatibleBitmap(hBMDC, 1, 1); 188 VERIFY(::GetDIBits(hBMDC, hBM, 0, 1, NULL, gpBitmapInfo, DIB_RGB_COLORS)); 189 190 if (colorData->bitsperpixel > 8) { 191 if (MONITORINFOF_PRIMARY & pMonitorInfo->dwFlags) { 192 primaryPalettized = FALSE; 193 } 194 if (colorData->bitsperpixel != 24) { // 15, 16, or 32 bpp 195 int foo; 196 gpBitmapInfo->bmiHeader.biCompression = BI_BITFIELDS; 197 if (::GetDIBits(hBMDC, hBM, 0, 1, &foo, gpBitmapInfo, 198 DIB_RGB_COLORS) == 0) 199 { 200 // Bug 4684966: If GetDIBits returns an error, we could 201 // get stuck in an infinite loop setting the colorData 202 // fields. Hardcode bitColors to reasonable values instead. 203 // These values are picked according to standard masks 204 // for these bit depths on win9x, according to MSDN docs. 205 switch (colorData->bitsperpixel) { 206 case 15: 207 ((int *)gpBitmapInfo->bmiColors)[0] = 0x7c00; 208 ((int *)gpBitmapInfo->bmiColors)[1] = 0x03e0; 209 ((int *)gpBitmapInfo->bmiColors)[2] = 0x001f; 210 break; 211 case 16: 212 ((int *)gpBitmapInfo->bmiColors)[0] = 0xf800; 213 ((int *)gpBitmapInfo->bmiColors)[1] = 0x07e0; 214 ((int *)gpBitmapInfo->bmiColors)[2] = 0x001f; 215 break; 216 case 32: 217 default: 218 ((int *)gpBitmapInfo->bmiColors)[0] = 0xff0000; 219 ((int *)gpBitmapInfo->bmiColors)[1] = 0x00ff00; 220 ((int *)gpBitmapInfo->bmiColors)[2] = 0x0000ff; 221 break; 222 } 223 } 224 ri = ((unsigned int *)gpBitmapInfo->bmiColors)[0]; 225 colorData->rOff = 0; 226 while ((ri & 1) == 0) { 227 colorData->rOff++; 228 ri >>= 1; 229 } 230 colorData->rScale = 0; 231 while (ri < 0x80) { 232 colorData->rScale++; 233 ri <<= 1; 234 } 235 gi = ((unsigned int *)gpBitmapInfo->bmiColors)[1]; 236 colorData->gOff = 0; 237 while ((gi & 1) == 0) { 238 colorData->gOff++; 239 gi >>= 1; 240 } 241 colorData->gScale = 0; 242 while (gi < 0x80) { 243 colorData->gScale++; 244 gi <<= 1; 245 } 246 bi = ((unsigned int *)gpBitmapInfo->bmiColors)[2]; 247 colorData->bOff = 0; 248 while ((bi & 1) == 0) { 249 colorData->bOff++; 250 bi >>= 1; 251 } 252 colorData->bScale = 0; 253 while (bi < 0x80) { 254 colorData->bScale++; 255 bi <<= 1; 256 } 257 if ( (0 == colorData->bOff) 258 && (5 == colorData->gOff) 259 && (10 == colorData->rOff) 260 && (3 == colorData->bScale) 261 && (3 == colorData->gScale) 262 && (3 == colorData->rScale)) { 263 colorData->bitsperpixel = 15; 264 gpBitmapInfo->bmiHeader.biCompression = BI_RGB; 265 } 266 } else { // 24 bpp 267 gpBitmapInfo->bmiHeader.biBitCount = 24; 268 gpBitmapInfo->bmiHeader.biCompression = BI_RGB; 269 270 // Fill these values in as a convenience for the screen 271 // ColorModel construction code below (see getColorModel()) 272 ((int *)gpBitmapInfo->bmiColors)[0] = 0x0000ff; 273 ((int *)gpBitmapInfo->bmiColors)[1] = 0x00ff00; 274 ((int *)gpBitmapInfo->bmiColors)[2] = 0xff0000; 275 } 276 } else { 277 if (MONITORINFOF_PRIMARY & pMonitorInfo->dwFlags) { 278 primaryPalettized = TRUE; 279 } 280 gpBitmapInfo->bmiHeader.biBitCount = 8; 281 gpBitmapInfo->bmiHeader.biCompression = BI_RGB; 282 gpBitmapInfo->bmiHeader.biClrUsed = 256; 283 gpBitmapInfo->bmiHeader.biClrImportant = 256; 284 285 // The initialization of cData is done prior to 286 // calling palette->Update() since we need it 287 // for calculating inverseGrayLut 288 if (cData == NULL) { 289 cData = (ColorData*)safe_Calloc(1, sizeof(ColorData)); 290 memset(cData, 0, sizeof(ColorData)); 291 initDitherTables(cData); 292 } 293 294 if (!palette) { 295 palette = new AwtPalette(this); 296 } else { 297 palette->Update(); 298 } 299 palette->UpdateLogical(); 300 } 301 VERIFY(::DeleteObject(hBM)); 302 VERIFY(::DeleteDC(hBMDC)); 303 } 304 305 /** 306 * Creates a new colorModel given the current device configuration. 307 * The dynamic flag determines whether we use the system palette 308 * (dynamic == TRUE) or our custom palette in creating a new 309 * IndexedColorModel. 310 */ 311 jobject AwtWin32GraphicsDevice::GetColorModel(JNIEnv *env, jboolean dynamic) 312 { 313 jobject awt_colormodel; 314 int i; 315 if (colorData->bitsperpixel == 24) { 316 awt_colormodel = 317 JNU_NewObjectByName(env, "sun/awt/Win32ColorModel24", "()V"); 318 } else if (colorData->bitsperpixel > 8) { 319 int *masks = (int *)gpBitmapInfo->bmiColors; 320 int numbits = 0; 321 unsigned int bits = (masks[0] | masks[1] | masks[2]); 322 while (bits) { 323 numbits++; 324 bits >>= 1; 325 } 326 awt_colormodel = JNU_NewObjectByName(env, 327 "java/awt/image/DirectColorModel", 328 "(IIII)V", numbits, 329 masks[0], masks[1], masks[2]); 330 } else if (colorData->grayscale == GS_STATICGRAY) { 331 jclass clazz; 332 jclass clazz1; 333 jmethodID mid; 334 jobject cspace = NULL; 335 jint bits[1]; 336 jintArray bitsArray; 337 338 clazz1 = env->FindClass("java/awt/color/ColorSpace"); 339 CHECK_NULL_RETURN(clazz1, NULL); 340 mid = env->GetStaticMethodID(clazz1, "getInstance", 341 "(I)Ljava/awt/color/ColorSpace;"); 342 CHECK_NULL_RETURN(mid, NULL); 343 cspace = env->CallStaticObjectMethod(clazz1, mid, 344 java_awt_color_ColorSpace_CS_GRAY); 345 CHECK_NULL_RETURN(cspace, NULL); 346 347 bits[0] = 8; 348 bitsArray = env->NewIntArray(1); 349 if (bitsArray == 0) { 350 return NULL; 351 } else { 352 env->SetIntArrayRegion(bitsArray, 0, 1, bits); 353 } 354 355 clazz = env->FindClass("java/awt/image/ComponentColorModel"); 356 CHECK_NULL_RETURN(clazz, NULL); 357 mid = env->GetMethodID(clazz,"<init>", 358 "(Ljava/awt/color/ColorSpace;[IZZII)V"); 359 CHECK_NULL_RETURN(mid, NULL); 360 361 awt_colormodel = env->NewObject(clazz, mid, 362 cspace, 363 bitsArray, 364 JNI_FALSE, 365 JNI_FALSE, 366 java_awt_Transparency_OPAQUE, 367 java_awt_image_DataBuffer_TYPE_BYTE); 368 } else { 369 jintArray hRGB = env->NewIntArray(256); 370 unsigned int *rgb = NULL, *rgbP = NULL; 371 jboolean allvalid = JNI_TRUE; 372 jbyte vbits[256/8]; 373 jobject validBits = NULL; 374 375 CHECK_NULL_RETURN(hRGB, NULL); 376 /* Create the LUT from the color map */ 377 try { 378 rgb = (unsigned int *) env->GetPrimitiveArrayCritical(hRGB, 0); 379 CHECK_NULL_RETURN(rgb, NULL); 380 rgbP = rgb; 381 if (!palette) { 382 palette = new AwtPalette(this); 383 palette->UpdateLogical(); 384 } 385 if (colorData->grayscale == GS_INDEXGRAY) { 386 /* For IndexColorModel, pretend first 10 colors and last 387 10 colors are transparent black. This makes 388 ICM.allgrayopaque true. 389 */ 390 unsigned int *logicalEntries = palette->GetLogicalEntries(); 391 392 for (i=0; i < 10; i++) { 393 rgbP[i] = 0x00000000; 394 rgbP[i+246] = 0x00000000; 395 } 396 memcpy(&rgbP[10], &logicalEntries[10], 236 * sizeof(RGBQUAD)); 397 // We need to specify which entries in the colormap are 398 // valid so that the transparent black entries we have 399 // created do not affect the Transparency setting of the 400 // IndexColorModel. The vbits array is used to construct 401 // a BigInteger such that the most significant bit of vbits[0] 402 // indicates the validity of the last color (#256) and the 403 // least significant bit of vbits[256/8] indicates the 404 // validity of the first color (#0). We need to fill vbits 405 // with all 1's and then turn off the first and last 10 bits. 406 memset(vbits, 0xff, sizeof(vbits)); 407 vbits[0] = 0; 408 vbits[1] = (jbyte) (0xff >> 2); 409 vbits[sizeof(vbits)-2] = (jbyte) (0xff << 2); 410 vbits[sizeof(vbits)-1] = 0; 411 allvalid = JNI_FALSE; 412 } else { 413 if (AwtPalette::UseCustomPalette() && !dynamic) { 414 // If we plan to use our custom palette (i.e., we are 415 // not running inside another app and we are not creating 416 // a dynamic colorModel object), then setup ICM with 417 // custom palette entries 418 unsigned int *logicalEntries = palette->GetLogicalEntries(); 419 memcpy(rgbP, logicalEntries, 256 * sizeof(int)); 420 } else { 421 // Else, use current system palette entries. 422 // REMIND: This may not give the result we want if 423 // we are running inside another app and that 424 // parent app is running in the background when we 425 // reach here. We could at least cache an "ideal" set of 426 // system palette entries from the first time we are 427 // running in the foreground and then future ICM's will 428 // use that set instead. 429 unsigned int *systemEntries = palette->GetSystemEntries(); 430 memcpy(rgbP, systemEntries, 256 * sizeof(int)); 431 } 432 } 433 } catch (...) { 434 env->ReleasePrimitiveArrayCritical(hRGB, rgb, 0); 435 throw; 436 } 437 438 env->ReleasePrimitiveArrayCritical(hRGB, rgb, 0); 439 440 // Construct a new color model 441 if (!allvalid) { 442 jbyteArray bArray = env->NewByteArray(sizeof(vbits)); 443 CHECK_NULL_RETURN(bArray, NULL); 444 env->SetByteArrayRegion(bArray, 0, sizeof(vbits), vbits); 445 validBits = JNU_NewObjectByName(env, 446 "java/math/BigInteger", 447 "([B)V", bArray); 448 JNU_CHECK_EXCEPTION_RETURN(env, NULL); 449 } 450 awt_colormodel = 451 JNU_NewObjectByName(env, 452 "java/awt/image/IndexColorModel", 453 "(II[IIILjava/math/BigInteger;)V", 454 8, 256, 455 hRGB, 0, 456 java_awt_image_DataBuffer_TYPE_BYTE, 457 validBits); 458 } 459 return awt_colormodel; 460 } 461 462 /** 463 * Called from AwtPalette code when it is determined what grayscale 464 * value (if any) the current logical palette has 465 */ 466 void AwtWin32GraphicsDevice::SetGrayness(int grayValue) 467 { 468 colorData->grayscale = grayValue; 469 } 470 471 472 /** 473 * Update our dynamic IndexedColorModel. This happens after 474 * a change to the system palette. Any surfaces stored in vram 475 * (Win32OffScreenSurfaceData and GDIWindowSurfaceData objects) 476 * refer to this colorModel and use its lookup table and inverse 477 * lookup to calculate correct index values for rgb colors. So 478 * the colorModel must always reflect the current state of the 479 * system palette. 480 */ 481 void AwtWin32GraphicsDevice::UpdateDynamicColorModel() 482 { 483 if (!javaDevice) { 484 // javaDevice may not be set yet. If not, return. In 485 // this situation, we probably don't need an update anyway 486 // since the colorModel will be created with the correct 487 // info when the java side is initialized. 488 return; 489 } 490 JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); 491 jobject colorModel = env->GetObjectField(javaDevice, 492 dynamicColorModelID); 493 if (!colorModel) { 494 return; 495 } 496 if (env->IsInstanceOf(colorModel, indexCMClass)) { 497 // If colorModel not of type ICM then we're not in 8-bit mode and 498 // don't need to update it 499 jboolean isCopy; 500 unsigned int *newEntries = palette->GetSystemEntries(); 501 jintArray rgbArray = (jintArray)env->GetObjectField(colorModel, 502 AwtWin32GraphicsDevice::indexCMrgbID); 503 jintArray cacheArray = (jintArray)env->GetObjectField(colorModel, 504 AwtWin32GraphicsDevice::indexCMcacheID); 505 if (!rgbArray || !cacheArray) { 506 JNU_ThrowInternalError(env, "rgb or lookupcache array of IndexColorModel null"); 507 return; 508 } 509 int rgbLength = env->GetArrayLength(rgbArray); 510 int cacheLength = env->GetArrayLength(cacheArray); 511 jint *cmEntries = (jint *)env->GetPrimitiveArrayCritical(rgbArray, &isCopy); 512 if (!cmEntries) { 513 env->ExceptionClear(); 514 JNU_ThrowInternalError(env, "Problem retrieving rgb critical array"); 515 return; 516 } 517 jint *cache = (jint *)env->GetPrimitiveArrayCritical(cacheArray, &isCopy); 518 if (!cache) { 519 env->ExceptionClear(); 520 env->ReleasePrimitiveArrayCritical(rgbArray, cmEntries, JNI_ABORT); 521 JNU_ThrowInternalError(env, "Problem retrieving cache critical array"); 522 return; 523 } 524 // Set the new rgb values 525 int i; 526 for (i = 0; i < rgbLength; ++i) { 527 cmEntries[i] = newEntries[i]; 528 } 529 // clear out the old cache 530 for (i = 0; i < cacheLength; ++i) { 531 cache[i] = 0; 532 } 533 env->ReleasePrimitiveArrayCritical(cacheArray, cache, 0); 534 env->ReleasePrimitiveArrayCritical(rgbArray, cmEntries, 0); 535 536 // Call WToolkit::paletteChanged() method; this will invalidate 537 // the offscreen surfaces dependent on this dynamic colorModel 538 // to ensure that they get redrawn with the correct color indices 539 env->CallStaticVoidMethod(AwtWin32GraphicsDevice::wToolkitClass, 540 paletteChangedMID); 541 } 542 } 543 544 unsigned int *AwtWin32GraphicsDevice::GetSystemPaletteEntries() 545 { 546 // REMIND: What to do if palette NULL? Need to throw 547 // some kind of exception? 548 return palette->GetSystemEntries(); 549 } 550 551 unsigned char *AwtWin32GraphicsDevice::GetSystemInverseLUT() 552 { 553 // REMIND: What to do if palette NULL? Need to throw 554 // some kind of exception? 555 return palette->GetSystemInverseLUT(); 556 } 557 558 559 BOOL AwtWin32GraphicsDevice::UpdateSystemPalette() 560 { 561 if (colorData->bitsperpixel > 8) { 562 return FALSE; 563 } else { 564 return palette->Update(); 565 } 566 } 567 568 HPALETTE AwtWin32GraphicsDevice::SelectPalette(HDC hDC) 569 { 570 if (palette) { 571 return palette->Select(hDC); 572 } else { 573 return NULL; 574 } 575 } 576 577 void AwtWin32GraphicsDevice::RealizePalette(HDC hDC) 578 { 579 if (palette) { 580 palette->Realize(hDC); 581 } 582 } 583 584 /** 585 * Deterine which device the HWND exists on and return the 586 * appropriate index into the devices array. 587 */ 588 int AwtWin32GraphicsDevice::DeviceIndexForWindow(HWND hWnd) 589 { 590 HMONITOR mon = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST); 591 int screen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(mon); 592 return screen; 593 } 594 595 /** 596 * Get the HPALETTE associated with this device 597 */ 598 HPALETTE AwtWin32GraphicsDevice::GetPalette() 599 { 600 if (palette) { 601 return palette->GetPalette(); 602 } else { 603 return NULL; 604 } 605 } 606 607 /** 608 * Object referring to this device is releasing that reference. 609 * This allows the array holding all devices to be released (once 610 * all references to the array have gone away). 611 */ 612 void AwtWin32GraphicsDevice::Release() 613 { 614 devicesArray->Release(); 615 } 616 617 /** 618 * Links this native object with its java Win32GraphicsDevice. 619 * Need this link because the colorModel of the java device 620 * may be updated from native code. 621 */ 622 void AwtWin32GraphicsDevice::SetJavaDevice(JNIEnv *env, jobject objPtr) 623 { 624 javaDevice = env->NewWeakGlobalRef(objPtr); 625 } 626 627 /** 628 * Sets horizontal and vertical scale factors 629 */ 630 void AwtWin32GraphicsDevice::SetScale(float sx, float sy) 631 { 632 scaleX = sx; 633 scaleY = sy; 634 } 635 636 int AwtWin32GraphicsDevice::ScaleUpX(int x) 637 { 638 return (int)ceil(x * scaleX); 639 } 640 641 int AwtWin32GraphicsDevice::ScaleUpY(int y) 642 { 643 return (int)ceil(y * scaleY); 644 } 645 646 int AwtWin32GraphicsDevice::ScaleDownX(int x) 647 { 648 return (int)ceil(x / scaleX); 649 } 650 651 int AwtWin32GraphicsDevice::ScaleDownY(int y) 652 { 653 return (int)ceil(y / scaleY); 654 } 655 656 void AwtWin32GraphicsDevice::InitDesktopScales() 657 { 658 unsigned x = 0; 659 unsigned y = 0; 660 float dpiX = -1.0f; 661 float dpiY = -1.0f; 662 663 // for debug purposes 664 static float scale = -2.0f; 665 if (scale == -2) { 666 scale = -1; 667 char *uiScale = getenv("J2D_UISCALE"); 668 if (uiScale != NULL) { 669 scale = (float)strtod(uiScale, NULL); 670 if (errno == ERANGE || scale <= 0) { 671 scale = -1; 672 } 673 } 674 } 675 676 if (scale > 0) { 677 SetScale(scale, scale); 678 return; 679 } 680 681 typedef HRESULT(WINAPI GetDpiForMonitorFunc)(HMONITOR, int, UINT*, UINT*); 682 static HMODULE hLibSHCoreDll = NULL; 683 static GetDpiForMonitorFunc *lpGetDpiForMonitor = NULL; 684 685 if (hLibSHCoreDll == NULL) { 686 hLibSHCoreDll = JDK_LoadSystemLibrary("shcore.dll"); 687 if (hLibSHCoreDll != NULL) { 688 lpGetDpiForMonitor = (GetDpiForMonitorFunc*)GetProcAddress( 689 hLibSHCoreDll, "GetDpiForMonitor"); 690 } 691 } 692 693 if (lpGetDpiForMonitor != NULL) { 694 HRESULT hResult = lpGetDpiForMonitor(GetMonitor(), 695 MDT_Effective_DPI, &x, &y); 696 if (hResult == S_OK) { 697 dpiX = static_cast<float>(x); 698 dpiY = static_cast<float>(y); 699 } 700 } else { 701 ID2D1Factory* m_pDirect2dFactory; 702 HRESULT res = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, 703 &m_pDirect2dFactory); 704 if (res == S_OK) { 705 m_pDirect2dFactory->GetDesktopDpi(&dpiX, &dpiY); 706 m_pDirect2dFactory->Release(); 707 } 708 } 709 710 if (dpiX > 0 && dpiY > 0) { 711 SetScale(dpiX / 96, dpiY / 96); 712 } 713 } 714 715 float AwtWin32GraphicsDevice::GetScaleX() 716 { 717 return scaleX; 718 } 719 720 float AwtWin32GraphicsDevice::GetScaleY() 721 { 722 return scaleY; 723 } 724 725 /** 726 * Disables offscreen acceleration for this device. This 727 * sets a flag in the java object that is used to determine 728 * whether offscreen surfaces can be created on the device. 729 */ 730 void AwtWin32GraphicsDevice::DisableOffscreenAcceleration() 731 { 732 // REMIND: noop for now 733 } 734 735 /** 736 * Invalidates the GraphicsDevice object associated with this 737 * device by disabling offscreen acceleration and calling 738 * invalidate(defIndex) on the java object. 739 */ 740 void AwtWin32GraphicsDevice::Invalidate(JNIEnv *env) 741 { 742 int defIndex = AwtWin32GraphicsDevice::GetDefaultDeviceIndex(); 743 DisableOffscreenAcceleration(); 744 jobject javaDevice = GetJavaDevice(); 745 if (!JNU_IsNull(env, javaDevice)) { 746 JNU_CallMethodByName(env, NULL, javaDevice, "invalidate", 747 "(I)V", defIndex); 748 } 749 } 750 751 /** 752 * Static deviceIndex-based methods 753 * 754 * The following methods take a deviceIndex for the list of devices 755 * and perform the appropriate action on that device. This way of 756 * dereferencing the list of devices allows us to do appropriate 757 * locks around the list to ensure multi-threaded safety. 758 */ 759 760 761 jobject AwtWin32GraphicsDevice::GetColorModel(JNIEnv *env, jboolean dynamic, 762 int deviceIndex) 763 { 764 Devices::InstanceAccess devices; 765 return devices->GetDevice(deviceIndex)->GetColorModel(env, dynamic); 766 } 767 768 LPMONITORINFO AwtWin32GraphicsDevice::GetMonitorInfo(int deviceIndex) 769 { 770 Devices::InstanceAccess devices; 771 return devices->GetDevice(deviceIndex)->GetMonitorInfo(); 772 } 773 774 /** 775 * This function updates the data in the MONITORINFOEX structure pointed to by 776 * pMonitorInfo for all monitors on the system. Added for 4654713. 777 */ 778 void AwtWin32GraphicsDevice::ResetAllMonitorInfo() 779 { 780 //IE in some circumstances generates WM_SETTINGCHANGE message on appearance 781 //and thus triggers this method 782 //but we may not have the devices list initialized yet. 783 if (!Devices::GetInstance()){ 784 return; 785 } 786 Devices::InstanceAccess devices; 787 int devicesNum = devices->GetNumDevices(); 788 for (int deviceIndex = 0; deviceIndex < devicesNum; deviceIndex++) { 789 HMONITOR monitor = devices->GetDevice(deviceIndex)->GetMonitor(); 790 ::GetMonitorInfo(monitor, 791 devices->GetDevice(deviceIndex)->pMonitorInfo); 792 } 793 } 794 795 void AwtWin32GraphicsDevice::DisableOffscreenAccelerationForDevice( 796 HMONITOR hMonitor) 797 { 798 Devices::InstanceAccess devices; 799 if (hMonitor == NULL) { 800 devices->GetDevice(0)->DisableOffscreenAcceleration(); 801 } else { 802 int devicesNum = devices->GetNumDevices(); 803 for (int i = 0; i < devicesNum; ++i) { 804 if (devices->GetDevice(i)->GetMonitor() == hMonitor) { 805 devices->GetDevice(i)->DisableOffscreenAcceleration(); 806 } 807 } 808 } 809 } 810 811 HMONITOR AwtWin32GraphicsDevice::GetMonitor(int deviceIndex) 812 { 813 Devices::InstanceAccess devices; 814 return devices->GetDevice(deviceIndex)->GetMonitor(); 815 } 816 817 HPALETTE AwtWin32GraphicsDevice::GetPalette(int deviceIndex) 818 { 819 Devices::InstanceAccess devices; 820 return devices->GetDevice(deviceIndex)->GetPalette(); 821 } 822 823 void AwtWin32GraphicsDevice::UpdateDynamicColorModel(int deviceIndex) 824 { 825 Devices::InstanceAccess devices; 826 devices->GetDevice(deviceIndex)->UpdateDynamicColorModel(); 827 } 828 829 BOOL AwtWin32GraphicsDevice::UpdateSystemPalette(int deviceIndex) 830 { 831 Devices::InstanceAccess devices; 832 return devices->GetDevice(deviceIndex)->UpdateSystemPalette(); 833 } 834 835 HPALETTE AwtWin32GraphicsDevice::SelectPalette(HDC hDC, int deviceIndex) 836 { 837 Devices::InstanceAccess devices; 838 return devices->GetDevice(deviceIndex)->SelectPalette(hDC); 839 } 840 841 void AwtWin32GraphicsDevice::RealizePalette(HDC hDC, int deviceIndex) 842 { 843 Devices::InstanceAccess devices; 844 devices->GetDevice(deviceIndex)->RealizePalette(hDC); 845 } 846 847 ColorData *AwtWin32GraphicsDevice::GetColorData(int deviceIndex) 848 { 849 Devices::InstanceAccess devices; 850 return devices->GetDevice(deviceIndex)->GetColorData(); 851 } 852 853 /** 854 * Return the grayscale value for the indicated device. 855 */ 856 int AwtWin32GraphicsDevice::GetGrayness(int deviceIndex) 857 { 858 Devices::InstanceAccess devices; 859 return devices->GetDevice(deviceIndex)->GetGrayness(); 860 } 861 862 HDC AwtWin32GraphicsDevice::GetDCFromScreen(int screen) { 863 J2dTraceLn1(J2D_TRACE_INFO, 864 "AwtWin32GraphicsDevice::GetDCFromScreen screen=%d", screen); 865 Devices::InstanceAccess devices; 866 AwtWin32GraphicsDevice *dev = devices->GetDevice(screen); 867 return MakeDCFromMonitor(dev->GetMonitor()); 868 } 869 870 /** Compare elements of MONITORINFOEX structures for the given HMONITORs. 871 * If equal, return TRUE 872 */ 873 BOOL AwtWin32GraphicsDevice::AreSameMonitors(HMONITOR mon1, HMONITOR mon2) { 874 J2dTraceLn2(J2D_TRACE_INFO, 875 "AwtWin32GraphicsDevice::AreSameMonitors mhnd1=%x mhnd2=%x", 876 mon1, mon2); 877 DASSERT(mon1 != NULL); 878 DASSERT(mon2 != NULL); 879 880 MONITORINFOEX mi1; 881 MONITORINFOEX mi2; 882 883 memset((void*)(&mi1), 0, sizeof(MONITORINFOEX)); 884 mi1.cbSize = sizeof(MONITORINFOEX); 885 memset((void*)(&mi2), 0, sizeof(MONITORINFOEX)); 886 mi2.cbSize = sizeof(MONITORINFOEX); 887 888 if (::GetMonitorInfo(mon1, &mi1) != 0 && 889 ::GetMonitorInfo(mon2, &mi2) != 0 ) 890 { 891 if (::EqualRect(&mi1.rcMonitor, &mi2.rcMonitor) && 892 ::EqualRect(&mi1.rcWork, &mi2.rcWork) && 893 (mi1.dwFlags == mi1.dwFlags)) 894 { 895 896 J2dTraceLn(J2D_TRACE_VERBOSE, " the monitors are the same"); 897 return TRUE; 898 } 899 } 900 J2dTraceLn(J2D_TRACE_VERBOSE, " the monitors are not the same"); 901 return FALSE; 902 } 903 904 int AwtWin32GraphicsDevice::GetScreenFromHMONITOR(HMONITOR mon) { 905 J2dTraceLn1(J2D_TRACE_INFO, 906 "AwtWin32GraphicsDevice::GetScreenFromHMONITOR mhnd=%x", mon); 907 908 DASSERT(mon != NULL); 909 Devices::InstanceAccess devices; 910 911 for (int i = 0; i < devices->GetNumDevices(); i++) { 912 HMONITOR mhnd = devices->GetDevice(i)->GetMonitor(); 913 if (AreSameMonitors(mon, mhnd)) { 914 J2dTraceLn1(J2D_TRACE_VERBOSE, " Found device: %d", i); 915 return i; 916 } 917 } 918 919 J2dTraceLn1(J2D_TRACE_WARNING, 920 "AwtWin32GraphicsDevice::GetScreenFromHMONITOR(): "\ 921 "couldn't find screen for HMONITOR %x, returning default", mon); 922 return AwtWin32GraphicsDevice::GetDefaultDeviceIndex(); 923 } 924 925 926 /** 927 * End of static deviceIndex-based methods 928 */ 929 930 931 const DWORD REQUIRED_FLAGS = ( //Flags which must be set in 932 PFD_SUPPORT_GDI | //in the PixelFormatDescriptor. 933 PFD_DRAW_TO_WINDOW); //Used to choose the default config 934 //and to check formats in 935 //isPixFmtSupported() 936 extern "C" { 937 938 JNIEXPORT void JNICALL 939 Java_sun_awt_Win32GraphicsDevice_initIDs(JNIEnv *env, jclass cls) 940 { 941 TRY; 942 943 /* class ids */ 944 jclass iCMClass = env->FindClass("java/awt/image/IndexColorModel"); 945 CHECK_NULL(iCMClass); 946 AwtWin32GraphicsDevice::indexCMClass = (jclass) env->NewGlobalRef(iCMClass); 947 env->DeleteLocalRef(iCMClass); 948 DASSERT(AwtWin32GraphicsDevice::indexCMClass); 949 CHECK_NULL(AwtWin32GraphicsDevice::indexCMClass); 950 951 jclass wTClass = env->FindClass("sun/awt/windows/WToolkit"); 952 CHECK_NULL(wTClass); 953 AwtWin32GraphicsDevice::wToolkitClass = (jclass)env->NewGlobalRef(wTClass); 954 env->DeleteLocalRef(wTClass); 955 DASSERT(AwtWin32GraphicsDevice::wToolkitClass); 956 CHECK_NULL(AwtWin32GraphicsDevice::wToolkitClass); 957 958 /* field ids */ 959 AwtWin32GraphicsDevice::dynamicColorModelID = env->GetFieldID(cls, 960 "dynamicColorModel", "Ljava/awt/image/ColorModel;"); 961 DASSERT(AwtWin32GraphicsDevice::dynamicColorModelID); 962 CHECK_NULL(AwtWin32GraphicsDevice::dynamicColorModelID); 963 964 AwtWin32GraphicsDevice::indexCMrgbID = 965 env->GetFieldID(AwtWin32GraphicsDevice::indexCMClass, "rgb", "[I"); 966 DASSERT(AwtWin32GraphicsDevice::indexCMrgbID); 967 CHECK_NULL(AwtWin32GraphicsDevice::indexCMrgbID); 968 969 AwtWin32GraphicsDevice::indexCMcacheID = 970 env->GetFieldID(AwtWin32GraphicsDevice::indexCMClass, 971 "lookupcache", "[I"); 972 DASSERT(AwtWin32GraphicsDevice::indexCMcacheID); 973 CHECK_NULL(AwtWin32GraphicsDevice::indexCMcacheID); 974 975 /* method ids */ 976 AwtWin32GraphicsDevice::paletteChangedMID = env->GetStaticMethodID( 977 AwtWin32GraphicsDevice::wToolkitClass, "paletteChanged", "()V"); 978 DASSERT(AwtWin32GraphicsDevice::paletteChangedMID); 979 CHECK_NULL(AwtWin32GraphicsDevice::paletteChangedMID); 980 981 // Only want to call this once per session 982 make_uns_ordered_dither_array(img_oda_alpha, 256); 983 984 CATCH_BAD_ALLOC; 985 } 986 987 } /* extern "C" */ 988 989 990 /* 991 * Class: sun_awt_Win32GraphicsDevice 992 * Method: getMaxConfigsImpl 993 * Signature: ()I 994 */ 995 996 JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getMaxConfigsImpl 997 (JNIEnv* jniEnv, jobject theThis, jint screen) { 998 TRY; 999 HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen); 1000 1001 PIXELFORMATDESCRIPTOR pfd; 1002 int max = ::DescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR), 1003 &pfd); 1004 if (hDC != NULL) { 1005 VERIFY(::DeleteDC(hDC)); 1006 hDC = NULL; 1007 } 1008 //If ::DescribePixelFormat() fails, max = 0 1009 //In this case, we return 1 config with visual number 0 1010 if (max == 0) { 1011 max = 1; 1012 } 1013 return (jint)max; 1014 CATCH_BAD_ALLOC_RET(0); 1015 } 1016 1017 /* 1018 * Class: sun_awt_Win32GraphicsDevice 1019 * Method: isPixFmtSupported 1020 * Signature: (I)Z 1021 */ 1022 1023 JNIEXPORT jboolean JNICALL Java_sun_awt_Win32GraphicsDevice_isPixFmtSupported 1024 (JNIEnv* env, jobject theThis, jint pixFmtID, jint screen) { 1025 TRY; 1026 jboolean suppColor = JNI_TRUE; 1027 HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen); 1028 1029 if (pixFmtID == 0) { 1030 return true; 1031 } 1032 1033 PIXELFORMATDESCRIPTOR pfd; 1034 int max = ::DescribePixelFormat(hDC, (int)pixFmtID, 1035 sizeof(PIXELFORMATDESCRIPTOR), &pfd); 1036 DASSERT(max); 1037 1038 //Check for supported ColorModel 1039 if ((pfd.cColorBits < 8) || 1040 ((pfd.cColorBits == 8) && (pfd.iPixelType != PFD_TYPE_COLORINDEX))) { 1041 //Note: this still allows for PixelFormats with > 8 color bits 1042 //which use COLORINDEX instead of RGB. This seems to work fine, 1043 //although issues may crop up involving PFD_NEED_PALETTE, which 1044 //is not currently taken into account. 1045 //If changes are made, they should also be reflected in 1046 //getDefaultPixID. 1047 suppColor = JNI_FALSE; 1048 } 1049 1050 if (hDC != NULL) { 1051 VERIFY(::DeleteDC(hDC)); 1052 hDC = NULL; 1053 } 1054 return (((pfd.dwFlags & REQUIRED_FLAGS) == REQUIRED_FLAGS) && suppColor) ? 1055 JNI_TRUE : JNI_FALSE; 1056 CATCH_BAD_ALLOC_RET(FALSE); 1057 } 1058 1059 /* 1060 * Class: sun_awt_Win32GraphicsDevice 1061 * Method: getDefaultPixIDImpl 1062 * Signature: (I)I 1063 */ 1064 1065 JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getDefaultPixIDImpl 1066 (JNIEnv* env, jobject theThis, jint screen) { 1067 TRY; 1068 int pixFmtID = 0; 1069 HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen); 1070 1071 PIXELFORMATDESCRIPTOR pfd = { 1072 sizeof(PIXELFORMATDESCRIPTOR), 1073 1, //version 1074 REQUIRED_FLAGS, //flags 1075 0, //iPixelType 1076 0, //cColorBits 1077 0,0,0,0,0,0,0,0, //cRedBits, cRedShift, green, blue, alpha 1078 0,0,0,0,0, //cAccumBits, cAccumRedBits, green, blue, alpha 1079 0,0,0,0,0,0,0,0 //etc. 1080 }; 1081 1082 //If 8-bit mode, must use Indexed mode 1083 if (8 == ::GetDeviceCaps(hDC, BITSPIXEL)) { 1084 pfd.iPixelType = PFD_TYPE_COLORINDEX; 1085 } 1086 1087 pixFmtID = ::ChoosePixelFormat(hDC, &pfd); 1088 if (pixFmtID == 0) { 1089 //Return 0 if GDI call fails. 1090 if (hDC != NULL) { 1091 VERIFY(::DeleteDC(hDC)); 1092 hDC = NULL; 1093 } 1094 return pixFmtID; 1095 } 1096 1097 if (JNI_FALSE == Java_sun_awt_Win32GraphicsDevice_isPixFmtSupported( 1098 env, theThis, pixFmtID, screen)) { 1099 /* Can't find a suitable pixel format ID. Fall back on 0. */ 1100 pixFmtID = 0; 1101 } 1102 1103 VERIFY(::DeleteDC(hDC)); 1104 hDC = NULL; 1105 return (jint)pixFmtID; 1106 CATCH_BAD_ALLOC_RET(0); 1107 } 1108 1109 /* 1110 * Class: sun_awt_Win32GraphicsDevice 1111 * Method: enterFullScreenExclusive 1112 * Signature: (Ljava/awt/peer/WindowPeer;)V 1113 */ 1114 1115 JNIEXPORT void JNICALL 1116 Java_sun_awt_Win32GraphicsDevice_enterFullScreenExclusive( 1117 JNIEnv* env, jobject graphicsDevice, 1118 jint screen, jobject windowPeer) { 1119 1120 TRY; 1121 1122 PDATA pData; 1123 JNI_CHECK_PEER_RETURN(windowPeer); 1124 1125 AwtWindow *window = (AwtWindow *)pData; // safe cast since we are called 1126 // with the WWindowPeer object 1127 HWND hWnd = window->GetHWnd(); 1128 1129 if (!::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, 1130 SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOSIZE)) 1131 { 1132 J2dTraceLn1(J2D_TRACE_ERROR, 1133 "Error %d setting topmost attribute to fs window", 1134 ::GetLastError()); 1135 } 1136 1137 CATCH_BAD_ALLOC; 1138 } 1139 1140 /* 1141 * Class: sun_awt_Win32GraphicsDevice 1142 * Method: exitFullScreenExclusive 1143 * Signature: (Ljava/awt/peer/WindowPeer;)V 1144 */ 1145 1146 JNIEXPORT void JNICALL 1147 Java_sun_awt_Win32GraphicsDevice_exitFullScreenExclusive( 1148 JNIEnv* env, jobject graphicsDevice, 1149 jint screen, jobject windowPeer) { 1150 1151 TRY; 1152 1153 PDATA pData; 1154 JNI_CHECK_PEER_RETURN(windowPeer); 1155 1156 AwtWindow *window = (AwtWindow *)pData; // safe cast since we are called 1157 // with the WWindowPeer object 1158 HWND hWnd = window->GetHWnd(); 1159 1160 jobject target = env->GetObjectField(windowPeer, AwtObject::targetID); 1161 jboolean alwaysOnTop = JNU_GetFieldByName(env, NULL, target, "alwaysOnTop", "Z").z; 1162 env->DeleteLocalRef(target); 1163 1164 if (!::SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, 1165 SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOSIZE)) 1166 { 1167 J2dTraceLn1(J2D_TRACE_ERROR, 1168 "Error %d unsetting topmost attribute to fs window", 1169 ::GetLastError()); 1170 } 1171 1172 // We should restore alwaysOnTop state as it's anyway dropped here 1173 Java_sun_awt_windows_WWindowPeer_setAlwaysOnTopNative(env, windowPeer, alwaysOnTop); 1174 1175 CATCH_BAD_ALLOC; 1176 } 1177 1178 jobject CreateDisplayMode(JNIEnv* env, jint width, jint height, 1179 jint bitDepth, jint refreshRate) { 1180 1181 TRY; 1182 1183 jclass displayModeClass = env->FindClass("java/awt/DisplayMode"); 1184 if (JNU_IsNull(env, displayModeClass)) { 1185 env->ExceptionClear(); 1186 JNU_ThrowInternalError(env, "Could not get display mode class"); 1187 return NULL; 1188 } 1189 1190 jmethodID cid = env->GetMethodID(displayModeClass, "<init>", "(IIII)V"); 1191 if (cid == NULL) { 1192 env->ExceptionClear(); 1193 JNU_ThrowInternalError(env, "Could not get display mode constructor"); 1194 return NULL; 1195 } 1196 1197 jobject displayMode = env->NewObject(displayModeClass, cid, width, 1198 height, bitDepth, refreshRate); 1199 return displayMode; 1200 1201 CATCH_BAD_ALLOC_RET(NULL); 1202 } 1203 1204 /** 1205 * A utility function which retrieves a DISPLAY_DEVICE information 1206 * given a screen number. 1207 * 1208 * If the function was able to find an attached device for the given screen 1209 * number, the lpDisplayDevice will be initialized with the data and 1210 * the function will return TRUE, otherwise it returns FALSE and contents 1211 * of the structure pointed to by lpDisplayDevice is undefined. 1212 */ 1213 static BOOL 1214 GetAttachedDisplayDevice(int screen, DISPLAY_DEVICE *lpDisplayDevice) 1215 { 1216 DWORD dwDeviceNum = 0; 1217 lpDisplayDevice->cb = sizeof(DISPLAY_DEVICE); 1218 while (EnumDisplayDevices(NULL, dwDeviceNum, lpDisplayDevice, 0) && 1219 dwDeviceNum < 20) // avoid infinite loop with buggy drivers 1220 { 1221 if (lpDisplayDevice->StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) { 1222 Devices::InstanceAccess devices; 1223 MONITORINFOEX *pMonInfo = 1224 (LPMONITORINFOEX)devices->GetDevice(screen)->GetMonitorInfo(); 1225 // make sure the device names match 1226 if (wcscmp(pMonInfo->szDevice, lpDisplayDevice->DeviceName) == 0) { 1227 return TRUE; 1228 } 1229 } 1230 dwDeviceNum++; 1231 } 1232 return FALSE; 1233 } 1234 1235 /* 1236 * Class: sun_awt_Win32GraphicsDevice 1237 * Method: getCurrentDisplayMode 1238 * Signature: (IZ)Ljava/awt/DisplayMode; 1239 */ 1240 JNIEXPORT jobject JNICALL 1241 Java_sun_awt_Win32GraphicsDevice_getCurrentDisplayMode 1242 (JNIEnv* env, jobject graphicsDevice, jint screen) 1243 { 1244 TRY; 1245 1246 DEVMODE dm; 1247 LPTSTR pName = NULL; 1248 1249 dm.dmSize = sizeof(dm); 1250 dm.dmDriverExtra = 0; 1251 1252 DISPLAY_DEVICE displayDevice; 1253 if (GetAttachedDisplayDevice(screen, &displayDevice)) { 1254 pName = displayDevice.DeviceName; 1255 } 1256 if (!EnumDisplaySettings(pName, ENUM_CURRENT_SETTINGS, &dm)) 1257 { 1258 return NULL; 1259 } 1260 1261 return CreateDisplayMode(env, dm.dmPelsWidth, 1262 dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency); 1263 1264 CATCH_BAD_ALLOC_RET(NULL); 1265 } 1266 1267 /* 1268 * Class: sun_awt_Win32GraphicsDevice 1269 * Method: configDisplayMode 1270 * Signature: (IIIIZ)V 1271 */ 1272 JNIEXPORT void JNICALL 1273 Java_sun_awt_Win32GraphicsDevice_configDisplayMode 1274 (JNIEnv* env, jobject graphicsDevice, jint screen, jobject windowPeer, 1275 jint width, jint height, jint bitDepth, jint refreshRate) 1276 { 1277 TRY; 1278 1279 DEVMODE dm; 1280 1281 dm.dmSize = sizeof(dm); 1282 dm.dmDriverExtra = 0; 1283 dm.dmPelsWidth = width; 1284 dm.dmPelsHeight = height; 1285 dm.dmBitsPerPel = bitDepth; 1286 dm.dmDisplayFrequency = refreshRate; 1287 dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | 1288 DM_BITSPERPEL | DM_DISPLAYFREQUENCY; 1289 1290 // ChangeDisplaySettings works only on the primary screen. 1291 // ChangeDisplaySettingsEx is not available on NT, 1292 // so it'd be nice not to break it if we can help it. 1293 if (screen == AwtWin32GraphicsDevice::GetDefaultDeviceIndex()) { 1294 if (::ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != 1295 DISP_CHANGE_SUCCESSFUL) 1296 { 1297 JNU_ThrowInternalError(env, 1298 "Could not set display mode"); 1299 } 1300 return; 1301 } 1302 1303 DISPLAY_DEVICE displayDevice; 1304 if (!GetAttachedDisplayDevice(screen, &displayDevice) || 1305 (::ChangeDisplaySettingsEx(displayDevice.DeviceName, &dm, NULL, CDS_FULLSCREEN, NULL) != 1306 DISP_CHANGE_SUCCESSFUL)) 1307 { 1308 JNU_ThrowInternalError(env, 1309 "Could not set display mode"); 1310 } 1311 1312 CATCH_BAD_ALLOC; 1313 } 1314 1315 class EnumDisplayModeParam { 1316 public: 1317 EnumDisplayModeParam(JNIEnv* e, jobject a) : env(e), arrayList(a) {} 1318 JNIEnv* env; 1319 jobject arrayList; 1320 }; 1321 1322 void addDisplayMode(JNIEnv* env, jobject arrayList, jint width, 1323 jint height, jint bitDepth, jint refreshRate) { 1324 1325 TRY; 1326 1327 jobject displayMode = CreateDisplayMode(env, width, height, 1328 bitDepth, refreshRate); 1329 if (!JNU_IsNull(env, displayMode)) { 1330 jclass arrayListClass = env->GetObjectClass(arrayList); 1331 if (JNU_IsNull(env, arrayListClass)) { 1332 JNU_ThrowInternalError(env, 1333 "Could not get class java.util.ArrayList"); 1334 return; 1335 } 1336 jmethodID mid = env->GetMethodID(arrayListClass, "add", 1337 "(Ljava/lang/Object;)Z"); 1338 if (mid == NULL) { 1339 env->ExceptionClear(); 1340 JNU_ThrowInternalError(env, 1341 "Could not get method java.util.ArrayList.add()"); 1342 return; 1343 } 1344 env->CallObjectMethod(arrayList, mid, displayMode); 1345 env->DeleteLocalRef(displayMode); 1346 } 1347 1348 CATCH_BAD_ALLOC; 1349 } 1350 1351 /* 1352 * Class: sun_awt_Win32GraphicsDevice 1353 * Method: enumDisplayModes 1354 * Signature: (Ljava/util/ArrayList;Z)V 1355 */ 1356 JNIEXPORT void JNICALL Java_sun_awt_Win32GraphicsDevice_enumDisplayModes 1357 (JNIEnv* env, jobject graphicsDevice, jint screen, jobject arrayList) 1358 { 1359 1360 TRY; 1361 1362 DEVMODE dm; 1363 LPTSTR pName = NULL; 1364 DISPLAY_DEVICE displayDevice; 1365 1366 1367 if (GetAttachedDisplayDevice(screen, &displayDevice)) { 1368 pName = displayDevice.DeviceName; 1369 } 1370 1371 dm.dmSize = sizeof(dm); 1372 dm.dmDriverExtra = 0; 1373 1374 BOOL bContinue = TRUE; 1375 for (int i = 0; bContinue; i++) { 1376 bContinue = EnumDisplaySettings(pName, i, &dm); 1377 if (dm.dmBitsPerPel >= 8) { 1378 addDisplayMode(env, arrayList, dm.dmPelsWidth, dm.dmPelsHeight, 1379 dm.dmBitsPerPel, dm.dmDisplayFrequency); 1380 JNU_CHECK_EXCEPTION(env); 1381 } 1382 } 1383 1384 CATCH_BAD_ALLOC; 1385 } 1386 1387 /* 1388 * Class: sun_awt_Win32GraphicsDevice 1389 * Method: makeColorModel 1390 * Signature: ()Ljava/awt/image/ColorModel 1391 */ 1392 1393 JNIEXPORT jobject JNICALL 1394 Java_sun_awt_Win32GraphicsDevice_makeColorModel 1395 (JNIEnv *env, jobject thisPtr, jint screen, jboolean dynamic) 1396 { 1397 Devices::InstanceAccess devices; 1398 return devices->GetDevice(screen)->GetColorModel(env, dynamic); 1399 } 1400 1401 /* 1402 * Class: sun_awt_Win32GraphicsDevice 1403 * Method: initDevice 1404 * Signature: (I)V 1405 */ 1406 JNIEXPORT void JNICALL 1407 Java_sun_awt_Win32GraphicsDevice_initDevice 1408 (JNIEnv *env, jobject thisPtr, jint screen) 1409 { 1410 Devices::InstanceAccess devices; 1411 devices->GetDevice(screen)->SetJavaDevice(env, thisPtr); 1412 } 1413 1414 /* 1415 * Class: sun_awt_Win32GraphicsDevice 1416 * Method: setNativeScale 1417 * Signature: (I,F,F)V 1418 */ 1419 JNIEXPORT void JNICALL 1420 Java_sun_awt_Win32GraphicsDevice_setNativeScale 1421 (JNIEnv *env, jobject thisPtr, jint screen, jfloat scaleX, jfloat scaleY) 1422 { 1423 Devices::InstanceAccess devices; 1424 AwtWin32GraphicsDevice *device = devices->GetDevice(screen); 1425 1426 if (device != NULL ) { 1427 device->SetScale(scaleX, scaleY); 1428 } 1429 } 1430 1431 /* 1432 * Class: sun_awt_Win32GraphicsDevice 1433 * Method: getNativeScaleX 1434 * Signature: (I)F 1435 */ 1436 JNIEXPORT jfloat JNICALL 1437 Java_sun_awt_Win32GraphicsDevice_getNativeScaleX 1438 (JNIEnv *env, jobject thisPtr, jint screen) 1439 { 1440 Devices::InstanceAccess devices; 1441 AwtWin32GraphicsDevice *device = devices->GetDevice(screen); 1442 return (device == NULL) ? 1 : device->GetScaleX(); 1443 } 1444 1445 /* 1446 * Class: sun_awt_Win32GraphicsDevice 1447 * Method: getNativeScaleY 1448 * Signature: (I)F 1449 */ 1450 JNIEXPORT jfloat JNICALL 1451 Java_sun_awt_Win32GraphicsDevice_getNativeScaleY 1452 (JNIEnv *env, jobject thisPtr, jint screen) 1453 { 1454 Devices::InstanceAccess devices; 1455 AwtWin32GraphicsDevice *device = devices->GetDevice(screen); 1456 return (device == NULL) ? 1 : device->GetScaleY(); 1457 } 1458 1459 /* 1460 * Class: sun_awt_Win32GraphicsDevice 1461 * Method: initNativeScale 1462 * Signature: (I)V; 1463 */ 1464 JNIEXPORT void JNICALL 1465 Java_sun_awt_Win32GraphicsDevice_initNativeScale 1466 (JNIEnv *env, jobject thisPtr, jint screen) 1467 { 1468 Devices::InstanceAccess devices; 1469 AwtWin32GraphicsDevice *device = devices->GetDevice(screen); 1470 1471 if (device != NULL) { 1472 device->InitDesktopScales(); 1473 } 1474 }