/*
 * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */



/**
 * This class holds the information for a particular graphics device.
 * Since a display change can cause the creation of new devices
 * at any time, there is no referencing of the devices array allowed.
 * Instead, anyone wishing to reference a device in the array (e.g.,
 * the current default device or a device for a given hWnd) must
 * call one of the static methods of this class with the index of
 * the device in question.  Those methods will then lock the devices
 * array and forward the request to the current device at that
 * array index.
 */

#include <awt.h>
#include <sun_awt_Win32GraphicsDevice.h>
#include "awt_Canvas.h"
#include "awt_Win32GraphicsDevice.h"
#include "awt_Window.h"
#include "java_awt_Transparency.h"
#include "java_awt_color_ColorSpace.h"
#include "sun_awt_Win32GraphicsDevice.h"
#include "java_awt_image_DataBuffer.h"
#include "dither.h"
#include "img_util_md.h"
#include "Devices.h"
#include <d2d1.h>
#pragma comment(lib, "d2d1")
#include "systemScale.h"

uns_ordered_dither_array img_oda_alpha;

jclass      AwtWin32GraphicsDevice::indexCMClass;
jclass      AwtWin32GraphicsDevice::wToolkitClass;
jfieldID    AwtWin32GraphicsDevice::dynamicColorModelID;
jfieldID    AwtWin32GraphicsDevice::indexCMrgbID;
jfieldID    AwtWin32GraphicsDevice::indexCMcacheID;
jmethodID   AwtWin32GraphicsDevice::paletteChangedMID;
BOOL        AwtWin32GraphicsDevice::primaryPalettized;
int         AwtWin32GraphicsDevice::primaryIndex = 0;


/**
 * Construct this device.  Store the screen (index into the devices
 * array of this object), the array (used in static references via
 * particular device indices), the monitor/pMonitorInfo (which other
 * classes will inquire of this device), the bits per pixel of this
 * device, and information on whether the primary device is palettized.
 */
AwtWin32GraphicsDevice::AwtWin32GraphicsDevice(int screen,
                                               HMONITOR mhnd, Devices *arr)
{
    this->screen  = screen;
    this->devicesArray = arr;
    this->scaleX = 1;
    this->scaleY = 1;
    javaDevice = NULL;
    colorData = new ImgColorData;
    colorData->grayscale = GS_NOTGRAY;
    palette = NULL;
    cData = NULL;
    gpBitmapInfo = NULL;
    monitor = mhnd;
    pMonitorInfo = new MONITORINFOEX;
    pMonitorInfo->cbSize = sizeof(MONITORINFOEX);
    ::GetMonitorInfo(monitor, pMonitorInfo);

    // Set primary device info: other devices will need to know
    // whether the primary is palettized during the initialization
    // process
    HDC hDC = this->GetDC();
    colorData->bitsperpixel = ::GetDeviceCaps(hDC, BITSPIXEL);
    this->ReleaseDC(hDC);
    if (MONITORINFOF_PRIMARY & pMonitorInfo->dwFlags) {
        primaryIndex = screen;
        if (colorData->bitsperpixel > 8) {
            primaryPalettized = FALSE;
        } else {
            primaryPalettized = TRUE;
        }
    }
}

AwtWin32GraphicsDevice::~AwtWin32GraphicsDevice()
{
    delete colorData;
    if (gpBitmapInfo) {
        free(gpBitmapInfo);
    }
    if (palette) {
        delete palette;
    }
    if (pMonitorInfo) {
        delete pMonitorInfo;
    }
    if (javaDevice) {
        JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
        env->DeleteWeakGlobalRef(javaDevice);
    }
    if (cData != NULL) {
        freeICMColorData(cData);
    }
}

HDC AwtWin32GraphicsDevice::MakeDCFromMonitor(HMONITOR hmMonitor) {
    HDC retCode = NULL;
    if (NULL != hmMonitor) {
        MONITORINFOEX mieInfo;

        memset((void*)(&mieInfo), 0, sizeof(MONITORINFOEX));
        mieInfo.cbSize = sizeof(MONITORINFOEX);

        if (TRUE == ::GetMonitorInfo(hmMonitor, (LPMONITORINFOEX)(&mieInfo))) {
            HDC hDC = CreateDC(mieInfo.szDevice, NULL, NULL, NULL);
            if (NULL != hDC) {
                retCode = hDC;
            }
        }
    }
    return retCode;
}

HDC AwtWin32GraphicsDevice::GetDC()
{
    return MakeDCFromMonitor(monitor);
}

void AwtWin32GraphicsDevice::ReleaseDC(HDC hDC)
{
    if (hDC != NULL) {
        ::DeleteDC(hDC);
    }
}

/**
 * Init this device.  This creates the bitmap structure
 * used to hold the device color data and initializes any
 * appropriate palette structures.
 */
