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 CheckIntLimits(x * scaleX); 636 } 637 638 int AwtWin32GraphicsDevice::ScaleUpY(int y) 639 { 640 return CheckIntLimits(y * scaleY); 641 } 642 643 int AwtWin32GraphicsDevice::ScaleDownX(int x) 644 { 645 return CheckIntLimits(x / scaleX); 646 } 647 648 int AwtWin32GraphicsDevice::ScaleDownY(int y) 649 { 650 return CheckIntLimits(y / scaleY); 651 } 652 653 int AwtWin32GraphicsDevice::CheckIntLimits(double value) 654 { 655 if (value < INT_MIN) 656 { 657 return INT_MIN; 658 } 659 660 if (value > INT_MAX) 661 { 662 return INT_MAX; 663 } 664 665 return (int)ceil(value); 666 } 667 668 void AwtWin32GraphicsDevice::InitDesktopScales() 669 { 670 float dpiX = -1.0f; 671 float dpiY = -1.0f; 672 GetScreenDpi(GetMonitor(), &dpiX, &dpiY); 673 if (dpiX > 0 && dpiY > 0) { 674 SetScale(dpiX / 96, dpiY / 96); 675 } 676 } 677 678 float AwtWin32GraphicsDevice::GetScaleX() 679 { 680 return scaleX; 681 } 682 683 float AwtWin32GraphicsDevice::GetScaleY() 684 { 685 return scaleY; 686 } 687 688 /** 689 * Disables offscreen acceleration for this device. This 690 * sets a flag in the java object that is used to determine 691 * whether offscreen surfaces can be created on the device. 692 */ 693 void AwtWin32GraphicsDevice::DisableOffscreenAcceleration() 694 { 695 // REMIND: noop for now 696 } 697 698 /** 699 * Invalidates the GraphicsDevice object associated with this 700 * device by disabling offscreen acceleration and calling 701 * invalidate(defIndex) on the java object. 702 */ 703 void AwtWin32GraphicsDevice::Invalidate(JNIEnv *env) 704 { 705 int defIndex = AwtWin32GraphicsDevice::GetDefaultDeviceIndex(); 706 DisableOffscreenAcceleration(); 707 jobject javaDevice = GetJavaDevice(); 708 if (!JNU_IsNull(env, javaDevice)) { 709 JNU_CallMethodByName(env, NULL, javaDevice, "invalidate", 710 "(I)V", defIndex); 711 } 712 } 713 714 /** 715 * Static deviceIndex-based methods 716 * 717 * The following methods take a deviceIndex for the list of devices 718 * and perform the appropriate action on that device. This way of 719 * dereferencing the list of devices allows us to do appropriate 720 * locks around the list to ensure multi-threaded safety. 721 */ 722 723 724 jobject AwtWin32GraphicsDevice::GetColorModel(JNIEnv *env, jboolean dynamic, 725 int deviceIndex) 726 { 727 Devices::InstanceAccess devices; 728 return devices->GetDevice(deviceIndex)->GetColorModel(env, dynamic); 729 } 730 731 LPMONITORINFO AwtWin32GraphicsDevice::GetMonitorInfo(int deviceIndex) 732 { 733 Devices::InstanceAccess devices; 734 return devices->GetDevice(deviceIndex)->GetMonitorInfo(); 735 } 736 737 /** 738 * This function updates the data in the MONITORINFOEX structure pointed to by 739 * pMonitorInfo for all monitors on the system. Added for 4654713. 740 */ 741 void AwtWin32GraphicsDevice::ResetAllMonitorInfo() 742 { 743 //IE in some circumstances generates WM_SETTINGCHANGE message on appearance 744 //and thus triggers this method 745 //but we may not have the devices list initialized yet. 746 if (!Devices::GetInstance()){ 747 return; 748 } 749 Devices::InstanceAccess devices; 750 int devicesNum = devices->GetNumDevices(); 751 for (int deviceIndex = 0; deviceIndex < devicesNum; deviceIndex++) { 752 HMONITOR monitor = devices->GetDevice(deviceIndex)->GetMonitor(); 753 ::GetMonitorInfo(monitor, 754 devices->GetDevice(deviceIndex)->pMonitorInfo); 755 } 756 } 757 758 void AwtWin32GraphicsDevice::DisableOffscreenAccelerationForDevice( 759 HMONITOR hMonitor) 760 { 761 Devices::InstanceAccess devices; 762 if (hMonitor == NULL) { 763 devices->GetDevice(0)->DisableOffscreenAcceleration(); 764 } else { 765 int devicesNum = devices->GetNumDevices(); 766 for (int i = 0; i < devicesNum; ++i) { 767 if (devices->GetDevice(i)->GetMonitor() == hMonitor) { 768 devices->GetDevice(i)->DisableOffscreenAcceleration(); 769 } 770 } 771 } 772 } 773 774 HMONITOR AwtWin32GraphicsDevice::GetMonitor(int deviceIndex) 775 { 776 Devices::InstanceAccess devices; 777 return devices->GetDevice(deviceIndex)->GetMonitor(); 778 } 779 780 HPALETTE AwtWin32GraphicsDevice::GetPalette(int deviceIndex) 781 { 782 Devices::InstanceAccess devices; 783 return devices->GetDevice(deviceIndex)->GetPalette(); 784 } 785 786 void AwtWin32GraphicsDevice::UpdateDynamicColorModel(int deviceIndex) 787 { 788 Devices::InstanceAccess devices; 789 devices->GetDevice(deviceIndex)->UpdateDynamicColorModel(); 790 } 791 792 BOOL AwtWin32GraphicsDevice::UpdateSystemPalette(int deviceIndex) 793 { 794 Devices::InstanceAccess devices; 795 return devices->GetDevice(deviceIndex)->UpdateSystemPalette(); 796 } 797 798 HPALETTE AwtWin32GraphicsDevice::SelectPalette(HDC hDC, int deviceIndex) 799 { 800 Devices::InstanceAccess devices; 801 return devices->GetDevice(deviceIndex)->SelectPalette(hDC); 802 } 803 804 void AwtWin32GraphicsDevice::RealizePalette(HDC hDC, int deviceIndex) 805 { 806 Devices::InstanceAccess devices; 807 devices->GetDevice(deviceIndex)->RealizePalette(hDC); 808 } 809 810 ColorData *AwtWin32GraphicsDevice::GetColorData(int deviceIndex) 811 { 812 Devices::InstanceAccess devices; 813 return devices->GetDevice(deviceIndex)->GetColorData(); 814 } 815 816 /** 817 * Return the grayscale value for the indicated device. 818 */ 819 int AwtWin32GraphicsDevice::GetGrayness(int deviceIndex) 820 { 821 Devices::InstanceAccess devices; 822 return devices->GetDevice(deviceIndex)->GetGrayness(); 823 } 824 825 HDC AwtWin32GraphicsDevice::GetDCFromScreen(int screen) { 826 J2dTraceLn1(J2D_TRACE_INFO, 827 "AwtWin32GraphicsDevice::GetDCFromScreen screen=%d", screen); 828 Devices::InstanceAccess devices; 829 AwtWin32GraphicsDevice *dev = devices->GetDevice(screen); 830 return MakeDCFromMonitor(dev->GetMonitor()); 831 } 832 833 /** Compare elements of MONITORINFOEX structures for the given HMONITORs. 834 * If equal, return TRUE 835 */ 836 BOOL AwtWin32GraphicsDevice::AreSameMonitors(HMONITOR mon1, HMONITOR mon2) { 837 J2dTraceLn2(J2D_TRACE_INFO, 838 "AwtWin32GraphicsDevice::AreSameMonitors mhnd1=%x mhnd2=%x", 839 mon1, mon2); 840 DASSERT(mon1 != NULL); 841 DASSERT(mon2 != NULL); 842 843 MONITORINFOEX mi1; 844 MONITORINFOEX mi2; 845 846 memset((void*)(&mi1), 0, sizeof(MONITORINFOEX)); 847 mi1.cbSize = sizeof(MONITORINFOEX); 848 memset((void*)(&mi2), 0, sizeof(MONITORINFOEX)); 849 mi2.cbSize = sizeof(MONITORINFOEX); 850 851 if (::GetMonitorInfo(mon1, &mi1) != 0 && 852 ::GetMonitorInfo(mon2, &mi2) != 0 ) 853 { 854 if (::EqualRect(&mi1.rcMonitor, &mi2.rcMonitor) && 855 ::EqualRect(&mi1.rcWork, &mi2.rcWork) && 856 (mi1.dwFlags == mi1.dwFlags)) 857 { 858 859 J2dTraceLn(J2D_TRACE_VERBOSE, " the monitors are the same"); 860 return TRUE; 861 } 862 } 863 J2dTraceLn(J2D_TRACE_VERBOSE, " the monitors are not the same"); 864 return FALSE; 865 } 866 867 int AwtWin32GraphicsDevice::GetScreenFromHMONITOR(HMONITOR mon) { 868 J2dTraceLn1(J2D_TRACE_INFO, 869 "AwtWin32GraphicsDevice::GetScreenFromHMONITOR mhnd=%x", mon); 870 871 DASSERT(mon != NULL); 872 JNIEnv *env = (JNIEnv*) JNU_GetEnv(jvm, JNI_VERSION_1_2); 873 if (!Devices::GetInstance()) { 874 Devices::UpdateInstance(env); 875 } 876 Devices::InstanceAccess devices; 877 878 for (int i = 0; i < devices->GetNumDevices(); i++) { 879 HMONITOR mhnd = devices->GetDevice(i)->GetMonitor(); 880 if (AreSameMonitors(mon, mhnd)) { 881 J2dTraceLn1(J2D_TRACE_VERBOSE, " Found device: %d", i); 882 return i; 883 } 884 } 885 886 J2dTraceLn1(J2D_TRACE_WARNING, 887 "AwtWin32GraphicsDevice::GetScreenFromHMONITOR(): "\ 888 "couldn't find screen for HMONITOR %x, returning default", mon); 889 return AwtWin32GraphicsDevice::GetDefaultDeviceIndex(); 890 } 891 892 893 /** 894 * End of static deviceIndex-based methods 895 */ 896 897 898 const DWORD REQUIRED_FLAGS = ( //Flags which must be set in 899 PFD_SUPPORT_GDI | //in the PixelFormatDescriptor. 900 PFD_DRAW_TO_WINDOW); //Used to choose the default config 901 //and to check formats in 902 //isPixFmtSupported() 903 extern "C" { 904 905 JNIEXPORT void JNICALL 906 Java_sun_awt_Win32GraphicsDevice_initIDs(JNIEnv *env, jclass cls) 907 { 908 TRY; 909 910 /* class ids */ 911 jclass iCMClass = env->FindClass("java/awt/image/IndexColorModel"); 912 CHECK_NULL(iCMClass); 913 AwtWin32GraphicsDevice::indexCMClass = (jclass) env->NewGlobalRef(iCMClass); 914 env->DeleteLocalRef(iCMClass); 915 DASSERT(AwtWin32GraphicsDevice::indexCMClass); 916 CHECK_NULL(AwtWin32GraphicsDevice::indexCMClass); 917 918 jclass wTClass = env->FindClass("sun/awt/windows/WToolkit"); 919 CHECK_NULL(wTClass); 920 AwtWin32GraphicsDevice::wToolkitClass = (jclass)env->NewGlobalRef(wTClass); 921 env->DeleteLocalRef(wTClass); 922 DASSERT(AwtWin32GraphicsDevice::wToolkitClass); 923 CHECK_NULL(AwtWin32GraphicsDevice::wToolkitClass); 924 925 /* field ids */ 926 AwtWin32GraphicsDevice::dynamicColorModelID = env->GetFieldID(cls, 927 "dynamicColorModel", "Ljava/awt/image/ColorModel;"); 928 DASSERT(AwtWin32GraphicsDevice::dynamicColorModelID); 929 CHECK_NULL(AwtWin32GraphicsDevice::dynamicColorModelID); 930 931 AwtWin32GraphicsDevice::indexCMrgbID = 932 env->GetFieldID(AwtWin32GraphicsDevice::indexCMClass, "rgb", "[I"); 933 DASSERT(AwtWin32GraphicsDevice::indexCMrgbID); 934 CHECK_NULL(AwtWin32GraphicsDevice::indexCMrgbID); 935 936 AwtWin32GraphicsDevice::indexCMcacheID = 937 env->GetFieldID(AwtWin32GraphicsDevice::indexCMClass, 938 "lookupcache", "[I"); 939 DASSERT(AwtWin32GraphicsDevice::indexCMcacheID); 940 CHECK_NULL(AwtWin32GraphicsDevice::indexCMcacheID); 941 942 /* method ids */ 943 AwtWin32GraphicsDevice::paletteChangedMID = env->GetStaticMethodID( 944 AwtWin32GraphicsDevice::wToolkitClass, "paletteChanged", "()V"); 945 DASSERT(AwtWin32GraphicsDevice::paletteChangedMID); 946 CHECK_NULL(AwtWin32GraphicsDevice::paletteChangedMID); 947 948 // Only want to call this once per session 949 make_uns_ordered_dither_array(img_oda_alpha, 256); 950 951 // workaround JDK-6477756, ignore return value to keep dll in memory 952 JDK_LoadSystemLibrary("opengl32.dll"); 953 954 CATCH_BAD_ALLOC; 955 } 956 957 } /* extern "C" */ 958 959 960 /* 961 * Class: sun_awt_Win32GraphicsDevice 962 * Method: getMaxConfigsImpl 963 * Signature: ()I 964 */ 965 966 JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getMaxConfigsImpl 967 (JNIEnv* jniEnv, jobject theThis, jint screen) { 968 TRY; 969 HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen); 970 971 PIXELFORMATDESCRIPTOR pfd; 972 int max = ::DescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR), 973 &pfd); 974 if (hDC != NULL) { 975 VERIFY(::DeleteDC(hDC)); 976 hDC = NULL; 977 } 978 //If ::DescribePixelFormat() fails, max = 0 979 //In this case, we return 1 config with visual number 0 980 if (max == 0) { 981 max = 1; 982 } 983 return (jint)max; 984 CATCH_BAD_ALLOC_RET(0); 985 } 986 987 /* 988 * Class: sun_awt_Win32GraphicsDevice 989 * Method: isPixFmtSupported 990 * Signature: (I)Z 991 */ 992 993 JNIEXPORT jboolean JNICALL Java_sun_awt_Win32GraphicsDevice_isPixFmtSupported 994 (JNIEnv* env, jobject theThis, jint pixFmtID, jint screen) { 995 TRY; 996 jboolean suppColor = JNI_TRUE; 997 HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen); 998 999 if (pixFmtID == 0) { 1000 return true; 1001 } 1002 1003 PIXELFORMATDESCRIPTOR pfd; 1004 int max = ::DescribePixelFormat(hDC, (int)pixFmtID, 1005 sizeof(PIXELFORMATDESCRIPTOR), &pfd); 1006 DASSERT(max); 1007 1008 //Check for supported ColorModel 1009 if ((pfd.cColorBits < 8) || 1010 ((pfd.cColorBits == 8) && (pfd.iPixelType != PFD_TYPE_COLORINDEX))) { 1011 //Note: this still allows for PixelFormats with > 8 color bits 1012 //which use COLORINDEX instead of RGB. This seems to work fine, 1013 //although issues may crop up involving PFD_NEED_PALETTE, which 1014 //is not currently taken into account. 1015 //If changes are made, they should also be reflected in 1016 //getDefaultPixID. 1017 suppColor = JNI_FALSE; 1018 } 1019 1020 if (hDC != NULL) { 1021 VERIFY(::DeleteDC(hDC)); 1022 hDC = NULL; 1023 } 1024 return (((pfd.dwFlags & REQUIRED_FLAGS) == REQUIRED_FLAGS) && suppColor) ? 1025 JNI_TRUE : JNI_FALSE; 1026 CATCH_BAD_ALLOC_RET(FALSE); 1027 } 1028 1029 /* 1030 * Class: sun_awt_Win32GraphicsDevice 1031 * Method: getDefaultPixIDImpl 1032 * Signature: (I)I 1033 */ 1034 1035 JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getDefaultPixIDImpl 1036 (JNIEnv* env, jobject theThis, jint screen) { 1037 TRY; 1038 int pixFmtID = 0; 1039 HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen); 1040 1041 PIXELFORMATDESCRIPTOR pfd = { 1042 sizeof(PIXELFORMATDESCRIPTOR), 1043 1, //version 1044 REQUIRED_FLAGS, //flags 1045 0, //iPixelType 1046 0, //cColorBits 1047 0,0,0,0,0,0,0,0, //cRedBits, cRedShift, green, blue, alpha 1048 0,0,0,0,0, //cAccumBits, cAccumRedBits, green, blue, alpha 1049 0,0,0,0,0,0,0,0 //etc. 1050 }; 1051 1052 //If 8-bit mode, must use Indexed mode 1053 if (8 == ::GetDeviceCaps(hDC, BITSPIXEL)) { 1054 pfd.iPixelType = PFD_TYPE_COLORINDEX; 1055 } 1056 1057 pixFmtID = ::ChoosePixelFormat(hDC, &pfd); 1058 if (pixFmtID == 0) { 1059 //Return 0 if GDI call fails. 1060 if (hDC != NULL) { 1061 VERIFY(::DeleteDC(hDC)); 1062 hDC = NULL; 1063 } 1064 return pixFmtID; 1065 } 1066 1067 if (JNI_FALSE == Java_sun_awt_Win32GraphicsDevice_isPixFmtSupported( 1068 env, theThis, pixFmtID, screen)) { 1069 /* Can't find a suitable pixel format ID. Fall back on 0. */ 1070 pixFmtID = 0; 1071 } 1072 1073 VERIFY(::DeleteDC(hDC)); 1074 hDC = NULL; 1075 return (jint)pixFmtID; 1076 CATCH_BAD_ALLOC_RET(0); 1077 } 1078 1079 /* 1080 * Class: sun_awt_Win32GraphicsDevice 1081 * Method: enterFullScreenExclusive 1082 * Signature: (Ljava/awt/peer/WindowPeer;)V 1083 */ 1084 1085 JNIEXPORT void JNICALL 1086 Java_sun_awt_Win32GraphicsDevice_enterFullScreenExclusive( 1087 JNIEnv* env, jobject graphicsDevice, 1088 jint screen, jobject windowPeer) { 1089 1090 TRY; 1091 1092 PDATA pData; 1093 JNI_CHECK_PEER_RETURN(windowPeer); 1094 1095 AwtWindow *window = (AwtWindow *)pData; // safe cast since we are called 1096 // with the WWindowPeer object 1097 HWND hWnd = window->GetHWnd(); 1098 1099 if (!::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, 1100 SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOSIZE)) 1101 { 1102 J2dTraceLn1(J2D_TRACE_ERROR, 1103 "Error %d setting topmost attribute to fs window", 1104 ::GetLastError()); 1105 } 1106 1107 CATCH_BAD_ALLOC; 1108 } 1109 1110 /* 1111 * Class: sun_awt_Win32GraphicsDevice 1112 * Method: exitFullScreenExclusive 1113 * Signature: (Ljava/awt/peer/WindowPeer;)V 1114 */ 1115 1116 JNIEXPORT void JNICALL 1117 Java_sun_awt_Win32GraphicsDevice_exitFullScreenExclusive( 1118 JNIEnv* env, jobject graphicsDevice, 1119 jint screen, jobject windowPeer) { 1120 1121 TRY; 1122 1123 PDATA pData; 1124 JNI_CHECK_PEER_RETURN(windowPeer); 1125 1126 AwtWindow *window = (AwtWindow *)pData; // safe cast since we are called 1127 // with the WWindowPeer object 1128 HWND hWnd = window->GetHWnd(); 1129 1130 jobject target = env->GetObjectField(windowPeer, AwtObject::targetID); 1131 jboolean alwaysOnTop = JNU_GetFieldByName(env, NULL, target, "alwaysOnTop", "Z").z; 1132 env->DeleteLocalRef(target); 1133 1134 if (!::SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, 1135 SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOSIZE)) 1136 { 1137 J2dTraceLn1(J2D_TRACE_ERROR, 1138 "Error %d unsetting topmost attribute to fs window", 1139 ::GetLastError()); 1140 } 1141 1142 // We should restore alwaysOnTop state as it's anyway dropped here 1143 Java_sun_awt_windows_WWindowPeer_setAlwaysOnTopNative(env, windowPeer, alwaysOnTop); 1144 1145 CATCH_BAD_ALLOC; 1146 } 1147 1148 jobject CreateDisplayMode(JNIEnv* env, jint width, jint height, 1149 jint bitDepth, jint refreshRate) { 1150 1151 TRY; 1152 1153 jclass displayModeClass = env->FindClass("java/awt/DisplayMode"); 1154 if (JNU_IsNull(env, displayModeClass)) { 1155 env->ExceptionClear(); 1156 JNU_ThrowInternalError(env, "Could not get display mode class"); 1157 return NULL; 1158 } 1159 1160 jmethodID cid = env->GetMethodID(displayModeClass, "<init>", "(IIII)V"); 1161 if (cid == NULL) { 1162 env->ExceptionClear(); 1163 JNU_ThrowInternalError(env, "Could not get display mode constructor"); 1164 return NULL; 1165 } 1166 1167 jobject displayMode = env->NewObject(displayModeClass, cid, width, 1168 height, bitDepth, refreshRate); 1169 return displayMode; 1170 1171 CATCH_BAD_ALLOC_RET(NULL); 1172 } 1173 1174 /** 1175 * A utility function which retrieves a DISPLAY_DEVICE information 1176 * given a screen number. 1177 * 1178 * If the function was able to find an attached device for the given screen 1179 * number, the lpDisplayDevice will be initialized with the data and 1180 * the function will return TRUE, otherwise it returns FALSE and contents 1181 * of the structure pointed to by lpDisplayDevice is undefined. 1182 */ 1183 static BOOL 1184 GetAttachedDisplayDevice(int screen, DISPLAY_DEVICE *lpDisplayDevice) 1185 { 1186 DWORD dwDeviceNum = 0; 1187 lpDisplayDevice->cb = sizeof(DISPLAY_DEVICE); 1188 while (EnumDisplayDevices(NULL, dwDeviceNum, lpDisplayDevice, 0) && 1189 dwDeviceNum < 20) // avoid infinite loop with buggy drivers 1190 { 1191 if (lpDisplayDevice->StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) { 1192 Devices::InstanceAccess devices; 1193 MONITORINFOEX *pMonInfo = 1194 (LPMONITORINFOEX)devices->GetDevice(screen)->GetMonitorInfo(); 1195 // make sure the device names match 1196 if (wcscmp(pMonInfo->szDevice, lpDisplayDevice->DeviceName) == 0) { 1197 return TRUE; 1198 } 1199 } 1200 dwDeviceNum++; 1201 } 1202 return FALSE; 1203 } 1204 1205 /* 1206 * Class: sun_awt_Win32GraphicsDevice 1207 * Method: getCurrentDisplayMode 1208 * Signature: (IZ)Ljava/awt/DisplayMode; 1209 */ 1210 JNIEXPORT jobject JNICALL 1211 Java_sun_awt_Win32GraphicsDevice_getCurrentDisplayMode 1212 (JNIEnv* env, jobject graphicsDevice, jint screen) 1213 { 1214 TRY; 1215 1216 DEVMODE dm; 1217 LPTSTR pName = NULL; 1218 1219 dm.dmSize = sizeof(dm); 1220 dm.dmDriverExtra = 0; 1221 1222 DISPLAY_DEVICE displayDevice; 1223 if (GetAttachedDisplayDevice(screen, &displayDevice)) { 1224 pName = displayDevice.DeviceName; 1225 } 1226 if (!EnumDisplaySettings(pName, ENUM_CURRENT_SETTINGS, &dm)) 1227 { 1228 return NULL; 1229 } 1230 1231 return CreateDisplayMode(env, dm.dmPelsWidth, 1232 dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency); 1233 1234 CATCH_BAD_ALLOC_RET(NULL); 1235 } 1236 1237 /* 1238 * Class: sun_awt_Win32GraphicsDevice 1239 * Method: configDisplayMode 1240 * Signature: (IIIIZ)V 1241 */ 1242 JNIEXPORT void JNICALL 1243 Java_sun_awt_Win32GraphicsDevice_configDisplayMode 1244 (JNIEnv* env, jobject graphicsDevice, jint screen, jobject windowPeer, 1245 jint width, jint height, jint bitDepth, jint refreshRate) 1246 { 1247 TRY; 1248 1249 DEVMODE dm; 1250 1251 dm.dmSize = sizeof(dm); 1252 dm.dmDriverExtra = 0; 1253 dm.dmPelsWidth = width; 1254 dm.dmPelsHeight = height; 1255 dm.dmBitsPerPel = bitDepth; 1256 dm.dmDisplayFrequency = refreshRate; 1257 dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | 1258 DM_BITSPERPEL | DM_DISPLAYFREQUENCY; 1259 1260 // ChangeDisplaySettings works only on the primary screen. 1261 // ChangeDisplaySettingsEx is not available on NT, 1262 // so it'd be nice not to break it if we can help it. 1263 if (screen == AwtWin32GraphicsDevice::GetDefaultDeviceIndex()) { 1264 if (::ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != 1265 DISP_CHANGE_SUCCESSFUL) 1266 { 1267 JNU_ThrowInternalError(env, 1268 "Could not set display mode"); 1269 } 1270 return; 1271 } 1272 1273 DISPLAY_DEVICE displayDevice; 1274 if (!GetAttachedDisplayDevice(screen, &displayDevice) || 1275 (::ChangeDisplaySettingsEx(displayDevice.DeviceName, &dm, NULL, CDS_FULLSCREEN, NULL) != 1276 DISP_CHANGE_SUCCESSFUL)) 1277 { 1278 JNU_ThrowInternalError(env, 1279 "Could not set display mode"); 1280 } 1281 1282 CATCH_BAD_ALLOC; 1283 } 1284 1285 class EnumDisplayModeParam { 1286 public: 1287 EnumDisplayModeParam(JNIEnv* e, jobject a) : env(e), arrayList(a) {} 1288 JNIEnv* env; 1289 jobject arrayList; 1290 }; 1291 1292 void addDisplayMode(JNIEnv* env, jobject arrayList, jint width, 1293 jint height, jint bitDepth, jint refreshRate) { 1294 1295 TRY; 1296 1297 jobject displayMode = CreateDisplayMode(env, width, height, 1298 bitDepth, refreshRate); 1299 if (!JNU_IsNull(env, displayMode)) { 1300 jclass arrayListClass = env->GetObjectClass(arrayList); 1301 if (JNU_IsNull(env, arrayListClass)) { 1302 JNU_ThrowInternalError(env, 1303 "Could not get class java.util.ArrayList"); 1304 return; 1305 } 1306 jmethodID mid = env->GetMethodID(arrayListClass, "add", 1307 "(Ljava/lang/Object;)Z"); 1308 if (mid == NULL) { 1309 env->ExceptionClear(); 1310 JNU_ThrowInternalError(env, 1311 "Could not get method java.util.ArrayList.add()"); 1312 return; 1313 } 1314 env->CallObjectMethod(arrayList, mid, displayMode); 1315 env->DeleteLocalRef(displayMode); 1316 } 1317 1318 CATCH_BAD_ALLOC; 1319 } 1320 1321 /* 1322 * Class: sun_awt_Win32GraphicsDevice 1323 * Method: enumDisplayModes 1324 * Signature: (Ljava/util/ArrayList;Z)V 1325 */ 1326 JNIEXPORT void JNICALL Java_sun_awt_Win32GraphicsDevice_enumDisplayModes 1327 (JNIEnv* env, jobject graphicsDevice, jint screen, jobject arrayList) 1328 { 1329 1330 TRY; 1331 1332 DEVMODE dm; 1333 LPTSTR pName = NULL; 1334 DISPLAY_DEVICE displayDevice; 1335 1336 1337 if (GetAttachedDisplayDevice(screen, &displayDevice)) { 1338 pName = displayDevice.DeviceName; 1339 } 1340 1341 dm.dmSize = sizeof(dm); 1342 dm.dmDriverExtra = 0; 1343 1344 BOOL bContinue = TRUE; 1345 for (int i = 0; bContinue; i++) { 1346 bContinue = EnumDisplaySettings(pName, i, &dm); 1347 if (dm.dmBitsPerPel >= 8) { 1348 addDisplayMode(env, arrayList, dm.dmPelsWidth, dm.dmPelsHeight, 1349 dm.dmBitsPerPel, dm.dmDisplayFrequency); 1350 JNU_CHECK_EXCEPTION(env); 1351 } 1352 } 1353 1354 CATCH_BAD_ALLOC; 1355 } 1356 1357 /* 1358 * Class: sun_awt_Win32GraphicsDevice 1359 * Method: makeColorModel 1360 * Signature: ()Ljava/awt/image/ColorModel 1361 */ 1362 1363 JNIEXPORT jobject JNICALL 1364 Java_sun_awt_Win32GraphicsDevice_makeColorModel 1365 (JNIEnv *env, jobject thisPtr, jint screen, jboolean dynamic) 1366 { 1367 Devices::InstanceAccess devices; 1368 return devices->GetDevice(screen)->GetColorModel(env, dynamic); 1369 } 1370 1371 /* 1372 * Class: sun_awt_Win32GraphicsDevice 1373 * Method: initDevice 1374 * Signature: (I)V 1375 */ 1376 JNIEXPORT void JNICALL 1377 Java_sun_awt_Win32GraphicsDevice_initDevice 1378 (JNIEnv *env, jobject thisPtr, jint screen) 1379 { 1380 Devices::InstanceAccess devices; 1381 devices->GetDevice(screen)->SetJavaDevice(env, thisPtr); 1382 } 1383 1384 /* 1385 * Class: sun_awt_Win32GraphicsDevice 1386 * Method: setNativeScale 1387 * Signature: (I,F,F)V 1388 */ 1389 JNIEXPORT void JNICALL 1390 Java_sun_awt_Win32GraphicsDevice_setNativeScale 1391 (JNIEnv *env, jobject thisPtr, jint screen, jfloat scaleX, jfloat scaleY) 1392 { 1393 Devices::InstanceAccess devices; 1394 AwtWin32GraphicsDevice *device = devices->GetDevice(screen); 1395 1396 if (device != NULL ) { 1397 device->SetScale(scaleX, scaleY); 1398 } 1399 } 1400 1401 /* 1402 * Class: sun_awt_Win32GraphicsDevice 1403 * Method: getNativeScaleX 1404 * Signature: (I)F 1405 */ 1406 JNIEXPORT jfloat JNICALL 1407 Java_sun_awt_Win32GraphicsDevice_getNativeScaleX 1408 (JNIEnv *env, jobject thisPtr, jint screen) 1409 { 1410 Devices::InstanceAccess devices; 1411 AwtWin32GraphicsDevice *device = devices->GetDevice(screen); 1412 return (device == NULL) ? 1 : device->GetScaleX(); 1413 } 1414 1415 /* 1416 * Class: sun_awt_Win32GraphicsDevice 1417 * Method: getNativeScaleY 1418 * Signature: (I)F 1419 */ 1420 JNIEXPORT jfloat JNICALL 1421 Java_sun_awt_Win32GraphicsDevice_getNativeScaleY 1422 (JNIEnv *env, jobject thisPtr, jint screen) 1423 { 1424 Devices::InstanceAccess devices; 1425 AwtWin32GraphicsDevice *device = devices->GetDevice(screen); 1426 return (device == NULL) ? 1 : device->GetScaleY(); 1427 } 1428 1429 /* 1430 * Class: sun_awt_Win32GraphicsDevice 1431 * Method: initNativeScale 1432 * Signature: (I)V; 1433 */ 1434 JNIEXPORT void JNICALL 1435 Java_sun_awt_Win32GraphicsDevice_initNativeScale 1436 (JNIEnv *env, jobject thisPtr, jint screen) 1437 { 1438 Devices::InstanceAccess devices; 1439 AwtWin32GraphicsDevice *device = devices->GetDevice(screen); 1440 1441 if (device != NULL) { 1442 device->InitDesktopScales(); 1443 } 1444 } 1445