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