void AwtWin32GraphicsDevice::Initialize()
{
    unsigned int ri, gi, bi;
    if (colorData->bitsperpixel < 8) {
        // REMIND: how to handle?
    }

    // Create a BitmapInfo object for color data
    if (!gpBitmapInfo) {
        try {
            gpBitmapInfo = (BITMAPINFO *)
                safe_Malloc(sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
        } catch (std::bad_alloc&) {
            throw;
        }
        gpBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    }
    gpBitmapInfo->bmiHeader.biBitCount = 0;
    HDC hBMDC = this->GetDC();
    HBITMAP hBM = ::CreateCompatibleBitmap(hBMDC, 1, 1);
    VERIFY(::GetDIBits(hBMDC, hBM, 0, 1, NULL, gpBitmapInfo, DIB_RGB_COLORS));

    if (colorData->bitsperpixel > 8) {
        if (MONITORINFOF_PRIMARY & pMonitorInfo->dwFlags) {
            primaryPalettized = FALSE;
        }
        if (colorData->bitsperpixel != 24) { // 15, 16, or 32 bpp
            int foo;
            gpBitmapInfo->bmiHeader.biCompression = BI_BITFIELDS;
            if (::GetDIBits(hBMDC, hBM, 0, 1, &foo, gpBitmapInfo,
                            DIB_RGB_COLORS) == 0)
            {
                // Bug 4684966: If GetDIBits returns an error, we could
                // get stuck in an infinite loop setting the colorData
                // fields.  Hardcode bitColors to reasonable values instead.
                // These values are picked according to standard masks
                // for these bit depths on win9x, according to MSDN docs.
                switch (colorData->bitsperpixel) {
                case 15:
                    ((int *)gpBitmapInfo->bmiColors)[0] = 0x7c00;
                    ((int *)gpBitmapInfo->bmiColors)[1] = 0x03e0;
                    ((int *)gpBitmapInfo->bmiColors)[2] = 0x001f;
                    break;
                case 16:
                    ((int *)gpBitmapInfo->bmiColors)[0] = 0xf800;
                    ((int *)gpBitmapInfo->bmiColors)[1] = 0x07e0;
                    ((int *)gpBitmapInfo->bmiColors)[2] = 0x001f;
                    break;
                case 32:
                default:
                    ((int *)gpBitmapInfo->bmiColors)[0] = 0xff0000;
                    ((int *)gpBitmapInfo->bmiColors)[1] = 0x00ff00;
                    ((int *)gpBitmapInfo->bmiColors)[2] = 0x0000ff;
                    break;
                }
            }
            ri = ((unsigned int *)gpBitmapInfo->bmiColors)[0];
            colorData->rOff = 0;
            while ((ri & 1) == 0) {
                colorData->rOff++;
                ri >>= 1;
            }
            colorData->rScale = 0;
            while (ri < 0x80) {
                colorData->rScale++;
                ri <<= 1;
            }
            gi = ((unsigned int *)gpBitmapInfo->bmiColors)[1];
            colorData->gOff = 0;
            while ((gi & 1) == 0) {
                colorData->gOff++;
                gi >>= 1;
            }
            colorData->gScale = 0;
            while (gi < 0x80) {
                colorData->gScale++;
                gi <<= 1;
            }
            bi = ((unsigned int *)gpBitmapInfo->bmiColors)[2];
            colorData->bOff = 0;
            while ((bi & 1) == 0) {
                colorData->bOff++;
                bi >>= 1;
            }
            colorData->bScale = 0;
            while (bi < 0x80) {
                colorData->bScale++;
                bi <<= 1;
            }
            if (   (0 == colorData->bOff)
                && (5 == colorData->gOff)
                && (10 == colorData->rOff)
                && (3 == colorData->bScale)
                && (3 == colorData->gScale)
                && (3 == colorData->rScale)) {
                colorData->bitsperpixel = 15;
                gpBitmapInfo->bmiHeader.biCompression = BI_RGB;
            }
        } else {    // 24 bpp
            gpBitmapInfo->bmiHeader.biBitCount = 24;
            gpBitmapInfo->bmiHeader.biCompression = BI_RGB;

            // Fill these values in as a convenience for the screen
            // ColorModel construction code below (see getColorModel())
            ((int *)gpBitmapInfo->bmiColors)[0] = 0x0000ff;
            ((int *)gpBitmapInfo->bmiColors)[1] = 0x00ff00;
            ((int *)gpBitmapInfo->bmiColors)[2] = 0xff0000;
        }
    } else {
        if (MONITORINFOF_PRIMARY & pMonitorInfo->dwFlags) {
            primaryPalettized = TRUE;
        }
        gpBitmapInfo->bmiHeader.biBitCount = 8;
        gpBitmapInfo->bmiHeader.biCompression = BI_RGB;
        gpBitmapInfo->bmiHeader.biClrUsed = 256;
        gpBitmapInfo->bmiHeader.biClrImportant = 256;

        // The initialization of cData is done prior to
        // calling palette->Update() since we need it
        // for calculating inverseGrayLut
        if (cData == NULL) {
            cData = (ColorData*)safe_Calloc(1, sizeof(ColorData));
            memset(cData, 0, sizeof(ColorData));
            initDitherTables(cData);
        }

        if (!palette) {
            palette = new AwtPalette(this);
        } else {
            palette->Update();
        }
        palette->UpdateLogical();
    }
    VERIFY(::DeleteObject(hBM));
    VERIFY(::DeleteDC(hBMDC));
}

/**
 * Creates a new colorModel given the current device configuration.
 * The dynamic flag determines whether we use the system palette
 * (dynamic == TRUE) or our custom palette in creating a new
 * IndexedColorModel.
 */
jobject AwtWin32GraphicsDevice::GetColorModel(JNIEnv *env, jboolean dynamic)
{
    jobject awt_colormodel;
    int i;
    if (colorData->bitsperpixel == 24) {
        awt_colormodel =
            JNU_NewObjectByName(env, "sun/awt/Win32ColorModel24", "()V");
    } else if (colorData->bitsperpixel > 8) {
        int *masks = (int *)gpBitmapInfo->bmiColors;
        int numbits = 0;
        unsigned int bits = (masks[0] | masks[1] | masks[2]);
        while (bits) {
            numbits++;
            bits >>= 1;
        }
        awt_colormodel = JNU_NewObjectByName(env,
                                             "java/awt/image/DirectColorModel",
                                             "(IIII)V", numbits,
                                             masks[0], masks[1], masks[2]);
    } else if (colorData->grayscale == GS_STATICGRAY) {
        jclass clazz;
        jclass clazz1;
        jmethodID mid;
        jobject cspace = NULL;
        jint bits[1];
        jintArray bitsArray;

        clazz1 = env->FindClass("java/awt/color/ColorSpace");
        CHECK_NULL_RETURN(clazz1, NULL);
        mid = env->GetStaticMethodID(clazz1, "getInstance",
              "(I)Ljava/awt/color/ColorSpace;");
        CHECK_NULL_RETURN(mid, NULL);
        cspace = env->CallStaticObjectMethod(clazz1, mid,
            java_awt_color_ColorSpace_CS_GRAY);
        CHECK_NULL_RETURN(cspace, NULL);

        bits[0] = 8;
        bitsArray = env->NewIntArray(1);
        if (bitsArray == 0) {
            return NULL;
        } else {
            env->SetIntArrayRegion(bitsArray, 0, 1, bits);
        }

        clazz = env->FindClass("java/awt/image/ComponentColorModel");
        CHECK_NULL_RETURN(clazz, NULL);
        mid = env->GetMethodID(clazz,"<init>",
            "(Ljava/awt/color/ColorSpace;[IZZII)V");
        CHECK_NULL_RETURN(mid, NULL);

        awt_colormodel = env->NewObject(clazz, mid,
                                        cspace,
                                        bitsArray,
                                        JNI_FALSE,
                                        JNI_FALSE,
                                        java_awt_Transparency_OPAQUE,
                                        java_awt_image_DataBuffer_TYPE_BYTE);
    } else {
        jintArray hRGB = env->NewIntArray(256);
        unsigned int *rgb = NULL, *rgbP = NULL;
        jboolean allvalid = JNI_TRUE;
        jbyte vbits[256/8];
        jobject validBits = NULL;

        CHECK_NULL_RETURN(hRGB, NULL);
        /* Create the LUT from the color map */
        try {
            rgb = (unsigned int *) env->GetPrimitiveArrayCritical(hRGB, 0);
            CHECK_NULL_RETURN(rgb, NULL);
            rgbP = rgb;
            if (!palette) {
                palette = new AwtPalette(this);
                palette->UpdateLogical();
            }
            if (colorData->grayscale == GS_INDEXGRAY) {
                /* For IndexColorModel, pretend first 10 colors and last
                   10 colors are transparent black.  This makes
                   ICM.allgrayopaque true.
                */
                unsigned int *logicalEntries = palette->GetLogicalEntries();

                for (i=0; i < 10; i++) {
                    rgbP[i] = 0x00000000;
                    rgbP[i+246] = 0x00000000;
                }
                memcpy(&rgbP[10], &logicalEntries[10], 236 * sizeof(RGBQUAD));
                // We need to specify which entries in the colormap are
                // valid so that the transparent black entries we have
                // created do not affect the Transparency setting of the
                // IndexColorModel.  The vbits array is used to construct
                // a BigInteger such that the most significant bit of vbits[0]
                // indicates the validity of the last color (#256) and the
                // least significant bit of vbits[256/8] indicates the
                // validity of the first color (#0).  We need to fill vbits
                // with all 1's and then turn off the first and last 10 bits.
                memset(vbits, 0xff, sizeof(vbits));
                vbits[0] = 0;
                vbits[1] = (jbyte) (0xff >> 2);
                vbits[sizeof(vbits)-2] = (jbyte) (0xff << 2);
                vbits[sizeof(vbits)-1] = 0;
                allvalid = JNI_FALSE;
            } else {
                if (AwtPalette::UseCustomPalette() && !dynamic) {
                    // If we plan to use our custom palette (i.e., we are
                    // not running inside another app and we are not creating
                    // a dynamic colorModel object), then setup ICM with
                    // custom palette entries
                    unsigned int *logicalEntries = palette->GetLogicalEntries();
                    memcpy(rgbP, logicalEntries, 256 * sizeof(int));
                } else {
                    // Else, use current system palette entries.
                    // REMIND: This may not give the result we want if
                    // we are running inside another app and that
                    // parent app is running in the background when we
                    // reach here.  We could at least cache an "ideal" set of
                    // system palette entries from the first time we are
                    // running in the foreground and then future ICM's will
                    // use that set instead.
                    unsigned int *systemEntries = palette->GetSystemEntries();
                    memcpy(rgbP, systemEntries, 256 * sizeof(int));
                }
            }
        } catch (...) {
            env->ReleasePrimitiveArrayCritical(hRGB, rgb, 0);
            throw;
        }

        env->ReleasePrimitiveArrayCritical(hRGB, rgb, 0);

        // Construct a new color model
        if (!allvalid) {
            jbyteArray bArray = env->NewByteArray(sizeof(vbits));
            CHECK_NULL_RETURN(bArray, NULL);
            env->SetByteArrayRegion(bArray, 0, sizeof(vbits), vbits);
            validBits = JNU_NewObjectByName(env,
                                            "java/math/BigInteger",
                                            "([B)V", bArray);
            JNU_CHECK_EXCEPTION_RETURN(env, NULL);
        }
        awt_colormodel =
            JNU_NewObjectByName(env,
                                "java/awt/image/IndexColorModel",
                                "(II[IIILjava/math/BigInteger;)V",
                                8, 256,
                                hRGB, 0,
                                java_awt_image_DataBuffer_TYPE_BYTE,
                                validBits);
    }
    return awt_colormodel;
}

/**
 * Called from AwtPalette code when it is determined what grayscale
 * value (if any) the current logical palette has
 */
void AwtWin32GraphicsDevice::SetGrayness(int grayValue)
{
    colorData->grayscale = grayValue;
}


/**
 * Update our dynamic IndexedColorModel.  This happens after
 * a change to the system palette.  Any surfaces stored in vram
 * (Win32OffScreenSurfaceData and GDIWindowSurfaceData objects)
 * refer to this colorModel and use its lookup table and inverse
 * lookup to calculate correct index values for rgb colors.  So
 * the colorModel must always reflect the current state of the
 * system palette.
 */
void AwtWin32GraphicsDevice::UpdateDynamicColorModel()
{
    if (!javaDevice) {
        // javaDevice may not be set yet.  If not, return.  In
        // this situation, we probably don't need an update anyway
        // since the colorModel will be created with the correct
        // info when the java side is initialized.
        return;
    }
    JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
    jobject colorModel = env->GetObjectField(javaDevice,
        dynamicColorModelID);
    if (!colorModel) {
        return;
    }
    if (env->IsInstanceOf(colorModel, indexCMClass)) {
        // If colorModel not of type ICM then we're not in 8-bit mode and
        // don't need to update it
        jboolean isCopy;
        unsigned int *newEntries = palette->GetSystemEntries();
        jintArray rgbArray = (jintArray)env->GetObjectField(colorModel,
            AwtWin32GraphicsDevice::indexCMrgbID);
        jintArray cacheArray = (jintArray)env->GetObjectField(colorModel,
            AwtWin32GraphicsDevice::indexCMcacheID);
        if (!rgbArray || !cacheArray) {
            JNU_ThrowInternalError(env, "rgb or lookupcache array of IndexColorModel null");
            return;
        }
        int rgbLength = env->GetArrayLength(rgbArray);
        int cacheLength = env->GetArrayLength(cacheArray);
        jint *cmEntries = (jint *)env->GetPrimitiveArrayCritical(rgbArray, &isCopy);
        if (!cmEntries) {
            env->ExceptionClear();
            JNU_ThrowInternalError(env, "Problem retrieving rgb critical array");
            return;
        }
        jint *cache = (jint *)env->GetPrimitiveArrayCritical(cacheArray, &isCopy);
        if (!cache) {
            env->ExceptionClear();
            env->ReleasePrimitiveArrayCritical(rgbArray, cmEntries, JNI_ABORT);
            JNU_ThrowInternalError(env, "Problem retrieving cache critical array");
            return;
        }
        // Set the new rgb values
    int i;
    for (i = 0; i < rgbLength; ++i) {
            cmEntries[i] = newEntries[i];
        }
        // clear out the old cache
        for (i = 0; i < cacheLength; ++i) {
            cache[i] = 0;
        }
        env->ReleasePrimitiveArrayCritical(cacheArray, cache, 0);
        env->ReleasePrimitiveArrayCritical(rgbArray, cmEntries, 0);

        // Call WToolkit::paletteChanged() method; this will invalidate
        // the offscreen surfaces dependent on this dynamic colorModel
        // to ensure that they get redrawn with the correct color indices
        env->CallStaticVoidMethod(AwtWin32GraphicsDevice::wToolkitClass,
            paletteChangedMID);
    }
}

unsigned int *AwtWin32GraphicsDevice::GetSystemPaletteEntries()
{
    // REMIND: What to do if palette NULL?  Need to throw
    // some kind of exception?
    return palette->GetSystemEntries();
}

unsigned char *AwtWin32GraphicsDevice::GetSystemInverseLUT()
{
    // REMIND: What to do if palette NULL?  Need to throw
    // some kind of exception?
    return palette->GetSystemInverseLUT();
}


BOOL AwtWin32GraphicsDevice::UpdateSystemPalette()
{
    if (colorData->bitsperpixel > 8) {
        return FALSE;
    } else {
        return palette->Update();
    }
}

HPALETTE AwtWin32GraphicsDevice::SelectPalette(HDC hDC)
{
    if (palette) {
        return palette->Select(hDC);
    } else {
        return NULL;
    }
}

void AwtWin32GraphicsDevice::RealizePalette(HDC hDC)
{
    if (palette) {
        palette->Realize(hDC);
    }
}

/**
 * Deterine which device the HWND exists on and return the
 * appropriate index into the devices array.
 */
int AwtWin32GraphicsDevice::DeviceIndexForWindow(HWND hWnd)
{
    HMONITOR mon = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
    int screen = AwtWin32GraphicsDevice::GetScreenFromHMONITOR(mon);
    return screen;
}

/**
 * Get the HPALETTE associated with this device
 */
HPALETTE AwtWin32GraphicsDevice::GetPalette()
{
    if (palette) {
        return palette->GetPalette();
    } else {
        return NULL;
    }
}

/**
 * Object referring to this device is releasing that reference.
 * This allows the array holding all devices to be released (once
 * all references to the array have gone away).
 */
void AwtWin32GraphicsDevice::Release()
{
    devicesArray->Release();
}

/**
 * Links this native object with its java Win32GraphicsDevice.
 * Need this link because the colorModel of the java device
 * may be updated from native code.
 */
void AwtWin32GraphicsDevice::SetJavaDevice(JNIEnv *env, jobject objPtr)
{
    javaDevice = env->NewWeakGlobalRef(objPtr);
}

/**
 * Sets horizontal and vertical scale factors
 */
void AwtWin32GraphicsDevice::SetScale(float sx, float sy)
{
    scaleX = sx;
    scaleY = sy;
}

int AwtWin32GraphicsDevice::ScaleUpX(int x)
{
    return (int)ceil(x * scaleX);
}

int AwtWin32GraphicsDevice::ScaleUpY(int y)
{
    return (int)ceil(y * scaleY);
}

int AwtWin32GraphicsDevice::ScaleDownX(int x)
{
    return (int)ceil(x / scaleX);
}

int AwtWin32GraphicsDevice::ScaleDownY(int y)
{
    return (int)ceil(y / scaleY);
}

void AwtWin32GraphicsDevice::InitDesktopScales()
{
    float dpiX = -1.0f;
    float dpiY = -1.0f;
    GetScreenDpi(GetMonitor(), &dpiX, &dpiY);
    if (dpiX > 0 && dpiY > 0) {
        SetScale(dpiX / 96, dpiY / 96);
    }
}

float AwtWin32GraphicsDevice::GetScaleX()
{
    return scaleX;
}

float AwtWin32GraphicsDevice::GetScaleY()
{
    return scaleY;
}

/**
 * Disables offscreen acceleration for this device.  This
 * sets a flag in the java object that is used to determine
 * whether offscreen surfaces can be created on the device.
 */
void AwtWin32GraphicsDevice::DisableOffscreenAcceleration()
{
    // REMIND: noop for now
}

/**
 * Invalidates the GraphicsDevice object associated with this
 * device by disabling offscreen acceleration and calling
 * invalidate(defIndex) on the java object.
 */
void AwtWin32GraphicsDevice::Invalidate(JNIEnv *env)
{
    int defIndex = AwtWin32GraphicsDevice::GetDefaultDeviceIndex();
    DisableOffscreenAcceleration();
    jobject javaDevice = GetJavaDevice();
    if (!JNU_IsNull(env, javaDevice)) {
        JNU_CallMethodByName(env, NULL, javaDevice, "invalidate",
                             "(I)V", defIndex);
    }
}

/**
 * Static deviceIndex-based methods
 *
 * The following methods take a deviceIndex for the list of devices
 * and perform the appropriate action on that device.  This way of
 * dereferencing the list of devices allows us to do appropriate
 * locks around the list to ensure multi-threaded safety.
 */


jobject AwtWin32GraphicsDevice::GetColorModel(JNIEnv *env, jboolean dynamic,
                                              int deviceIndex)
{
    Devices::InstanceAccess devices;
    return devices->GetDevice(deviceIndex)->GetColorModel(env, dynamic);
}

LPMONITORINFO AwtWin32GraphicsDevice::GetMonitorInfo(int deviceIndex)
{
    Devices::InstanceAccess devices;
    return devices->GetDevice(deviceIndex)->GetMonitorInfo();
}

/**
 * This function updates the data in the MONITORINFOEX structure pointed to by
 * pMonitorInfo for all monitors on the system.  Added for 4654713.
 */
void AwtWin32GraphicsDevice::ResetAllMonitorInfo()
{
    //IE in some circumstances generates WM_SETTINGCHANGE message on appearance
    //and thus triggers this method
    //but we may not have the devices list initialized yet.
    if (!Devices::GetInstance()){
        return;
    }
    Devices::InstanceAccess devices;
    int devicesNum = devices->GetNumDevices();
    for (int deviceIndex = 0; deviceIndex < devicesNum; deviceIndex++) {
        HMONITOR monitor = devices->GetDevice(deviceIndex)->GetMonitor();
        ::GetMonitorInfo(monitor,
                         devices->GetDevice(deviceIndex)->pMonitorInfo);
    }
}

void AwtWin32GraphicsDevice::DisableOffscreenAccelerationForDevice(
    HMONITOR hMonitor)
{
    Devices::InstanceAccess devices;
    if (hMonitor == NULL) {
        devices->GetDevice(0)->DisableOffscreenAcceleration();
    } else {
        int devicesNum = devices->GetNumDevices();
        for (int i = 0; i < devicesNum; ++i) {
            if (devices->GetDevice(i)->GetMonitor() == hMonitor) {
                devices->GetDevice(i)->DisableOffscreenAcceleration();
            }
        }
    }
}

HMONITOR AwtWin32GraphicsDevice::GetMonitor(int deviceIndex)
{
    Devices::InstanceAccess devices;
    return devices->GetDevice(deviceIndex)->GetMonitor();
}

HPALETTE AwtWin32GraphicsDevice::GetPalette(int deviceIndex)
{
    Devices::InstanceAccess devices;
    return devices->GetDevice(deviceIndex)->GetPalette();
}

void AwtWin32GraphicsDevice::UpdateDynamicColorModel(int deviceIndex)
{
    Devices::InstanceAccess devices;
    devices->GetDevice(deviceIndex)->UpdateDynamicColorModel();
}

BOOL AwtWin32GraphicsDevice::UpdateSystemPalette(int deviceIndex)
{
    Devices::InstanceAccess devices;
    return devices->GetDevice(deviceIndex)->UpdateSystemPalette();
}

HPALETTE AwtWin32GraphicsDevice::SelectPalette(HDC hDC, int deviceIndex)
{
    Devices::InstanceAccess devices;
    return devices->GetDevice(deviceIndex)->SelectPalette(hDC);
}

void AwtWin32GraphicsDevice::RealizePalette(HDC hDC, int deviceIndex)
{
    Devices::InstanceAccess devices;
    devices->GetDevice(deviceIndex)->RealizePalette(hDC);
}

ColorData *AwtWin32GraphicsDevice::GetColorData(int deviceIndex)
{
    Devices::InstanceAccess devices;
    return devices->GetDevice(deviceIndex)->GetColorData();
}

/**
 * Return the grayscale value for the indicated device.
 */
int AwtWin32GraphicsDevice::GetGrayness(int deviceIndex)
{
    Devices::InstanceAccess devices;
    return devices->GetDevice(deviceIndex)->GetGrayness();
}

HDC AwtWin32GraphicsDevice::GetDCFromScreen(int screen) {
    J2dTraceLn1(J2D_TRACE_INFO,
                "AwtWin32GraphicsDevice::GetDCFromScreen screen=%d", screen);
    Devices::InstanceAccess devices;
    AwtWin32GraphicsDevice *dev = devices->GetDevice(screen);
    return MakeDCFromMonitor(dev->GetMonitor());
}

/** Compare elements of MONITORINFOEX structures for the given HMONITORs.
 * If equal, return TRUE
 */
BOOL AwtWin32GraphicsDevice::AreSameMonitors(HMONITOR mon1, HMONITOR mon2) {
    J2dTraceLn2(J2D_TRACE_INFO,
                "AwtWin32GraphicsDevice::AreSameMonitors mhnd1=%x mhnd2=%x",
                mon1, mon2);
    DASSERT(mon1 != NULL);
    DASSERT(mon2 != NULL);

    MONITORINFOEX mi1;
    MONITORINFOEX mi2;

    memset((void*)(&mi1), 0, sizeof(MONITORINFOEX));
    mi1.cbSize = sizeof(MONITORINFOEX);
    memset((void*)(&mi2), 0, sizeof(MONITORINFOEX));
    mi2.cbSize = sizeof(MONITORINFOEX);

    if (::GetMonitorInfo(mon1, &mi1) != 0 &&
        ::GetMonitorInfo(mon2, &mi2) != 0 )
    {
        if (::EqualRect(&mi1.rcMonitor, &mi2.rcMonitor) &&
            ::EqualRect(&mi1.rcWork, &mi2.rcWork) &&
            (mi1.dwFlags  == mi1.dwFlags))
        {

            J2dTraceLn(J2D_TRACE_VERBOSE, "  the monitors are the same");
            return TRUE;
        }
    }
    J2dTraceLn(J2D_TRACE_VERBOSE, "  the monitors are not the same");
    return FALSE;
}

int AwtWin32GraphicsDevice::GetScreenFromHMONITOR(HMONITOR mon) {
    J2dTraceLn1(J2D_TRACE_INFO,
                "AwtWin32GraphicsDevice::GetScreenFromHMONITOR mhnd=%x", mon);

    DASSERT(mon != NULL);
    Devices::InstanceAccess devices;

    for (int i = 0; i < devices->GetNumDevices(); i++) {
        HMONITOR mhnd = devices->GetDevice(i)->GetMonitor();
        if (AreSameMonitors(mon, mhnd)) {
            J2dTraceLn1(J2D_TRACE_VERBOSE, "  Found device: %d", i);
            return i;
        }
    }

    J2dTraceLn1(J2D_TRACE_WARNING,
                "AwtWin32GraphicsDevice::GetScreenFromHMONITOR(): "\
                "couldn't find screen for HMONITOR %x, returning default", mon);
    return AwtWin32GraphicsDevice::GetDefaultDeviceIndex();
}


/**
 * End of static deviceIndex-based methods
 */


    const DWORD REQUIRED_FLAGS = (   //Flags which must be set in
     PFD_SUPPORT_GDI |               //in the PixelFormatDescriptor.
     PFD_DRAW_TO_WINDOW);            //Used to choose the default config
                                     //and to check formats in
                                     //isPixFmtSupported()
extern "C" {

JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsDevice_initIDs(JNIEnv *env, jclass cls)
{
    TRY;

    /* class ids */
    jclass iCMClass = env->FindClass("java/awt/image/IndexColorModel");
    CHECK_NULL(iCMClass);
    AwtWin32GraphicsDevice::indexCMClass = (jclass) env->NewGlobalRef(iCMClass);
    env->DeleteLocalRef(iCMClass);
    DASSERT(AwtWin32GraphicsDevice::indexCMClass);
    CHECK_NULL(AwtWin32GraphicsDevice::indexCMClass);

    jclass wTClass = env->FindClass("sun/awt/windows/WToolkit");
    CHECK_NULL(wTClass);
    AwtWin32GraphicsDevice::wToolkitClass = (jclass)env->NewGlobalRef(wTClass);
    env->DeleteLocalRef(wTClass);
    DASSERT(AwtWin32GraphicsDevice::wToolkitClass);
    CHECK_NULL(AwtWin32GraphicsDevice::wToolkitClass);

    /* field ids */
    AwtWin32GraphicsDevice::dynamicColorModelID = env->GetFieldID(cls,
        "dynamicColorModel", "Ljava/awt/image/ColorModel;");
    DASSERT(AwtWin32GraphicsDevice::dynamicColorModelID);
    CHECK_NULL(AwtWin32GraphicsDevice::dynamicColorModelID);

    AwtWin32GraphicsDevice::indexCMrgbID =
        env->GetFieldID(AwtWin32GraphicsDevice::indexCMClass, "rgb", "[I");
    DASSERT(AwtWin32GraphicsDevice::indexCMrgbID);
    CHECK_NULL(AwtWin32GraphicsDevice::indexCMrgbID);

    AwtWin32GraphicsDevice::indexCMcacheID =
        env->GetFieldID(AwtWin32GraphicsDevice::indexCMClass,
        "lookupcache", "[I");
    DASSERT(AwtWin32GraphicsDevice::indexCMcacheID);
    CHECK_NULL(AwtWin32GraphicsDevice::indexCMcacheID);

    /* method ids */
    AwtWin32GraphicsDevice::paletteChangedMID = env->GetStaticMethodID(
        AwtWin32GraphicsDevice::wToolkitClass, "paletteChanged", "()V");
    DASSERT(AwtWin32GraphicsDevice::paletteChangedMID);
    CHECK_NULL(AwtWin32GraphicsDevice::paletteChangedMID);

    // Only want to call this once per session
    make_uns_ordered_dither_array(img_oda_alpha, 256);

    // workaround JDK-6477756, ignore return value to keep dll in memory
    JDK_LoadSystemLibrary("opengl32.dll");

    CATCH_BAD_ALLOC;
}

} /* extern "C" */


/*
 * Class:     sun_awt_Win32GraphicsDevice
 * Method:    getMaxConfigsImpl
 * Signature: ()I
 */

JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getMaxConfigsImpl
    (JNIEnv* jniEnv, jobject theThis, jint screen) {
        TRY;
    HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen);

    PIXELFORMATDESCRIPTOR pfd;
    int max = ::DescribePixelFormat(hDC, 1, sizeof(PIXELFORMATDESCRIPTOR),
        &pfd);
    if (hDC != NULL) {
        VERIFY(::DeleteDC(hDC));
        hDC = NULL;
    }
    //If ::DescribePixelFormat() fails, max = 0
    //In this case, we return 1 config with visual number 0
    if (max == 0) {
        max = 1;
    }
    return (jint)max;
        CATCH_BAD_ALLOC_RET(0);
}

