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 // workaround JDK-6477756, ignore return value to keep dll in memory 933 JDK_LoadSystemLibrary("opengl32.dll"); 934 935 CATCH_BAD_ALLOC; 936 } 937 938 } /* extern "C" */ 939 940 941 /* 942 * Class: sun_awt_Win32GraphicsDevice 943 * Method: getMaxConfigsImpl 944 * Signature: ()I 945 */ 946 947 JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getMaxConfigsImpl 948 (JNIEnv* jniEnv, jobject theThis, jint screen) { 949 TRY; 950 HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen); 951 952 PIXELFORMATDESCRIPTOR pfd; 953 int max = ::DescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR), 954 &pfd); 955 if (hDC != NULL) { 956 VERIFY(::DeleteDC(hDC)); 957 hDC = NULL; 958 } 959 //If ::DescribePixelFormat() fails, max = 0 960 //In this case, we return 1 config with visual number 0 961 if (max == 0) { 962 max = 1; 963 } 964 return (jint)max; 965 CATCH_BAD_ALLOC_RET(0); 966 } 967 968 /* 969 * Class: sun_awt_Win32GraphicsDevice 970 * Method: isPixFmtSupported 971 * Signature: (I)Z 972 */ 973 974 JNIEXPORT jboolean JNICALL Java_sun_awt_Win32GraphicsDevice_isPixFmtSupported 975 (JNIEnv* env, jobject theThis, jint pixFmtID, jint screen) { 976 TRY; 977 jboolean suppColor = JNI_TRUE; 978 HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen); 979 980 if (pixFmtID == 0) { 981 return true; 982 } 983 984 PIXELFORMATDESCRIPTOR pfd; 985 int max = ::DescribePixelFormat(hDC, (int)pixFmtID, 986 sizeof(PIXELFORMATDESCRIPTOR), &pfd); 987 DASSERT(max); 988 989 //Check for supported ColorModel 990 if ((pfd.cColorBits < 8) || 991 ((pfd.cColorBits == 8) && (pfd.iPixelType != PFD_TYPE_COLORINDEX))) { 992 //Note: this still allows for PixelFormats with > 8 color bits 993 //which use COLORINDEX instead of RGB. This seems to work fine, 994 //although issues may crop up involving PFD_NEED_PALETTE, which 995 //is not currently taken into account. 996 //If changes are made, they should also be reflected in 997 //getDefaultPixID. 998 suppColor = JNI_FALSE; 999 } 1000 1001 if (hDC != NULL) { 1002 VERIFY(::DeleteDC(hDC)); 1003 hDC = NULL; 1004 } 1005 return (((pfd.dwFlags & REQUIRED_FLAGS) == REQUIRED_FLAGS) && suppColor) ? 1006 JNI_TRUE : JNI_FALSE; 1007 CATCH_BAD_ALLOC_RET(FALSE); 1008 } 1009 1010 /* 1011 * Class: sun_awt_Win32GraphicsDevice 1012 * Method: getDefaultPixIDImpl 1013 * Signature: (I)I 1014 */ 1015 1016 JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getDefaultPixIDImpl 1017 (JNIEnv* env, jobject theThis, jint screen) { 1018 TRY; 1019 int pixFmtID = 0; 1020 HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen); 1021 1022 PIXELFORMATDESCRIPTOR pfd = { 1023 sizeof(PIXELFORMATDESCRIPTOR), 1024 1, //version 1025 REQUIRED_FLAGS, //flags 1026 0, //iPixelType 1027 0, //cColorBits 1028 0,0,0,0,0,0,0,0, //cRedBits, cRedShift, green, blue, alpha 1029 0,0,0,0,0, //cAccumBits, cAccumRedBits, green, blue, alpha 1030 0,0,0,0,0,0,0,0 //etc. 1031 }; 1032 1033 //If 8-bit mode, must use Indexed mode 1034 if (8 == ::GetDeviceCaps(hDC, BITSPIXEL)) { 1035 pfd.iPixelType = PFD_TYPE_COLORINDEX; 1036 } 1037 1038 pixFmtID = ::ChoosePixelFormat(hDC, &pfd); 1039 if (pixFmtID == 0) { 1040 //Return 0 if GDI call fails. 1041 if (hDC != NULL) { 1042 VERIFY(::DeleteDC(hDC)); 1043 hDC = NULL; 1044 } 1045 return pixFmtID; 1046 } 1047 1048 if (JNI_FALSE == Java_sun_awt_Win32GraphicsDevice_isPixFmtSupported( 1049 env, theThis, pixFmtID, screen)) { 1050 /* Can't find a suitable pixel format ID. Fall back on 0. */ 1051 pixFmtID = 0; 1052 } 1053 1054 VERIFY(::DeleteDC(hDC)); 1055 hDC = NULL; 1056 return (jint)pixFmtID; 1057 CATCH_BAD_ALLOC_RET(0); 1058 } 1059 1060 /* 1061 * Class: sun_awt_Win32GraphicsDevice 1062 * Method: enterFullScreenExclusive 1063 * Signature: (Ljava/awt/peer/WindowPeer;)V 1064 */ 1065 1066 JNIEXPORT void JNICALL 1067 Java_sun_awt_Win32GraphicsDevice_enterFullScreenExclusive( 1068 JNIEnv* env, jobject graphicsDevice, 1069 jint screen, jobject windowPeer) { 1070 1071 TRY; 1072 1073 PDATA pData; 1074 JNI_CHECK_PEER_RETURN(windowPeer); 1075 1076 AwtWindow *window = (AwtWindow *)pData; // safe cast since we are called 1077 // with the WWindowPeer object 1078 HWND hWnd = window->GetHWnd(); 1079 1080 if (!::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, 1081 SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOSIZE)) 1082 { 1083 J2dTraceLn1(J2D_TRACE_ERROR, 1084 "Error %d setting topmost attribute to fs window", 1085 ::GetLastError()); 1086 } 1087 1088 CATCH_BAD_ALLOC; 1089 } 1090 1091 /* 1092 * Class: sun_awt_Win32GraphicsDevice 1093 * Method: exitFullScreenExclusive 1094 * Signature: (Ljava/awt/peer/WindowPeer;)V 1095 */ 1096 1097 JNIEXPORT void JNICALL 1098 Java_sun_awt_Win32GraphicsDevice_exitFullScreenExclusive( 1099 JNIEnv* env, jobject graphicsDevice, 1100 jint screen, jobject windowPeer) { 1101 1102 TRY; 1103 1104 PDATA pData; 1105 JNI_CHECK_PEER_RETURN(windowPeer); 1106 1107 AwtWindow *window = (AwtWindow *)pData; // safe cast since we are called 1108 // with the WWindowPeer object 1109 HWND hWnd = window->GetHWnd(); 1110 1111 jobject target = env->GetObjectField(windowPeer, AwtObject::targetID); 1112 jboolean alwaysOnTop = JNU_GetFieldByName(env, NULL, target, "alwaysOnTop", "Z").z; 1113 env->DeleteLocalRef(target); 1114 1115 if (!::SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, 1116 SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOSIZE)) 1117 { 1118 J2dTraceLn1(J2D_TRACE_ERROR, 1119 "Error %d unsetting topmost attribute to fs window", 1120 ::GetLastError()); 1121 } 1122 1123 // We should restore alwaysOnTop state as it's anyway dropped here 1124 Java_sun_awt_windows_WWindowPeer_setAlwaysOnTopNative(env, windowPeer, alwaysOnTop); 1125 1126 CATCH_BAD_ALLOC; 1127 } 1128 1129 jobject CreateDisplayMode(JNIEnv* env, jint width, jint height, 1130 jint bitDepth, jint refreshRate) { 1131 1132 TRY; 1133 1134 jclass displayModeClass = env->FindClass("java/awt/DisplayMode"); 1135 if (JNU_IsNull(env, displayModeClass)) { 1136 env->ExceptionClear(); 1137 JNU_ThrowInternalError(env, "Could not get display mode class"); 1138 return NULL; 1139 } 1140 1141 jmethodID cid = env->GetMethodID(displayModeClass, "<init>", "(IIII)V"); 1142 if (cid == NULL) { 1143 env->ExceptionClear(); 1144 JNU_ThrowInternalError(env, "Could not get display mode constructor"); 1145 return NULL; 1146 } 1147 1148 jobject displayMode = env->NewObject(displayModeClass, cid, width, 1149 height, bitDepth, refreshRate); 1150 return displayMode; 1151 1152 CATCH_BAD_ALLOC_RET(NULL); 1153 } 1154 1155 /** 1156 * A utility function which retrieves a DISPLAY_DEVICE information 1157 * given a screen number. 1158 * 1159 * If the function was able to find an attached device for the given screen 1160 * number, the lpDisplayDevice will be initialized with the data and 1161 * the function will return TRUE, otherwise it returns FALSE and contents 1162 * of the structure pointed to by lpDisplayDevice is undefined. 1163 */ 1164 static BOOL 1165 GetAttachedDisplayDevice(int screen, DISPLAY_DEVICE *lpDisplayDevice) 1166 { 1167 DWORD dwDeviceNum = 0; 1168 lpDisplayDevice->cb = sizeof(DISPLAY_DEVICE); 1169 while (EnumDisplayDevices(NULL, dwDeviceNum, lpDisplayDevice, 0) && 1170 dwDeviceNum < 20) // avoid infinite loop with buggy drivers 1171 { 1172 if (lpDisplayDevice->StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) { 1173 Devices::InstanceAccess devices; 1174 MONITORINFOEX *pMonInfo = 1175 (LPMONITORINFOEX)devices->GetDevice(screen)->GetMonitorInfo(); 1176 // make sure the device names match 1177 if (wcscmp(pMonInfo->szDevice, lpDisplayDevice->DeviceName) == 0) { 1178 return TRUE; 1179 } 1180 } 1181 dwDeviceNum++; 1182 } 1183 return FALSE; 1184 } 1185 1186 /* 1187 * Class: sun_awt_Win32GraphicsDevice 1188 * Method: getCurrentDisplayMode 1189 * Signature: (IZ)Ljava/awt/DisplayMode; 1190 */ 1191 JNIEXPORT jobject JNICALL 1192 Java_sun_awt_Win32GraphicsDevice_getCurrentDisplayMode 1193 (JNIEnv* env, jobject graphicsDevice, jint screen) 1194 { 1195 TRY; 1196 1197 DEVMODE dm; 1198 LPTSTR pName = NULL; 1199 1200 dm.dmSize = sizeof(dm); 1201 dm.dmDriverExtra = 0; 1202 1203 DISPLAY_DEVICE displayDevice; 1204 if (GetAttachedDisplayDevice(screen, &displayDevice)) { 1205 pName = displayDevice.DeviceName; 1206 } 1207 if (!EnumDisplaySettings(pName, ENUM_CURRENT_SETTINGS, &dm)) 1208 { 1209 return NULL; 1210 } 1211 1212 return CreateDisplayMode(env, dm.dmPelsWidth, 1213 dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency); 1214 1215 CATCH_BAD_ALLOC_RET(NULL); 1216 } 1217 1218 /* 1219 * Class: sun_awt_Win32GraphicsDevice 1220 * Method: configDisplayMode 1221 * Signature: (IIIIZ)V 1222 */ 1223 JNIEXPORT void JNICALL 1224 Java_sun_awt_Win32GraphicsDevice_configDisplayMode 1225 (JNIEnv* env, jobject graphicsDevice, jint screen, jobject windowPeer, 1226 jint width, jint height, jint bitDepth, jint refreshRate) 1227 { 1228 TRY; 1229 1230 DEVMODE dm; 1231 1232 dm.dmSize = sizeof(dm); 1233 dm.dmDriverExtra = 0; 1234 dm.dmPelsWidth = width; 1235 dm.dmPelsHeight = height; 1236 dm.dmBitsPerPel = bitDepth; 1237 dm.dmDisplayFrequency = refreshRate; 1238 dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | 1239 DM_BITSPERPEL | DM_DISPLAYFREQUENCY; 1240 1241 // ChangeDisplaySettings works only on the primary screen. 1242 // ChangeDisplaySettingsEx is not available on NT, 1243 // so it'd be nice not to break it if we can help it. 1244 if (screen == AwtWin32GraphicsDevice::GetDefaultDeviceIndex()) { 1245 if (::ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != 1246 DISP_CHANGE_SUCCESSFUL) 1247 { 1248 JNU_ThrowInternalError(env, 1249 "Could not set display mode"); 1250 } 1251 return; 1252 } 1253 1254 DISPLAY_DEVICE displayDevice; 1255 if (!GetAttachedDisplayDevice(screen, &displayDevice) || 1256 (::ChangeDisplaySettingsEx(displayDevice.DeviceName, &dm, NULL, CDS_FULLSCREEN, NULL) != 1257 DISP_CHANGE_SUCCESSFUL)) 1258 { 1259 JNU_ThrowInternalError(env, 1260 "Could not set display mode"); 1261 } 1262 1263 CATCH_BAD_ALLOC; 1264 } 1265 1266 class EnumDisplayModeParam { 1267 public: 1268 EnumDisplayModeParam(JNIEnv* e, jobject a) : env(e), arrayList(a) {} 1269 JNIEnv* env; 1270 jobject arrayList; 1271 }; 1272 1273 void addDisplayMode(JNIEnv* env, jobject arrayList, jint width, 1274 jint height, jint bitDepth, jint refreshRate) { 1275 1276 TRY; 1277 1278 jobject displayMode = CreateDisplayMode(env, width, height, 1279 bitDepth, refreshRate); 1280 if (!JNU_IsNull(env, displayMode)) { 1281 jclass arrayListClass = env->GetObjectClass(arrayList); 1282 if (JNU_IsNull(env, arrayListClass)) { 1283 JNU_ThrowInternalError(env, 1284 "Could not get class java.util.ArrayList"); 1285 return; 1286 } 1287 jmethodID mid = env->GetMethodID(arrayListClass, "add", 1288 "(Ljava/lang/Object;)Z"); 1289 if (mid == NULL) { 1290 env->ExceptionClear(); 1291 JNU_ThrowInternalError(env, 1292 "Could not get method java.util.ArrayList.add()"); 1293 return; 1294 } 1295 env->CallObjectMethod(arrayList, mid, displayMode); 1296 env->DeleteLocalRef(displayMode); 1297 } 1298 1299 CATCH_BAD_ALLOC; 1300 } 1301 1302 /* 1303 * Class: sun_awt_Win32GraphicsDevice 1304 * Method: enumDisplayModes 1305 * Signature: (Ljava/util/ArrayList;Z)V 1306 */ 1307 JNIEXPORT void JNICALL Java_sun_awt_Win32GraphicsDevice_enumDisplayModes 1308 (JNIEnv* env, jobject graphicsDevice, jint screen, jobject arrayList) 1309 { 1310 1311 TRY; 1312 1313 DEVMODE dm; 1314 LPTSTR pName = NULL; 1315 DISPLAY_DEVICE displayDevice; 1316 1317 1318 if (GetAttachedDisplayDevice(screen, &displayDevice)) { 1319 pName = displayDevice.DeviceName; 1320 } 1321 1322 dm.dmSize = sizeof(dm); 1323 dm.dmDriverExtra = 0; 1324 1325 BOOL bContinue = TRUE; 1326 for (int i = 0; bContinue; i++) { 1327 bContinue = EnumDisplaySettings(pName, i, &dm); 1328 if (dm.dmBitsPerPel >= 8) { 1329 addDisplayMode(env, arrayList, dm.dmPelsWidth, dm.dmPelsHeight, 1330 dm.dmBitsPerPel, dm.dmDisplayFrequency); 1331 JNU_CHECK_EXCEPTION(env); 1332 } 1333 } 1334 1335 CATCH_BAD_ALLOC; 1336 } 1337 1338 /* 1339 * Class: sun_awt_Win32GraphicsDevice 1340 * Method: makeColorModel 1341 * Signature: ()Ljava/awt/image/ColorModel 1342 */ 1343 1344 JNIEXPORT jobject JNICALL 1345 Java_sun_awt_Win32GraphicsDevice_makeColorModel 1346 (JNIEnv *env, jobject thisPtr, jint screen, jboolean dynamic) 1347 { 1348 Devices::InstanceAccess devices; 1349 return devices->GetDevice(screen)->GetColorModel(env, dynamic); 1350 } 1351 1352 /* 1353 * Class: sun_awt_Win32GraphicsDevice 1354 * Method: initDevice 1355 * Signature: (I)V 1356 */ 1357 JNIEXPORT void JNICALL 1358 Java_sun_awt_Win32GraphicsDevice_initDevice 1359 (JNIEnv *env, jobject thisPtr, jint screen) 1360 { 1361 Devices::InstanceAccess devices; 1362 devices->GetDevice(screen)->SetJavaDevice(env, thisPtr); 1363 } 1364 1365 /* 1366 * Class: sun_awt_Win32GraphicsDevice 1367 * Method: setNativeScale 1368 * Signature: (I,F,F)V 1369 */ 1370 JNIEXPORT void JNICALL 1371 Java_sun_awt_Win32GraphicsDevice_setNativeScale 1372 (JNIEnv *env, jobject thisPtr, jint screen, jfloat scaleX, jfloat scaleY) 1373 { 1374 Devices::InstanceAccess devices; 1375 AwtWin32GraphicsDevice *device = devices->GetDevice(screen); 1376 1377 if (device != NULL ) { 1378 device->SetScale(scaleX, scaleY); 1379 } 1380 } 1381 1382 /* 1383 * Class: sun_awt_Win32GraphicsDevice 1384 * Method: getNativeScaleX 1385 * Signature: (I)F 1386 */ 1387 JNIEXPORT jfloat JNICALL 1388 Java_sun_awt_Win32GraphicsDevice_getNativeScaleX 1389 (JNIEnv *env, jobject thisPtr, jint screen) 1390 { 1391 Devices::InstanceAccess devices; 1392 AwtWin32GraphicsDevice *device = devices->GetDevice(screen); 1393 return (device == NULL) ? 1 : device->GetScaleX(); 1394 } 1395 1396 /* 1397 * Class: sun_awt_Win32GraphicsDevice 1398 * Method: getNativeScaleY 1399 * Signature: (I)F 1400 */ 1401 JNIEXPORT jfloat JNICALL 1402 Java_sun_awt_Win32GraphicsDevice_getNativeScaleY 1403 (JNIEnv *env, jobject thisPtr, jint screen) 1404 { 1405 Devices::InstanceAccess devices; 1406 AwtWin32GraphicsDevice *device = devices->GetDevice(screen); 1407 return (device == NULL) ? 1 : device->GetScaleY(); 1408 } 1409 1410 /* 1411 * Class: sun_awt_Win32GraphicsDevice 1412 * Method: initNativeScale 1413 * Signature: (I)V; 1414 */ 1415 JNIEXPORT void JNICALL 1416 Java_sun_awt_Win32GraphicsDevice_initNativeScale 1417 (JNIEnv *env, jobject thisPtr, jint screen) 1418 { 1419 Devices::InstanceAccess devices; 1420 AwtWin32GraphicsDevice *device = devices->GetDevice(screen); 1421 1422 if (device != NULL) { 1423 device->InitDesktopScales(); 1424 } 1425 } 1426