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 */
AwtWin32GraphicsDevice(int screen,HMONITOR mhnd,Devices * arr)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
~AwtWin32GraphicsDevice()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
MakeDCFromMonitor(HMONITOR hmMonitor)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
GetDC()143 HDC AwtWin32GraphicsDevice::GetDC()
144 {
145 return MakeDCFromMonitor(monitor);
146 }
147
ReleaseDC(HDC hDC)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 */
Initialize()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 */
GetColorModel(JNIEnv * env,jboolean dynamic)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 */
SetGrayness(int grayValue)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 */
UpdateDynamicColorModel()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
GetSystemPaletteEntries()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
GetSystemInverseLUT()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
UpdateSystemPalette()551 BOOL AwtWin32GraphicsDevice::UpdateSystemPalette()
552 {
553 if (colorData->bitsperpixel > 8) {
554 return FALSE;
555 } else {
556 return palette->Update();
557 }
558 }
559
SelectPalette(HDC hDC)560 HPALETTE AwtWin32GraphicsDevice::SelectPalette(HDC hDC)
561 {
562 if (palette) {
563 return palette->Select(hDC);
564 } else {
565 return NULL;
566 }
567 }
568
RealizePalette(HDC hDC)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 */
DeviceIndexForWindow(HWND hWnd)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 */
GetPalette()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 */
Release()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 */
SetJavaDevice(JNIEnv * env,jobject objPtr)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 */
DisableOffscreenAcceleration()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 */
Invalidate(JNIEnv * env)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
GetColorModel(JNIEnv * env,jboolean dynamic,int deviceIndex)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
GetMonitorInfo(int deviceIndex)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 */
ResetAllMonitorInfo()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
DisableOffscreenAccelerationForDevice(HMONITOR hMonitor)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
GetMonitor(int deviceIndex)705 HMONITOR AwtWin32GraphicsDevice::GetMonitor(int deviceIndex)
706 {
707 Devices::InstanceAccess devices;
708 return devices->GetDevice(deviceIndex)->GetMonitor();
709 }
710
GetPalette(int deviceIndex)711 HPALETTE AwtWin32GraphicsDevice::GetPalette(int deviceIndex)
712 {
713 Devices::InstanceAccess devices;
714 return devices->GetDevice(deviceIndex)->GetPalette();
715 }
716
UpdateDynamicColorModel(int deviceIndex)717 void AwtWin32GraphicsDevice::UpdateDynamicColorModel(int deviceIndex)
718 {
719 Devices::InstanceAccess devices;
720 devices->GetDevice(deviceIndex)->UpdateDynamicColorModel();
721 }
722
UpdateSystemPalette(int deviceIndex)723 BOOL AwtWin32GraphicsDevice::UpdateSystemPalette(int deviceIndex)
724 {
725 Devices::InstanceAccess devices;
726 return devices->GetDevice(deviceIndex)->UpdateSystemPalette();
727 }
728
SelectPalette(HDC hDC,int deviceIndex)729 HPALETTE AwtWin32GraphicsDevice::SelectPalette(HDC hDC, int deviceIndex)
730 {
731 Devices::InstanceAccess devices;
732 return devices->GetDevice(deviceIndex)->SelectPalette(hDC);
733 }
734
RealizePalette(HDC hDC,int deviceIndex)735 void AwtWin32GraphicsDevice::RealizePalette(HDC hDC, int deviceIndex)
736 {
737 Devices::InstanceAccess devices;
738 devices->GetDevice(deviceIndex)->RealizePalette(hDC);
739 }
740
GetColorData(int deviceIndex)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 */
GetGrayness(int deviceIndex)750 int AwtWin32GraphicsDevice::GetGrayness(int deviceIndex)
751 {
752 Devices::InstanceAccess devices;
753 return devices->GetDevice(deviceIndex)->GetGrayness();
754 }
755
GetDCFromScreen(int screen)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 */
AreSameMonitors(HMONITOR mon1,HMONITOR mon2)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
GetScreenFromHMONITOR(HMONITOR mon)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
Java_sun_awt_Win32GraphicsDevice_initIDs(JNIEnv * env,jclass cls)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 // workaround JDK-6477756, ignore return value to keep dll in memory
879 JDK_LoadSystemLibrary("opengl32.dll");
880
881 CATCH_BAD_ALLOC;
882 }
883
884 } /* extern "C" */
885
886
887 /*
888 * Class: sun_awt_Win32GraphicsDevice
889 * Method: getMaxConfigsImpl
890 * Signature: ()I
891 */
892
Java_sun_awt_Win32GraphicsDevice_getMaxConfigsImpl(JNIEnv * jniEnv,jobject theThis,jint screen)893 JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getMaxConfigsImpl
894 (JNIEnv* jniEnv, jobject theThis, jint screen) {
895 TRY;
896 HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen);
897
898 PIXELFORMATDESCRIPTOR pfd;
899 int max = ::DescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR),
900 &pfd);
901 if (hDC != NULL) {
902 VERIFY(::DeleteDC(hDC));
903 hDC = NULL;
904 }
905 //If ::DescribePixelFormat() fails, max = 0
906 //In this case, we return 1 config with visual number 0
907 if (max == 0) {
908 max = 1;
909 }
910 return (jint)max;
911 CATCH_BAD_ALLOC_RET(0);
912 }
913
914 /*
915 * Class: sun_awt_Win32GraphicsDevice
916 * Method: isPixFmtSupported
917 * Signature: (I)Z
918 */
919
Java_sun_awt_Win32GraphicsDevice_isPixFmtSupported(JNIEnv * env,jobject theThis,jint pixFmtID,jint screen)920 JNIEXPORT jboolean JNICALL Java_sun_awt_Win32GraphicsDevice_isPixFmtSupported
921 (JNIEnv* env, jobject theThis, jint pixFmtID, jint screen) {
922 TRY;
923 jboolean suppColor = JNI_TRUE;
924 HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen);
925
926 if (pixFmtID == 0) {
927 return true;
928 }
929
930 PIXELFORMATDESCRIPTOR pfd;
931 int max = ::DescribePixelFormat(hDC, (int)pixFmtID,
932 sizeof(PIXELFORMATDESCRIPTOR), &pfd);
933 DASSERT(max);
934
935 //Check for supported ColorModel
936 if ((pfd.cColorBits < 8) ||
937 ((pfd.cColorBits == 8) && (pfd.iPixelType != PFD_TYPE_COLORINDEX))) {
938 //Note: this still allows for PixelFormats with > 8 color bits
939 //which use COLORINDEX instead of RGB. This seems to work fine,
940 //although issues may crop up involving PFD_NEED_PALETTE, which
941 //is not currently taken into account.
942 //If changes are made, they should also be reflected in
943 //getDefaultPixID.
944 suppColor = JNI_FALSE;
945 }
946
947 if (hDC != NULL) {
948 VERIFY(::DeleteDC(hDC));
949 hDC = NULL;
950 }
951 return (((pfd.dwFlags & REQUIRED_FLAGS) == REQUIRED_FLAGS) && suppColor) ?
952 JNI_TRUE : JNI_FALSE;
953 CATCH_BAD_ALLOC_RET(FALSE);
954 }
955
956 /*
957 * Class: sun_awt_Win32GraphicsDevice
958 * Method: getDefaultPixIDImpl
959 * Signature: (I)I
960 */
961
Java_sun_awt_Win32GraphicsDevice_getDefaultPixIDImpl(JNIEnv * env,jobject theThis,jint screen)962 JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getDefaultPixIDImpl
963 (JNIEnv* env, jobject theThis, jint screen) {
964 TRY;
965 int pixFmtID = 0;
966 HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen);
967
968 PIXELFORMATDESCRIPTOR pfd = {
969 sizeof(PIXELFORMATDESCRIPTOR),
970 1, //version
971 REQUIRED_FLAGS, //flags
972 0, //iPixelType
973 0, //cColorBits
974 0,0,0,0,0,0,0,0, //cRedBits, cRedShift, green, blue, alpha
975 0,0,0,0,0, //cAccumBits, cAccumRedBits, green, blue, alpha
976 0,0,0,0,0,0,0,0 //etc.
977 };
978
979 //If 8-bit mode, must use Indexed mode
980 if (8 == ::GetDeviceCaps(hDC, BITSPIXEL)) {
981 pfd.iPixelType = PFD_TYPE_COLORINDEX;
982 }
983
984 pixFmtID = ::ChoosePixelFormat(hDC, &pfd);
985 if (pixFmtID == 0) {
986 //Return 0 if GDI call fails.
987 if (hDC != NULL) {
988 VERIFY(::DeleteDC(hDC));
989 hDC = NULL;
990 }
991 return pixFmtID;
992 }
993
994 if (JNI_FALSE == Java_sun_awt_Win32GraphicsDevice_isPixFmtSupported(
995 env, theThis, pixFmtID, screen)) {
996 /* Can't find a suitable pixel format ID. Fall back on 0. */
997 pixFmtID = 0;
998 }
999
1000 VERIFY(::DeleteDC(hDC));
1001 hDC = NULL;
1002 return (jint)pixFmtID;
1003 CATCH_BAD_ALLOC_RET(0);
1004 }
1005
1006 /*
1007 * Class: sun_awt_Win32GraphicsDevice
1008 * Method: enterFullScreenExclusive
1009 * Signature: (Ljava/awt/peer/WindowPeer;)V
1010 */
1011
1012 JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsDevice_enterFullScreenExclusive(JNIEnv * env,jobject graphicsDevice,jint screen,jobject windowPeer)1013 Java_sun_awt_Win32GraphicsDevice_enterFullScreenExclusive(
1014 JNIEnv* env, jobject graphicsDevice,
1015 jint screen, jobject windowPeer) {
1016
1017 TRY;
1018
1019 PDATA pData;
1020 JNI_CHECK_PEER_RETURN(windowPeer);
1021
1022 AwtWindow *window = (AwtWindow *)pData; // safe cast since we are called
1023 // with the WWindowPeer object
1024 HWND hWnd = window->GetHWnd();
1025
1026 if (!::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0,
1027 SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOSIZE))
1028 {
1029 J2dTraceLn1(J2D_TRACE_ERROR,
1030 "Error %d setting topmost attribute to fs window",
1031 ::GetLastError());
1032 }
1033
1034 CATCH_BAD_ALLOC;
1035 }
1036
1037 /*
1038 * Class: sun_awt_Win32GraphicsDevice
1039 * Method: exitFullScreenExclusive
1040 * Signature: (Ljava/awt/peer/WindowPeer;)V
1041 */
1042
1043 JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsDevice_exitFullScreenExclusive(JNIEnv * env,jobject graphicsDevice,jint screen,jobject windowPeer)1044 Java_sun_awt_Win32GraphicsDevice_exitFullScreenExclusive(
1045 JNIEnv* env, jobject graphicsDevice,
1046 jint screen, jobject windowPeer) {
1047
1048 TRY;
1049
1050 PDATA pData;
1051 JNI_CHECK_PEER_RETURN(windowPeer);
1052
1053 AwtWindow *window = (AwtWindow *)pData; // safe cast since we are called
1054 // with the WWindowPeer object
1055 HWND hWnd = window->GetHWnd();
1056
1057 jobject target = env->GetObjectField(windowPeer, AwtObject::targetID);
1058 jboolean alwaysOnTop = JNU_GetFieldByName(env, NULL, target, "alwaysOnTop", "Z").z;
1059 env->DeleteLocalRef(target);
1060
1061 if (!::SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
1062 SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOSIZE))
1063 {
1064 J2dTraceLn1(J2D_TRACE_ERROR,
1065 "Error %d unsetting topmost attribute to fs window",
1066 ::GetLastError());
1067 }
1068
1069 // We should restore alwaysOnTop state as it's anyway dropped here
1070 Java_sun_awt_windows_WWindowPeer_setAlwaysOnTopNative(env, windowPeer, alwaysOnTop);
1071
1072 CATCH_BAD_ALLOC;
1073 }
1074
CreateDisplayMode(JNIEnv * env,jint width,jint height,jint bitDepth,jint refreshRate)1075 jobject CreateDisplayMode(JNIEnv* env, jint width, jint height,
1076 jint bitDepth, jint refreshRate) {
1077
1078 TRY;
1079
1080 jclass displayModeClass = env->FindClass("java/awt/DisplayMode");
1081 if (JNU_IsNull(env, displayModeClass)) {
1082 env->ExceptionClear();
1083 JNU_ThrowInternalError(env, "Could not get display mode class");
1084 return NULL;
1085 }
1086
1087 jmethodID cid = env->GetMethodID(displayModeClass, "<init>", "(IIII)V");
1088 if (cid == NULL) {
1089 env->ExceptionClear();
1090 JNU_ThrowInternalError(env, "Could not get display mode constructor");
1091 return NULL;
1092 }
1093
1094 jobject displayMode = env->NewObject(displayModeClass, cid, width,
1095 height, bitDepth, refreshRate);
1096 return displayMode;
1097
1098 CATCH_BAD_ALLOC_RET(NULL);
1099 }
1100
1101 /**
1102 * A utility function which retrieves a DISPLAY_DEVICE information
1103 * given a screen number.
1104 *
1105 * If the function was able to find an attached device for the given screen
1106 * number, the lpDisplayDevice will be initialized with the data and
1107 * the function will return TRUE, otherwise it returns FALSE and contents
1108 * of the structure pointed to by lpDisplayDevice is undefined.
1109 */
1110 static BOOL
GetAttachedDisplayDevice(int screen,DISPLAY_DEVICE * lpDisplayDevice)1111 GetAttachedDisplayDevice(int screen, DISPLAY_DEVICE *lpDisplayDevice)
1112 {
1113 DWORD dwDeviceNum = 0;
1114 lpDisplayDevice->cb = sizeof(DISPLAY_DEVICE);
1115 while (EnumDisplayDevices(NULL, dwDeviceNum, lpDisplayDevice, 0) &&
1116 dwDeviceNum < 20) // avoid infinite loop with buggy drivers
1117 {
1118 if (lpDisplayDevice->StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) {
1119 Devices::InstanceAccess devices;
1120 MONITORINFOEX *pMonInfo =
1121 (LPMONITORINFOEX)devices->GetDevice(screen)->GetMonitorInfo();
1122 // make sure the device names match
1123 if (wcscmp(pMonInfo->szDevice, lpDisplayDevice->DeviceName) == 0) {
1124 return TRUE;
1125 }
1126 }
1127 dwDeviceNum++;
1128 }
1129 return FALSE;
1130 }
1131
1132 /*
1133 * Class: sun_awt_Win32GraphicsDevice
1134 * Method: getCurrentDisplayMode
1135 * Signature: (IZ)Ljava/awt/DisplayMode;
1136 */
1137 JNIEXPORT jobject JNICALL
Java_sun_awt_Win32GraphicsDevice_getCurrentDisplayMode(JNIEnv * env,jobject graphicsDevice,jint screen)1138 Java_sun_awt_Win32GraphicsDevice_getCurrentDisplayMode
1139 (JNIEnv* env, jobject graphicsDevice, jint screen)
1140 {
1141 TRY;
1142
1143 DEVMODE dm;
1144 LPTSTR pName = NULL;
1145
1146 dm.dmSize = sizeof(dm);
1147 dm.dmDriverExtra = 0;
1148
1149 DISPLAY_DEVICE displayDevice;
1150 if (GetAttachedDisplayDevice(screen, &displayDevice)) {
1151 pName = displayDevice.DeviceName;
1152 }
1153 if (!EnumDisplaySettings(pName, ENUM_CURRENT_SETTINGS, &dm))
1154 {
1155 return NULL;
1156 }
1157
1158 return CreateDisplayMode(env, dm.dmPelsWidth,
1159 dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency);
1160
1161 CATCH_BAD_ALLOC_RET(NULL);
1162 }
1163
1164 /*
1165 * Class: sun_awt_Win32GraphicsDevice
1166 * Method: configDisplayMode
1167 * Signature: (IIIIZ)V
1168 */
1169 JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsDevice_configDisplayMode(JNIEnv * env,jobject graphicsDevice,jint screen,jobject windowPeer,jint width,jint height,jint bitDepth,jint refreshRate)1170 Java_sun_awt_Win32GraphicsDevice_configDisplayMode
1171 (JNIEnv* env, jobject graphicsDevice, jint screen, jobject windowPeer,
1172 jint width, jint height, jint bitDepth, jint refreshRate)
1173 {
1174 TRY;
1175
1176 DEVMODE dm;
1177
1178 dm.dmSize = sizeof(dm);
1179 dm.dmDriverExtra = 0;
1180 dm.dmPelsWidth = width;
1181 dm.dmPelsHeight = height;
1182 dm.dmBitsPerPel = bitDepth;
1183 dm.dmDisplayFrequency = refreshRate;
1184 dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT |
1185 DM_BITSPERPEL | DM_DISPLAYFREQUENCY;
1186
1187 // ChangeDisplaySettings works only on the primary screen.
1188 // ChangeDisplaySettingsEx is not available on NT,
1189 // so it'd be nice not to break it if we can help it.
1190 if (screen == AwtWin32GraphicsDevice::GetDefaultDeviceIndex()) {
1191 if (::ChangeDisplaySettings(&dm, CDS_FULLSCREEN) !=
1192 DISP_CHANGE_SUCCESSFUL)
1193 {
1194 JNU_ThrowInternalError(env,
1195 "Could not set display mode");
1196 }
1197 return;
1198 }
1199
1200 DISPLAY_DEVICE displayDevice;
1201 if (!GetAttachedDisplayDevice(screen, &displayDevice) ||
1202 (::ChangeDisplaySettingsEx(displayDevice.DeviceName, &dm, NULL, CDS_FULLSCREEN, NULL) !=
1203 DISP_CHANGE_SUCCESSFUL))
1204 {
1205 JNU_ThrowInternalError(env,
1206 "Could not set display mode");
1207 }
1208
1209 CATCH_BAD_ALLOC;
1210 }
1211
1212 class EnumDisplayModeParam {
1213 public:
EnumDisplayModeParam(JNIEnv * e,jobject a)1214 EnumDisplayModeParam(JNIEnv* e, jobject a) : env(e), arrayList(a) {}
1215 JNIEnv* env;
1216 jobject arrayList;
1217 };
1218
addDisplayMode(JNIEnv * env,jobject arrayList,jint width,jint height,jint bitDepth,jint refreshRate)1219 void addDisplayMode(JNIEnv* env, jobject arrayList, jint width,
1220 jint height, jint bitDepth, jint refreshRate) {
1221
1222 TRY;
1223
1224 jobject displayMode = CreateDisplayMode(env, width, height,
1225 bitDepth, refreshRate);
1226 if (!JNU_IsNull(env, displayMode)) {
1227 jclass arrayListClass = env->GetObjectClass(arrayList);
1228 if (JNU_IsNull(env, arrayListClass)) {
1229 JNU_ThrowInternalError(env,
1230 "Could not get class java.util.ArrayList");
1231 return;
1232 }
1233 jmethodID mid = env->GetMethodID(arrayListClass, "add",
1234 "(Ljava/lang/Object;)Z");
1235 if (mid == NULL) {
1236 env->ExceptionClear();
1237 JNU_ThrowInternalError(env,
1238 "Could not get method java.util.ArrayList.add()");
1239 return;
1240 }
1241 env->CallObjectMethod(arrayList, mid, displayMode);
1242 env->DeleteLocalRef(displayMode);
1243 }
1244
1245 CATCH_BAD_ALLOC;
1246 }
1247
1248 /*
1249 * Class: sun_awt_Win32GraphicsDevice
1250 * Method: enumDisplayModes
1251 * Signature: (Ljava/util/ArrayList;Z)V
1252 */
Java_sun_awt_Win32GraphicsDevice_enumDisplayModes(JNIEnv * env,jobject graphicsDevice,jint screen,jobject arrayList)1253 JNIEXPORT void JNICALL Java_sun_awt_Win32GraphicsDevice_enumDisplayModes
1254 (JNIEnv* env, jobject graphicsDevice, jint screen, jobject arrayList)
1255 {
1256
1257 TRY;
1258
1259 DEVMODE dm;
1260 LPTSTR pName = NULL;
1261 DISPLAY_DEVICE displayDevice;
1262
1263
1264 if (GetAttachedDisplayDevice(screen, &displayDevice)) {
1265 pName = displayDevice.DeviceName;
1266 }
1267
1268 dm.dmSize = sizeof(dm);
1269 dm.dmDriverExtra = 0;
1270
1271 BOOL bContinue = TRUE;
1272 for (int i = 0; bContinue; i++) {
1273 bContinue = EnumDisplaySettings(pName, i, &dm);
1274 if (dm.dmBitsPerPel >= 8) {
1275 addDisplayMode(env, arrayList, dm.dmPelsWidth, dm.dmPelsHeight,
1276 dm.dmBitsPerPel, dm.dmDisplayFrequency);
1277 JNU_CHECK_EXCEPTION(env);
1278 }
1279 }
1280
1281 CATCH_BAD_ALLOC;
1282 }
1283
1284 /*
1285 * Class: sun_awt_Win32GraphicsDevice
1286 * Method: makeColorModel
1287 * Signature: ()Ljava/awt/image/ColorModel
1288 */
1289
1290 JNIEXPORT jobject JNICALL
Java_sun_awt_Win32GraphicsDevice_makeColorModel(JNIEnv * env,jobject thisPtr,jint screen,jboolean dynamic)1291 Java_sun_awt_Win32GraphicsDevice_makeColorModel
1292 (JNIEnv *env, jobject thisPtr, jint screen, jboolean dynamic)
1293 {
1294 Devices::InstanceAccess devices;
1295 return devices->GetDevice(screen)->GetColorModel(env, dynamic);
1296 }
1297
1298 /*
1299 * Class: sun_awt_Win32GraphicsDevice
1300 * Method: initDevice
1301 * Signature: (I)V
1302 */
1303 JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsDevice_initDevice(JNIEnv * env,jobject thisPtr,jint screen)1304 Java_sun_awt_Win32GraphicsDevice_initDevice
1305 (JNIEnv *env, jobject thisPtr, jint screen)
1306 {
1307 Devices::InstanceAccess devices;
1308 devices->GetDevice(screen)->SetJavaDevice(env, thisPtr);
1309 }
1310