/*
 * Class:     sun_awt_Win32GraphicsDevice
 * Method:    isPixFmtSupported
 * Signature: (I)Z
 */

JNIEXPORT jboolean JNICALL Java_sun_awt_Win32GraphicsDevice_isPixFmtSupported
    (JNIEnv* env, jobject theThis, jint pixFmtID, jint screen) {
        TRY;
    jboolean suppColor = JNI_TRUE;
    HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen);

    if (pixFmtID == 0) {
        return true;
    }

    PIXELFORMATDESCRIPTOR pfd;
    int max = ::DescribePixelFormat(hDC, (int)pixFmtID,
        sizeof(PIXELFORMATDESCRIPTOR), &pfd);
    DASSERT(max);

    //Check for supported ColorModel
    if ((pfd.cColorBits < 8) ||
       ((pfd.cColorBits == 8) && (pfd.iPixelType != PFD_TYPE_COLORINDEX))) {
        //Note: this still allows for PixelFormats with > 8 color bits
        //which use COLORINDEX instead of RGB.  This seems to work fine,
        //although issues may crop up involving PFD_NEED_PALETTE, which
        //is not currently taken into account.
        //If changes are made, they should also be reflected in
        //getDefaultPixID.
        suppColor = JNI_FALSE;
    }

    if (hDC != NULL) {
        VERIFY(::DeleteDC(hDC));
        hDC = NULL;
    }
    return (((pfd.dwFlags & REQUIRED_FLAGS) == REQUIRED_FLAGS) && suppColor) ?
     JNI_TRUE : JNI_FALSE;
        CATCH_BAD_ALLOC_RET(FALSE);
}

