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