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