/*
 * Class:     sun_awt_Win32GraphicsDevice
 * Method:    getDefaultPixIDImpl
 * Signature: (I)I
 */

JNIEXPORT jint JNICALL Java_sun_awt_Win32GraphicsDevice_getDefaultPixIDImpl
    (JNIEnv* env, jobject theThis, jint screen) {
        TRY;
    int pixFmtID = 0;
    HDC hDC = AwtWin32GraphicsDevice::GetDCFromScreen(screen);

    PIXELFORMATDESCRIPTOR pfd = {
        sizeof(PIXELFORMATDESCRIPTOR),
        1,               //version
        REQUIRED_FLAGS,  //flags
        0,               //iPixelType
        0,               //cColorBits
        0,0,0,0,0,0,0,0, //cRedBits, cRedShift, green, blue, alpha
        0,0,0,0,0,       //cAccumBits, cAccumRedBits, green, blue, alpha
        0,0,0,0,0,0,0,0  //etc.
    };

    //If 8-bit mode, must use Indexed mode
    if (8 == ::GetDeviceCaps(hDC, BITSPIXEL)) {
        pfd.iPixelType = PFD_TYPE_COLORINDEX;
    }

    pixFmtID = ::ChoosePixelFormat(hDC, &pfd);
    if (pixFmtID == 0) {
        //Return 0 if GDI call fails.
        if (hDC != NULL) {
            VERIFY(::DeleteDC(hDC));
            hDC = NULL;
        }
        return pixFmtID;
    }

    if (JNI_FALSE == Java_sun_awt_Win32GraphicsDevice_isPixFmtSupported(
     env, theThis, pixFmtID, screen)) {
        /* Can't find a suitable pixel format ID.  Fall back on 0. */
        pixFmtID = 0;
    }

    VERIFY(::DeleteDC(hDC));
    hDC = NULL;
    return (jint)pixFmtID;
        CATCH_BAD_ALLOC_RET(0);
}

