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