/*
 * Class:     sun_awt_Win32GraphicsDevice
 * Method:    enterFullScreenExclusive
 * Signature: (Ljava/awt/peer/WindowPeer;)V
 */

JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsDevice_enterFullScreenExclusive(
        JNIEnv* env, jobject graphicsDevice,
        jint screen, jobject windowPeer) {

    TRY;

    PDATA pData;
    JNI_CHECK_PEER_RETURN(windowPeer);

    AwtWindow *window = (AwtWindow *)pData;  // safe cast since we are called
                                             // with the WWindowPeer object
    HWND hWnd = window->GetHWnd();

    if (!::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0,
                        SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOSIZE))
    {
        J2dTraceLn1(J2D_TRACE_ERROR,
                    "Error %d setting topmost attribute to fs window",
                    ::GetLastError());
    }

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_Win32GraphicsDevice
 * Method:    exitFullScreenExclusive
 * Signature: (Ljava/awt/peer/WindowPeer;)V
 */

JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsDevice_exitFullScreenExclusive(
        JNIEnv* env, jobject graphicsDevice,
        jint screen, jobject windowPeer) {

    TRY;

    PDATA pData;
    JNI_CHECK_PEER_RETURN(windowPeer);

    AwtWindow *window = (AwtWindow *)pData;  // safe cast since we are called
                                             // with the WWindowPeer object
    HWND hWnd = window->GetHWnd();

    jobject target = env->GetObjectField(windowPeer, AwtObject::targetID);
    jboolean alwaysOnTop = JNU_GetFieldByName(env, NULL, target, "alwaysOnTop", "Z").z;
    env->DeleteLocalRef(target);

    if (!::SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
                        SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOSIZE))
    {
        J2dTraceLn1(J2D_TRACE_ERROR,
                    "Error %d unsetting topmost attribute to fs window",
                    ::GetLastError());
    }

    // We should restore alwaysOnTop state as it's anyway dropped here
    Java_sun_awt_windows_WWindowPeer_setAlwaysOnTopNative(env, windowPeer, alwaysOnTop);

    CATCH_BAD_ALLOC;
}

jobject CreateDisplayMode(JNIEnv* env, jint width, jint height,
    jint bitDepth, jint refreshRate) {

    TRY;

    jclass displayModeClass = env->FindClass("java/awt/DisplayMode");
    if (JNU_IsNull(env, displayModeClass)) {
        env->ExceptionClear();
        JNU_ThrowInternalError(env, "Could not get display mode class");
        return NULL;
    }

    jmethodID cid = env->GetMethodID(displayModeClass, "<init>", "(IIII)V");
    if (cid == NULL) {
        env->ExceptionClear();
        JNU_ThrowInternalError(env, "Could not get display mode constructor");
        return NULL;
    }

    jobject displayMode = env->NewObject(displayModeClass, cid, width,
        height, bitDepth, refreshRate);
    return displayMode;

    CATCH_BAD_ALLOC_RET(NULL);
}

/**
 * A utility function which retrieves a DISPLAY_DEVICE information
 * given a screen number.
 *
 * If the function was able to find an attached device for the given screen
 * number, the lpDisplayDevice will be initialized with the data and
 * the function will return TRUE, otherwise it returns FALSE and contents
 * of the structure pointed to by lpDisplayDevice is undefined.
 */
static BOOL
GetAttachedDisplayDevice(int screen, DISPLAY_DEVICE *lpDisplayDevice)
{
    DWORD dwDeviceNum = 0;
    lpDisplayDevice->cb = sizeof(DISPLAY_DEVICE);
    while (EnumDisplayDevices(NULL, dwDeviceNum, lpDisplayDevice, 0) &&
           dwDeviceNum < 20) // avoid infinite loop with buggy drivers
    {
        if (lpDisplayDevice->StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) {
            Devices::InstanceAccess devices;
            MONITORINFOEX *pMonInfo =
                (LPMONITORINFOEX)devices->GetDevice(screen)->GetMonitorInfo();
            // make sure the device names match
            if (wcscmp(pMonInfo->szDevice, lpDisplayDevice->DeviceName) == 0) {
                return TRUE;
            }
        }
        dwDeviceNum++;
    }
    return FALSE;
}

/*
 * Class:     sun_awt_Win32GraphicsDevice
 * Method:    getCurrentDisplayMode
 * Signature: (IZ)Ljava/awt/DisplayMode;
 */
JNIEXPORT jobject JNICALL
Java_sun_awt_Win32GraphicsDevice_getCurrentDisplayMode
    (JNIEnv* env, jobject graphicsDevice, jint screen)
{
    TRY;

    DEVMODE dm;
    LPTSTR pName = NULL;

    dm.dmSize = sizeof(dm);
    dm.dmDriverExtra = 0;

    DISPLAY_DEVICE displayDevice;
    if (GetAttachedDisplayDevice(screen, &displayDevice)) {
        pName = displayDevice.DeviceName;
    }
    if (!EnumDisplaySettings(pName, ENUM_CURRENT_SETTINGS, &dm))
    {
        return NULL;
    }

    return CreateDisplayMode(env, dm.dmPelsWidth,
        dm.dmPelsHeight, dm.dmBitsPerPel, dm.dmDisplayFrequency);

    CATCH_BAD_ALLOC_RET(NULL);
}

/*
 * Class:     sun_awt_Win32GraphicsDevice
 * Method:    configDisplayMode
 * Signature: (IIIIZ)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsDevice_configDisplayMode
    (JNIEnv* env, jobject graphicsDevice, jint screen, jobject windowPeer,
     jint width, jint height, jint bitDepth, jint refreshRate)
{
    TRY;

        DEVMODE dm;

    dm.dmSize = sizeof(dm);
    dm.dmDriverExtra = 0;
    dm.dmPelsWidth = width;
    dm.dmPelsHeight = height;
    dm.dmBitsPerPel = bitDepth;
    dm.dmDisplayFrequency = refreshRate;
    dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT |
        DM_BITSPERPEL | DM_DISPLAYFREQUENCY;

    // ChangeDisplaySettings works only on the primary screen.
    // ChangeDisplaySettingsEx is not available on NT,
    // so it'd be nice not to break it if we can help it.
    if (screen == AwtWin32GraphicsDevice::GetDefaultDeviceIndex()) {
        if (::ChangeDisplaySettings(&dm, CDS_FULLSCREEN) !=
            DISP_CHANGE_SUCCESSFUL)
        {
            JNU_ThrowInternalError(env,
                                   "Could not set display mode");
        }
        return;
    }

    DISPLAY_DEVICE displayDevice;
    if (!GetAttachedDisplayDevice(screen, &displayDevice) ||
        (::ChangeDisplaySettingsEx(displayDevice.DeviceName, &dm, NULL, CDS_FULLSCREEN, NULL) !=
          DISP_CHANGE_SUCCESSFUL))
    {
        JNU_ThrowInternalError(env,
                               "Could not set display mode");
    }

    CATCH_BAD_ALLOC;
}

class EnumDisplayModeParam {
public:
    EnumDisplayModeParam(JNIEnv* e, jobject a) : env(e), arrayList(a) {}
    JNIEnv* env;
    jobject arrayList;
};

void addDisplayMode(JNIEnv* env, jobject arrayList, jint width,
    jint height, jint bitDepth, jint refreshRate) {

    TRY;

    jobject displayMode = CreateDisplayMode(env, width, height,
        bitDepth, refreshRate);
    if (!JNU_IsNull(env, displayMode)) {
        jclass arrayListClass = env->GetObjectClass(arrayList);
        if (JNU_IsNull(env, arrayListClass)) {
            JNU_ThrowInternalError(env,
                "Could not get class java.util.ArrayList");
            return;
        }
        jmethodID mid = env->GetMethodID(arrayListClass, "add",
        "(Ljava/lang/Object;)Z");
        if (mid == NULL) {
            env->ExceptionClear();
            JNU_ThrowInternalError(env,
                "Could not get method java.util.ArrayList.add()");
            return;
        }
        env->CallObjectMethod(arrayList, mid, displayMode);
        env->DeleteLocalRef(displayMode);
    }

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_Win32GraphicsDevice
 * Method:    enumDisplayModes
 * Signature: (Ljava/util/ArrayList;Z)V
 */
JNIEXPORT void JNICALL Java_sun_awt_Win32GraphicsDevice_enumDisplayModes
    (JNIEnv* env, jobject graphicsDevice, jint screen, jobject arrayList)
{

    TRY;

    DEVMODE dm;
    LPTSTR pName = NULL;
    DISPLAY_DEVICE displayDevice;


    if (GetAttachedDisplayDevice(screen, &displayDevice)) {
        pName = displayDevice.DeviceName;
    }

    dm.dmSize = sizeof(dm);
    dm.dmDriverExtra = 0;

    BOOL bContinue = TRUE;
    for (int i = 0; bContinue; i++) {
        bContinue = EnumDisplaySettings(pName, i, &dm);
        if (dm.dmBitsPerPel >= 8) {
            addDisplayMode(env, arrayList, dm.dmPelsWidth, dm.dmPelsHeight,
                           dm.dmBitsPerPel, dm.dmDisplayFrequency);
            JNU_CHECK_EXCEPTION(env);
        }
    }

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_Win32GraphicsDevice
 * Method:    makeColorModel
 * Signature: ()Ljava/awt/image/ColorModel
 */

JNIEXPORT jobject JNICALL
    Java_sun_awt_Win32GraphicsDevice_makeColorModel
    (JNIEnv *env, jobject thisPtr, jint screen, jboolean dynamic)
{
    Devices::InstanceAccess devices;
    return devices->GetDevice(screen)->GetColorModel(env, dynamic);
}

/*
 * Class:     sun_awt_Win32GraphicsDevice
 * Method:    initDevice
 * Signature: (I)V
 */
JNIEXPORT void JNICALL
    Java_sun_awt_Win32GraphicsDevice_initDevice
    (JNIEnv *env, jobject thisPtr, jint screen)
{
    Devices::InstanceAccess devices;
    devices->GetDevice(screen)->SetJavaDevice(env, thisPtr);
}

/*
 * Class:     sun_awt_Win32GraphicsDevice
 * Method:    setNativeScale
 * Signature: (I,F,F)V
 */
JNIEXPORT void JNICALL
    Java_sun_awt_Win32GraphicsDevice_setNativeScale
    (JNIEnv *env, jobject thisPtr, jint screen, jfloat scaleX, jfloat scaleY)
{
    Devices::InstanceAccess devices;
    AwtWin32GraphicsDevice *device = devices->GetDevice(screen);

    if (device != NULL ) {
        device->SetScale(scaleX, scaleY);
    }
}

/*
 * Class:     sun_awt_Win32GraphicsDevice
 * Method:    getNativeScaleX
 * Signature: (I)F
 */
JNIEXPORT jfloat JNICALL
    Java_sun_awt_Win32GraphicsDevice_getNativeScaleX
    (JNIEnv *env, jobject thisPtr, jint screen)
{
    Devices::InstanceAccess devices;
    AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
    return (device == NULL) ? 1 : device->GetScaleX();
}

/*
 * Class:     sun_awt_Win32GraphicsDevice
 * Method:    getNativeScaleY
 * Signature: (I)F
 */
JNIEXPORT jfloat JNICALL
    Java_sun_awt_Win32GraphicsDevice_getNativeScaleY
    (JNIEnv *env, jobject thisPtr, jint screen)
{
    Devices::InstanceAccess devices;
    AwtWin32GraphicsDevice *device = devices->GetDevice(screen);
    return (device == NULL) ? 1 : device->GetScaleY();
}

/*
* Class:     sun_awt_Win32GraphicsDevice
* Method:    initNativeScale
* Signature: (I)V;
*/
JNIEXPORT void JNICALL
Java_sun_awt_Win32GraphicsDevice_initNativeScale
(JNIEnv *env, jobject thisPtr, jint screen)
{
    Devices::InstanceAccess devices;
    AwtWin32GraphicsDevice *device = devices->GetDevice(screen);

    if (device != NULL) {
        device->InitDesktopScales();
    }
}

