/*
 * Copyright (c) 1999, 2015, 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.
 */

#include "sun_java2d_windows_GDIWindowSurfaceData.h"

#include "GDIWindowSurfaceData.h"
#include "GraphicsPrimitiveMgr.h"
#include "Region.h"
#include "Disposer.h"
#include "WindowsFlags.h"
#include "awt_Component.h"
#include "awt_Palette.h"
#include "awt_Win32GraphicsDevice.h"
#include "gdefs.h"
#include "Trace.h"
#include "Devices.h"

#include "jni_util.h"

static LockFunc GDIWinSD_Lock;
static GetRasInfoFunc GDIWinSD_GetRasInfo;
static UnlockFunc GDIWinSD_Unlock;
static DisposeFunc GDIWinSD_Dispose;
static SetupFunc GDIWinSD_Setup;
static GetDCFunc GDIWinSD_GetDC;
static ReleaseDCFunc GDIWinSD_ReleaseDC;
static InvalidateSDFunc GDIWinSD_InvalidateSD;

static HBRUSH   nullbrush;
static HPEN     nullpen;

static jclass xorCompClass;

static jboolean beingShutdown = JNI_FALSE;
static volatile LONG timeStamp = 0;
extern CriticalSection windowMoveLock;

extern "C"
{
GeneralDisposeFunc DisposeThreadGraphicsInfo;
jobject JNI_GetCurrentThread(JNIEnv *env);
int threadInfoIndex = TLS_OUT_OF_INDEXES;

static jclass threadClass = NULL;
static jmethodID currentThreadMethodID = NULL;

void SetupThreadGraphicsInfo(JNIEnv *env, GDIWinSDOps *wsdo) {
    J2dTraceLn(J2D_TRACE_INFO, "SetupThreadGraphicsInfo");

    // REMIND: handle error when creation fails
    ThreadGraphicsInfo *info =
        (ThreadGraphicsInfo*)TlsGetValue(threadInfoIndex);
    if (info == NULL) {
        info = new ThreadGraphicsInfo;
        ZeroMemory(info, sizeof(ThreadGraphicsInfo));
        TlsSetValue(threadInfoIndex, (LPVOID)info);
        J2dTraceLn2(J2D_TRACE_VERBOSE,
                    "  current batch limit for for thread 0x%x is %d",
                     GetCurrentThreadId(), ::GdiGetBatchLimit());
        J2dTraceLn(J2D_TRACE_VERBOSE, "  setting to the limit to 1");
        // Fix for bug 4374079
        ::GdiSetBatchLimit(1);

        Disposer_AddRecord(env, JNI_GetCurrentThread(env),
                           DisposeThreadGraphicsInfo,
                           ptr_to_jlong(info));
    }

    HDC oldhDC = info->hDC;
    // the hDC is NULL for offscreen surfaces - we don't store it
    // in TLS as it must be created new every time.

    if( ((oldhDC == NULL) && wsdo->window != NULL) ||
         (info->wsdo != wsdo) ||
         (info->wsdoTimeStamp != wsdo->timeStamp) )
    {

        // Init graphics state, either because this is our first time
        // using it in this thread or because this thread is now
        // dealing with a different window than it was last time.

        //check extra condition:
        //(info->wsdoTimeStamp != wsdo->timeStamp).
        //Checking memory addresses (info->wsdo != wsdo) will not detect
        //that wsdo points to a newly allocated structure in case
        //that structure just got allocated at a "recycled" memory location
        //which previously was pointed by info->wsdo
        //see bug# 6859086

        // Release cached DC. We use deferred DC releasing mechanism because
        // the DC is associated with cached wsdo and component peer,
        // which may've been disposed by this time, and we have
        // no means of checking against it.
        if (oldhDC != NULL) {
            MoveDCToPassiveList(oldhDC, info->hWnd);
            info->hDC = NULL;
            info->hWnd = NULL;
        }

        if (wsdo->window != NULL){
            HDC hDC;
            // This is a window surface
            // First, init the HDC object
            AwtComponent *comp = GDIWindowSurfaceData_GetComp(env, wsdo);
            if (comp == NULL) {
                return;
            }
            hDC = comp->GetDCFromComponent();
            if (hDC != NULL) {
                ::SelectObject(hDC, nullbrush);
                ::SelectObject(hDC, nullpen);
                ::SelectClipRgn(hDC, (HRGN) NULL);
                ::SetROP2(hDC, R2_COPYPEN);
                wsdo->device->SelectPalette(hDC);
                // Note that on NT4 we don't need to do a realize here: the
                // palette-sharing takes care of color issues for us.  But
                // on win98 if we don't realize a DC's palette, that
                // palette does not appear to have correct access to the
                // logical->system mapping.
                wsdo->device->RealizePalette(hDC);

                // Second, init the rest of the graphics state
                ::GetClientRect(wsdo->window, &info->bounds);
                // Make window-relative from client-relative
                ::OffsetRect(&info->bounds, wsdo->insets.left, wsdo->insets.top);
                //Likewise, translate GDI calls from client-relative to window-relative
                ::OffsetViewportOrgEx(hDC, -wsdo->insets.left, -wsdo->insets.top, NULL);
            }

            // Finally, set these new values in the info for this thread
            info->hDC = hDC;
            info->hWnd = wsdo->window;
        }

        // cached brush and pen are not associated with any DC, and can be
        // reused, but have to set type to 0 to indicate that no pen/brush
        // were set to the new hdc
        info->type = 0;

        if (info->clip != NULL) {
            env->DeleteWeakGlobalRef(info->clip);
        }
        info->clip = NULL;

        if (info->comp != NULL) {
            env->DeleteWeakGlobalRef(info->comp);
        }
        info->comp = NULL;

        info->xorcolor = 0;
        info->patrop = PATCOPY;

        //store the address and time stamp of newly allocated GDIWinSDOps structure
        info->wsdo = wsdo;
        info->wsdoTimeStamp = wsdo->timeStamp;
    }
}

/**
 * Releases native data stored in Thread local storage.
 * Called by the Disposer when the associated thread dies.
 */
void DisposeThreadGraphicsInfo(JNIEnv *env, jlong tgi) {
    J2dTraceLn(J2D_TRACE_INFO, "DisposeThreadGraphicsInfo");
    ThreadGraphicsInfo *info = (ThreadGraphicsInfo*)jlong_to_ptr(tgi);
    if (info != NULL) {
        if (info->hDC != NULL) {
            // move the DC from the active dcs list to
            // the passive dc list to be released later
            MoveDCToPassiveList(info->hDC, info->hWnd);
        }

        if (info->clip != NULL) {
            env->DeleteWeakGlobalRef(info->clip);
        }
        if (info->comp != NULL) {
            env->DeleteWeakGlobalRef(info->comp);
        }

        if (info->brush != NULL) {
            info->brush->Release();
        }
        if (info->pen != NULL) {
            info->pen->Release();
        }

        delete info;
    }
}

/**
 * Returns current Thread object.
 */
jobject
JNI_GetCurrentThread(JNIEnv *env) {
    return env->CallStaticObjectMethod(threadClass, currentThreadMethodID);
} /* JNI_GetCurrentThread() */

/**
 * Return the data associated with this thread.
 * NOTE: This function assumes that the SetupThreadGraphicsInfo()
 * function has already been called for this situation (thread,
 * window, etc.), so we can assume that the thread info contains
 * a valid hDC.  This should usually be the case since GDIWinSD_Setup
 * is called as part of the GetOps() process.
 */
ThreadGraphicsInfo *GetThreadGraphicsInfo(JNIEnv *env,
                                          GDIWinSDOps *wsdo) {
    return (ThreadGraphicsInfo*)TlsGetValue(threadInfoIndex);
}

__inline HDC GetThreadDC(JNIEnv *env, GDIWinSDOps *wsdo) {
    ThreadGraphicsInfo *info =
        (ThreadGraphicsInfo *)GetThreadGraphicsInfo(env, wsdo);
    if (!info) {
        return (HDC) NULL;
    }
    return info->hDC;
}

} // extern "C"

/**
 * This source file contains support code for loops using the
 * SurfaceData interface to talk to a Win32 drawable from native
 * code.
 */

static BOOL GDIWinSD_CheckMonitorArea(GDIWinSDOps *wsdo,
                                     SurfaceDataBounds *bounds,
                                     HDC hDC)
{
    HWND hW = wsdo->window;
    BOOL retCode = TRUE;

    J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_CheckMonitorArea");
    int numScreens;
    {
        Devices::InstanceAccess devices;
        numScreens = devices->GetNumDevices();
    }
    if( numScreens > 1 ) {

        LPMONITORINFO miInfo;
        RECT rSect ={0,0,0,0};
        RECT rView ={bounds->x1, bounds->y1, bounds->x2, bounds->y2};
        retCode = FALSE;

        miInfo = wsdo->device->GetMonitorInfo();

        POINT ptOrig = {0, 0};
        ::ClientToScreen(hW, &ptOrig);
        ::OffsetRect(&rView,
            (ptOrig.x), (ptOrig.y));

        ::IntersectRect(&rSect,&rView,&(miInfo->rcMonitor));

        if( FALSE == ::IsRectEmpty(&rSect) ) {
            if( TRUE == ::EqualRect(&rSect,&rView) ) {
                retCode = TRUE;
            }
        }
    }
    return retCode;
}

extern "C" {

void
initThreadInfoIndex()
{
    if (threadInfoIndex == TLS_OUT_OF_INDEXES) {
        threadInfoIndex = TlsAlloc();
    }
}


/**
 * Utility function to make sure that native and java-level
 * surface depths are matched.  They can be mismatched when display-depths
 * change, either between the creation of the Java surfaceData structure
 * and the native ddraw surface, or later when a surface is automatically
 * adjusted to be the new display depth (even if it was created in a different
 * depth to begin with)
 */
BOOL SurfaceDepthsCompatible(int javaDepth, int nativeDepth)
{
    if (nativeDepth != javaDepth) {
        switch (nativeDepth) {
        case 0: // Error condition: something is wrong with the surface
        case 8:
        case 24:
            // Java and native surface depths should match exactly for
            // these cases
            return FALSE;
            break;
        case 16:
            // Java surfaceData should be 15 or 16 bits
            if (javaDepth < 15 || javaDepth > 16) {
                return FALSE;
            }
            break;
        case 32:
            // Could have this native depth for either 24- or 32-bit
            // Java surfaceData
            if (javaDepth != 24 && javaDepth != 32) {
                return FALSE;
            }
            break;
        default:
            // should not get here, but if we do something is odd, so
            // just register a failure
            return FALSE;
        }
    }
    return TRUE;
}


/*
 * Class:     sun_java2d_windows_GDIWindowSurfaceData
 * Method:    initIDs
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIWindowSurfaceData_initIDs(JNIEnv *env, jclass wsd,
                                                 jclass XORComp)
{
    jclass tc;
    J2dTraceLn(J2D_TRACE_INFO, "GDIWindowSurfaceData_initIDs");
    nullbrush = (HBRUSH) ::GetStockObject(NULL_BRUSH);
    nullpen = (HPEN) ::GetStockObject(NULL_PEN);

    initThreadInfoIndex();

    xorCompClass = (jclass)env->NewGlobalRef(XORComp);
    if (env->ExceptionCheck()) {
        return;
    }

    tc = env->FindClass("java/lang/Thread");
    DASSERT(tc != NULL);
    CHECK_NULL(tc);

    threadClass = (jclass)env->NewGlobalRef(tc);
    DASSERT(threadClass != NULL);
    CHECK_NULL(threadClass);

    currentThreadMethodID =
        env->GetStaticMethodID(threadClass,
                               "currentThread",  "()Ljava/lang/Thread;");
    DASSERT(currentThreadMethodID != NULL);
}

#undef ExceptionOccurred

/*
 * Class:     sun_java2d_windows_GDIWindowSurfaceData
 * Method:    initOps
 * Signature: (Ljava/lang/Object;IIIIII)V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIWindowSurfaceData_initOps(JNIEnv *env, jobject wsd,
                                                 jobject peer, jint depth,
                                                 jint redMask, jint greenMask,
                                                 jint blueMask, jint screen)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIWindowSurfaceData_initOps");
    GDIWinSDOps *wsdo = (GDIWinSDOps *)SurfaceData_InitOps(env, wsd, sizeof(GDIWinSDOps));
    if (wsdo == NULL) {
        JNU_ThrowOutOfMemoryError(env, "Initialization of SurfaceData failed.");
        return;
    }
    wsdo->timeStamp = InterlockedIncrement(&timeStamp); //creation time stamp
    wsdo->sdOps.Lock = GDIWinSD_Lock;
    wsdo->sdOps.GetRasInfo = GDIWinSD_GetRasInfo;
    wsdo->sdOps.Unlock = GDIWinSD_Unlock;
    wsdo->sdOps.Dispose = GDIWinSD_Dispose;
    wsdo->sdOps.Setup = GDIWinSD_Setup;
    wsdo->GetDC = GDIWinSD_GetDC;
    wsdo->ReleaseDC = GDIWinSD_ReleaseDC;
    wsdo->InvalidateSD = GDIWinSD_InvalidateSD;
    wsdo->invalid = JNI_FALSE;
    wsdo->lockType = WIN32SD_LOCK_UNLOCKED;
    wsdo->peer = env->NewWeakGlobalRef(peer);
    if (env->ExceptionOccurred()) {
        return;
    }
    wsdo->depth = depth;
    wsdo->pixelMasks[0] = redMask;
    wsdo->pixelMasks[1] = greenMask;
    wsdo->pixelMasks[2] = blueMask;
    // Init the DIB pixelStride and pixel masks according to
    // the pixel depth. In the 8-bit case, there are no
    // masks as a palette DIB is used instead. Likewise
    // in the 24-bit case, Windows doesn't expect the masks
    switch (depth) {
        case 8:
            wsdo->pixelStride = 1;
            break;
        case 15: //555
            wsdo->pixelStride = 2;
            break;
        case 16: //565
            wsdo->pixelStride = 2;
            break;
        case 24:
            wsdo->pixelStride = 3;
            break;
        case 32: //888
            wsdo->pixelStride = 4;
            break;
    }
    // GDIWindowSurfaceData_GetWindow will throw NullPointerException
    // if wsdo->window is NULL
    wsdo->window = GDIWindowSurfaceData_GetWindow(env, wsdo);
    J2dTraceLn2(J2D_TRACE_VERBOSE, "  wsdo=0x%x wsdo->window=0x%x",
                wsdo, wsdo->window);

    {
        Devices::InstanceAccess devices;
        wsdo->device = devices->GetDeviceReference(screen, FALSE);
    }
    if (wsdo->device == NULL ||
        !SurfaceDepthsCompatible(depth, wsdo->device->GetBitDepth()))
    {
        if (wsdo->device != NULL) {
            J2dTraceLn2(J2D_TRACE_WARNING,
                        "GDIWindowSurfaceData_initOps: Surface depth mismatch: "\
                        "wsdo->depth=%d device depth=%d. Surface invalidated.",
                        wsdo->depth, wsdo->device->GetBitDepth());
        } else {
            J2dTraceLn1(J2D_TRACE_WARNING,
                        "GDIWindowSurfaceData_initOps: Incorrect "\
                        "screen number (screen=%d). Surface invalidated.",
                        screen);
        }

        wsdo->invalid = JNI_TRUE;
    }
    wsdo->surfaceLock = new CriticalSection();
    wsdo->bitmap = NULL;
    wsdo->bmdc = NULL;
    wsdo->bmCopyToScreen = FALSE;
}

JNIEXPORT GDIWinSDOps * JNICALL
GDIWindowSurfaceData_GetOps(JNIEnv *env, jobject sData)
{
    SurfaceDataOps *ops = SurfaceData_GetOps(env, sData);
    // REMIND: There was originally a condition check here to make sure
    // that we were really dealing with a GDIWindowSurfaceData object, but
    // it did not allow for the existence of other win32-accelerated
    // surface data objects (e.g., Win32OffScreenSurfaceData).  I've
    // removed the check for now, but we should replace it with another,
    // more general check against Win32-related surfaces.
    return (GDIWinSDOps *) ops;
}

JNIEXPORT GDIWinSDOps * JNICALL
GDIWindowSurfaceData_GetOpsNoSetup(JNIEnv *env, jobject sData)
{
    // use the 'no setup' version of GetOps
    SurfaceDataOps *ops = SurfaceData_GetOpsNoSetup(env, sData);
    return (GDIWinSDOps *) ops;
}

JNIEXPORT AwtComponent * JNICALL
GDIWindowSurfaceData_GetComp(JNIEnv *env, GDIWinSDOps *wsdo)
{
    PDATA pData;
    jobject localObj = env->NewLocalRef(wsdo->peer);

    if (localObj == NULL || (pData = JNI_GET_PDATA(localObj)) == NULL) {
        J2dTraceLn1(J2D_TRACE_WARNING,
                    "GDIWindowSurfaceData_GetComp: Null pData? pData=0x%x",
                    pData);
        if (beingShutdown == JNI_TRUE) {
            wsdo->invalid = JNI_TRUE;
            return (AwtComponent *) NULL;
        }
        try {
            AwtToolkit::GetInstance().VerifyActive();
        } catch (awt_toolkit_shutdown&) {
            beingShutdown = JNI_TRUE;
            wsdo->invalid = JNI_TRUE;
            return (AwtComponent *) NULL;
        }
        if (wsdo->invalid == JNI_TRUE) {
            SurfaceData_ThrowInvalidPipeException(env,
                "GDIWindowSurfaceData: bounds changed");
        } else {
            JNU_ThrowNullPointerException(env, "component argument pData");
        }
        return (AwtComponent *) NULL;
    }
    return static_cast<AwtComponent*>(pData);
}

JNIEXPORT HWND JNICALL
GDIWindowSurfaceData_GetWindow(JNIEnv *env, GDIWinSDOps *wsdo)
{
    HWND window = wsdo->window;

    if (window == (HWND) NULL) {
        AwtComponent *comp = GDIWindowSurfaceData_GetComp(env, wsdo);
        if (comp == NULL) {
            J2dTraceLn(J2D_TRACE_WARNING,
                   "GDIWindowSurfaceData_GetWindow: null component");
            return (HWND) NULL;
        }
        comp->GetInsets(&wsdo->insets);
        window = comp->GetHWnd();
        if (::IsWindow(window) == FALSE) {
            J2dRlsTraceLn(J2D_TRACE_ERROR,
                          "GDIWindowSurfaceData_GetWindow: disposed component");
            JNU_ThrowNullPointerException(env, "disposed component");
            return (HWND) NULL;
        }
        wsdo->window = window;
    }

    return window;
}

} /* extern "C" */

static jboolean GDIWinSD_SimpleClip(JNIEnv *env, GDIWinSDOps *wsdo,
                                   SurfaceDataBounds *bounds,
                                   HDC hDC)
{
    RECT rClip;

    J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_SimpleClip");
    if (hDC == NULL) {
        return JNI_FALSE;
    }

    int nComplexity = ::GetClipBox(hDC, &rClip);

    switch (nComplexity) {
    case COMPLEXREGION:
        {
            J2dTraceLn(J2D_TRACE_VERBOSE,
                       "  complex clipping region");
            // if complex user/system clip, more detailed testing required
            // check to see if the view itself has a complex clip.
            // ::GetClipBox is only API which returns overlapped window status
            // so we set the rView as our clip, and then see if resulting
            // clip is complex.
            // Only other way to figure this out would be to walk the
            // overlapping windows (no API to get the actual visible clip
            // list).  Then we'd still have to merge that info with the
            // clip region for the dc (if it exists).
            // REMIND: we can cache the CreateRectRgnIndirect result,
            // and only override with ::SetRectRgn

            // First, create a region handle (need existing HRGN for
            // the following call).
            HRGN rgnSave = ::CreateRectRgn(0, 0, 0, 0);
            int  clipStatus = ::GetClipRgn(hDC, rgnSave);
            if (-1 == clipStatus) {
                J2dTraceLn(J2D_TRACE_WARNING,
                           "GDIWinSD_SimpleClip: failed due to clip status");
                ::DeleteObject(rgnSave);
                return JNI_FALSE;
            }
            HRGN rgnBounds = ::CreateRectRgn(
                bounds->x1 - wsdo->insets.left,
                bounds->y1 - wsdo->insets.top,
                bounds->x2 - wsdo->insets.left,
                bounds->y2 - wsdo->insets.top);
            ::SelectClipRgn(hDC, rgnBounds);
            nComplexity = ::GetClipBox(hDC, &rClip);
            ::SelectClipRgn(hDC, clipStatus? rgnSave: NULL);
            ::DeleteObject(rgnSave);
            ::DeleteObject(rgnBounds);

            // Now, test the new clip box.  If it's still not a
            // SIMPLE region, then our bounds must intersect part of
            // the clipping article
            if (SIMPLEREGION != nComplexity) {
                J2dTraceLn(J2D_TRACE_WARNING,
                           "GDIWinSD_SimpleClip: failed due to complexity");
                return JNI_FALSE;
            }
        }
        // NOTE: No break here - we want to fall through into the
        // SIMPLE case, adjust our bounds by the new rClip rect
        // and make sure that our locking bounds are not empty.
    case SIMPLEREGION:
        J2dTraceLn(J2D_TRACE_VERBOSE, "  simple clipping region");
        // Constrain the bounds to the given clip box
        if (bounds->x1 < rClip.left) {
            bounds->x1 = rClip.left;
        }
        if (bounds->y1 < rClip.top) {
            bounds->y1 = rClip.top;
        }
        if (bounds->x2 > rClip.right) {
            bounds->x2 = rClip.right;
        }
        if (bounds->y2 > rClip.bottom) {
            bounds->y2 = rClip.bottom;
        }
        // If the bounds are 0 or negative, then the bounds have
        // been obscured by the clip box, so return FALSE
        if ((bounds->x2 <= bounds->x1) ||
            (bounds->y2 <= bounds->y1)) {
            // REMIND: We should probably do something different here
            // instead of simply returning FALSE.  Since the bounds are
            // empty we won't end up drawing anything, so why spend the
            // effort of returning false and having GDI do a LOCK_BY_DIB?
            // Perhaps we need a new lock code that will indicate that we
            // shouldn't bother drawing?
            J2dTraceLn(J2D_TRACE_WARNING,
                       "GDIWinSD_SimpleClip: failed due to empty bounds");
            return JNI_FALSE;
        }
        break;
    case NULLREGION:
    case ERROR:
    default:
        J2dTraceLn1(J2D_TRACE_ERROR,
                   "GDIWinSD_SimpleClip: failed due to incorrect complexity=%d",
                    nComplexity);
        return JNI_FALSE;
    }

    return JNI_TRUE;
}

static jint GDIWinSD_Lock(JNIEnv *env,
                         SurfaceDataOps *ops,
                         SurfaceDataRasInfo *pRasInfo,
                         jint lockflags)
{
    GDIWinSDOps *wsdo = (GDIWinSDOps *) ops;
    int ret = SD_SUCCESS;
    HDC hDC;
    J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_Lock");

    /* This surfaceLock replaces an earlier implementation which used a
    monitor associated with the peer.  That implementation was prone
    to deadlock problems, so it was replaced by a lock that does not
    have dependencies outside of this thread or object.
    However, this lock doesn't necessarily do all that we want.
    For example, a user may issue a call which results in a DIB lock
    and another call which results in a DDraw Blt.  We can't guarantee
    what order these operations happen in (they are driver and
    video-card dependent), so locking around the issue of either of
    those calls won't necessarily guarantee a particular result.
    The real solution might be to move away from mixing our
    rendering API's.  That is, if we only used DDraw, then we could
    guarantee that all rendering operations would happen in a given
    order.  Similarly for GDI.  But by mixing them, we leave our
    code at the mercy of driver bugs.*/
    wsdo->surfaceLock->Enter();
    if (wsdo->invalid == JNI_TRUE) {
        J2dTraceLn(J2D_TRACE_WARNING, "GDIWinSD_Lock: surface is invalid");
        wsdo->surfaceLock->Leave();
        if (beingShutdown != JNI_TRUE) {
            SurfaceData_ThrowInvalidPipeException(env,
                "GDIWindowSurfaceData: bounds changed");
        }
        return SD_FAILURE;
    }
    if (wsdo->lockType != WIN32SD_LOCK_UNLOCKED) {
        wsdo->surfaceLock->Leave();
        if (!safe_ExceptionOccurred(env)) {
            JNU_ThrowInternalError(env, "Win32 LockRasData cannot nest locks");
        }
        return SD_FAILURE;
    }

    hDC = wsdo->GetDC(env, wsdo, 0, NULL, NULL, NULL, 0);
    if (hDC == NULL) {
        wsdo->surfaceLock->Leave();
        if (beingShutdown != JNI_TRUE) {
            JNU_ThrowNullPointerException(env, "HDC for component");
        }
        return SD_FAILURE;
    }

    if (lockflags & SD_LOCK_RD_WR) {
        // Do an initial clip to the client region of the window
        RECT crect;
        ::GetClientRect(wsdo->window, &crect);

        // Translate to window coords
        crect.left += wsdo->insets.left;
        crect.top += wsdo->insets.top;
        crect.right += wsdo->insets.left;
        crect.bottom += wsdo->insets.top;

        SurfaceDataBounds *bounds = &pRasInfo->bounds;

        if (bounds->x1 < crect.left) {
            bounds->x1 = crect.left;
        }
        if (bounds->y1 < crect.top) {
            bounds->y1 = crect.top;
        }
        if (bounds->x2 > crect.right) {
            bounds->x2 = crect.right;
        }
        if (bounds->y2 > crect.bottom) {
            bounds->y2 = crect.bottom;
        }

        if (bounds->x2 > bounds->x1 && bounds->y2 > bounds->y1) {
            wsdo->lockType = WIN32SD_LOCK_BY_DIB;
            if (lockflags & SD_LOCK_FASTEST) {
                ret = SD_SLOWLOCK;
            }
            J2dTraceLn(J2D_TRACE_VERBOSE, " locked by DIB");
        } else {
            wsdo->ReleaseDC(env, wsdo, hDC);
            wsdo->lockType = WIN32SD_LOCK_UNLOCKED;
            wsdo->surfaceLock->Leave();
            ret = SD_FAILURE;
            J2dTraceLn(J2D_TRACE_ERROR,
                       "GDIWinSD_Lock: error locking by DIB");
        }
    } else {
        J2dTraceLn(J2D_TRACE_VERBOSE, "GDIWinSD_Lock: surface wasn't locked");
        /* They didn't lock for anything - we won't give them anything */
        wsdo->ReleaseDC(env, wsdo, hDC);
        wsdo->lockType = WIN32SD_LOCK_UNLOCKED;
        wsdo->surfaceLock->Leave();
        ret = SD_FAILURE;
    }

    wsdo->lockFlags = lockflags;
    return ret;
}

static void GDIWinSD_GetRasInfo(JNIEnv *env,
                               SurfaceDataOps *ops,
                               SurfaceDataRasInfo *pRasInfo)
{
    GDIWinSDOps *wsdo = (GDIWinSDOps *) ops;
    jint lockflags = wsdo->lockFlags;
    J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_GetRasInfo");
    HDC hDC = GetThreadDC(env, wsdo);

    if (wsdo->lockType == WIN32SD_LOCK_UNLOCKED) {
        memset(pRasInfo, 0, sizeof(*pRasInfo));
        return;
    }

    if (wsdo->lockType == WIN32SD_LOCK_BY_DIB) {
        int x, y, w, h;
        int pixelStride = wsdo->pixelStride;
        // do not subtract insets from x,y as we take care of it in SD_GetDC
        x = pRasInfo->bounds.x1;
        y = pRasInfo->bounds.y1;
        w = pRasInfo->bounds.x2 - x;
        h = pRasInfo->bounds.y2 - y;

        struct tagBitmapheader  {
            BITMAPINFOHEADER bmiHeader;
            union {
                DWORD           dwMasks[3];
                RGBQUAD         palette[256];
            } colors;
        } bmi;

        // Need to create bitmap if we don't have one already or
        // if the existing one is not large enough for this operation
        // or if we are in 8 bpp display mode (because we need to
        // make sure that the latest palette info gets loaded into
        // the bitmap)
        // REMIND: we should find some way to dynamically force bitmap
        // recreation only when the palette changes
        if (pixelStride == 1 || !wsdo->bitmap || (w > wsdo->bmWidth) ||
            (h > wsdo->bmHeight))
        {
            if (wsdo->bitmap) {
                // delete old objects
                J2dTraceLn(J2D_TRACE_VERBOSE,
                           "GDIWinSD_GetRasInfo: recreating GDI bitmap");
                if (wsdo->bmdc) {   // should not be null
                    ::SelectObject(wsdo->bmdc, wsdo->oldmap);
                    ::DeleteDC(wsdo->bmdc);
                    wsdo->bmdc = 0;
                }
                ::DeleteObject(wsdo->bitmap);
                wsdo->bitmap = 0;
            }
            bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
            bmi.bmiHeader.biWidth = w;
            bmi.bmiHeader.biHeight = -h;
            wsdo->bmWidth = w;
            wsdo->bmHeight = h;
            bmi.bmiHeader.biPlanes = 1;
            bmi.bmiHeader.biBitCount = pixelStride * 8;
            // 1,3 byte use BI_RGB, 2,4 byte use BI_BITFIELD...
            bmi.bmiHeader.biCompression =
                (pixelStride & 1)
                    ? BI_RGB
                    : BI_BITFIELDS;
            bmi.bmiHeader.biSizeImage = 0;
            bmi.bmiHeader.biXPelsPerMeter = 0;
            bmi.bmiHeader.biYPelsPerMeter = 0;
            bmi.bmiHeader.biClrUsed = 0;
            bmi.bmiHeader.biClrImportant = 0;
            if (pixelStride == 1) {
                // we can use systemEntries here because
                // RGBQUAD is xRGB and systemEntries are stored as xRGB
                memcpy(bmi.colors.palette, wsdo->device->GetSystemPaletteEntries(),
                       sizeof(bmi.colors.palette));
            } else {
                // For non-index cases, init the masks for the pixel depth
                for (int i = 0; i < 3; i++) {
                    bmi.colors.dwMasks[i] = wsdo->pixelMasks[i];
                }
            }

            // REMIND: This would be better if moved to the Lock function
            // so that errors could be dealt with.
            wsdo->bitmap = ::CreateDIBSection(hDC, (BITMAPINFO *) &bmi,
                                              DIB_RGB_COLORS, &wsdo->bmBuffer, NULL, 0);
            if (wsdo->bitmap != 0) {
                // scanStride is cached along with reuseable bitmap
                // Round up to the next DWORD boundary
                wsdo->bmScanStride = (wsdo->bmWidth * pixelStride + 3) & ~3;
                wsdo->bmdc = ::CreateCompatibleDC(hDC);
                if (wsdo->bmdc == 0) {
                    ::DeleteObject(wsdo->bitmap);
                    wsdo->bitmap = 0;
                } else {
                    wsdo->oldmap = (HBITMAP) ::SelectObject(wsdo->bmdc,
                                                            wsdo->bitmap);
                }
            }
        }
        if (wsdo->bitmap != 0) {
            if (lockflags & SD_LOCK_NEED_PIXELS) {
                int ret = ::BitBlt(wsdo->bmdc, 0, 0, w, h,
                                   hDC, x, y, SRCCOPY);
                ::GdiFlush();
            }
            wsdo->x = x;
            wsdo->y = y;
            wsdo->w = w;
            wsdo->h = h;
            pRasInfo->rasBase = (char *)wsdo->bmBuffer - (x*pixelStride +
                                y*wsdo->bmScanStride);
            pRasInfo->pixelStride = pixelStride;
            pRasInfo->pixelBitOffset = 0;
            pRasInfo->scanStride = wsdo->bmScanStride;
            if (lockflags & SD_LOCK_WRITE) {
                // If the user writes to the bitmap then we should
                // copy the bitmap to the screen during Unlock
                wsdo->bmCopyToScreen = TRUE;
            }
        } else {
            pRasInfo->rasBase = NULL;
            pRasInfo->pixelStride = 0;
            pRasInfo->pixelBitOffset = 0;
            pRasInfo->scanStride = 0;
        }
    } else {
        /* They didn't lock for anything - we won't give them anything */
        pRasInfo->rasBase = NULL;
        pRasInfo->pixelStride = 0;
        pRasInfo->pixelBitOffset = 0;
        pRasInfo->scanStride = 0;
    }
    if (wsdo->lockFlags & SD_LOCK_LUT) {
        pRasInfo->lutBase =
            (long *) wsdo->device->GetSystemPaletteEntries();
        pRasInfo->lutSize = 256;
    } else {
        pRasInfo->lutBase = NULL;
        pRasInfo->lutSize = 0;
    }
    if (wsdo->lockFlags & SD_LOCK_INVCOLOR) {
        pRasInfo->invColorTable = wsdo->device->GetSystemInverseLUT();
        ColorData *cData = wsdo->device->GetColorData();
        pRasInfo->redErrTable = cData->img_oda_red;
        pRasInfo->grnErrTable = cData->img_oda_green;
        pRasInfo->bluErrTable = cData->img_oda_blue;
    } else {
        pRasInfo->invColorTable = NULL;
        pRasInfo->redErrTable = NULL;
        pRasInfo->grnErrTable = NULL;
        pRasInfo->bluErrTable = NULL;
    }
    if (wsdo->lockFlags & SD_LOCK_INVGRAY) {
        pRasInfo->invGrayTable =
            wsdo->device->GetColorData()->pGrayInverseLutData;
    } else {
        pRasInfo->invGrayTable = NULL;
    }
}

static void GDIWinSD_Setup(JNIEnv *env,
                          SurfaceDataOps *ops)
{
    // Call SetupTGI to ensure that this thread already has a DC that is
    // compatible with this window.  This means that we won't be calling
    // ::SendMessage(GETDC) in the middle of a lock procedure, which creates
    // a potential deadlock situation.
    // Note that calling SetupTGI here means that anybody needing a DC
    // later in this rendering process need only call GetTGI, which
    // assumes that the TGI structure is valid for this thread/window.
    SetupThreadGraphicsInfo(env, (GDIWinSDOps*)ops);
}


static void GDIWinSD_Unlock(JNIEnv *env,
                           SurfaceDataOps *ops,
                           SurfaceDataRasInfo *pRasInfo)
{
    GDIWinSDOps *wsdo = (GDIWinSDOps *) ops;
    J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_Unlock");
    HDC hDC = GetThreadDC(env, wsdo);

    if (wsdo->lockType == WIN32SD_LOCK_UNLOCKED) {
        if (!safe_ExceptionOccurred(env)) {
            JNU_ThrowInternalError(env,
                                   "Unmatched unlock on Win32 SurfaceData");
        }
        return;
    }

    if (wsdo->lockType == WIN32SD_LOCK_BY_DIB) {
        if (wsdo->lockFlags & SD_LOCK_WRITE) {
            J2dTraceLn(J2D_TRACE_VERBOSE,
                       "GDIWinSD_Unlock: do Blt of the bitmap");
            if (wsdo->bmCopyToScreen && ::IsWindowVisible(wsdo->window)) {
                // Don't bother copying to screen if our window has gone away
                // or if the bitmap was not actually written to during this
                // Lock/Unlock procedure.
                ::BitBlt(hDC, wsdo->x, wsdo->y, wsdo->w, wsdo->h,
                    wsdo->bmdc, 0, 0, SRCCOPY);
                ::GdiFlush();
            }
            wsdo->bmCopyToScreen = FALSE;
        }
        wsdo->lockType = WIN32SD_LOCK_UNLOCKED;
        wsdo->ReleaseDC(env, wsdo, hDC);
    }
    wsdo->surfaceLock->Leave();
}

/*
 * REMIND: This mechanism is just a prototype of a way to manage a
 * small cache of DC objects.  It is incomplete in the following ways:
 *
 * - It is not thread-safe!  It needs appropriate locking and release calls
 *   (perhaps the AutoDC mechanisms from Kestrel)
 * - It does hardly any error checking (What if GetDCEx returns NULL?)
 * - It cannot handle printer DCs and their resolution
 * - It should probably "live" in the native SurfaceData object to allow
 *   alternate implementations for printing and embedding
 * - It doesn't handle XOR
 * - It caches the client bounds to determine if clipping is really needed
 *   (no way to invalidate the cached bounds and there is probably a better
 *    way to manage clip validation in any case)
 */

#define COLORFOR(c)     (PALETTERGB(((c)>>16)&0xff,((c)>>8)&0xff,((c)&0xff)))

COLORREF CheckGrayColor(GDIWinSDOps *wsdo, int c) {
    if (wsdo->device->GetGrayness() != GS_NOTGRAY) {
        int g = (77 *(c & 0xFF) +
                 150*((c >> 8) & 0xFF) +
                 29 *((c >> 16) & 0xFF) + 128) / 256;
        c = g | (g << 8) | (g << 16);
    }
    return COLORFOR(c);
}

static HDC GDIWinSD_GetDC(JNIEnv *env, GDIWinSDOps *wsdo,
                         jint type, jint *patrop,
                         jobject clip, jobject comp, jint color)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_GetDC");

    if (wsdo->invalid == JNI_TRUE) {
        if (beingShutdown != JNI_TRUE) {
            SurfaceData_ThrowInvalidPipeException(env, "bounds changed");
        }
        return (HDC) NULL;
    }

    ThreadGraphicsInfo *info = GetThreadGraphicsInfo(env, wsdo);
    GDIWinSD_InitDC(env, wsdo, info, type, patrop, clip, comp, color);
    return env->ExceptionCheck() ? (HDC)NULL : info->hDC;
}

JNIEXPORT void JNICALL
GDIWinSD_InitDC(JNIEnv *env, GDIWinSDOps *wsdo, ThreadGraphicsInfo *info,
               jint type, jint *patrop,
               jobject clip, jobject comp, jint color)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_InitDC");

    // init clip
    if (clip == NULL) {
        if (info->type & CLIP) {
            ::SelectClipRgn(info->hDC, (HRGN) NULL);
            info->type ^= CLIP;
        }
        if (info->clip != NULL) {
            env->DeleteWeakGlobalRef(info->clip);
            info->clip = NULL;
        }
    } else if (!env->IsSameObject(clip, info->clip)) {
        SurfaceDataBounds span;
        RegionData clipInfo;
        if (Region_GetInfo(env, clip, &clipInfo)) {
            // return; // REMIND: What to do here?
        }

        if (Region_IsEmpty(&clipInfo)) {
            HRGN hrgn = ::CreateRectRgn(0, 0, 0, 0);
            ::SelectClipRgn(info->hDC, hrgn);
            ::DeleteObject(hrgn);
            info->type |= CLIP;
        } else if (Region_IsRectangular(&clipInfo)) {
            if (clipInfo.bounds.x1 <= info->bounds.left &&
                clipInfo.bounds.y1 <= info->bounds.top &&
                clipInfo.bounds.x2 >= info->bounds.right &&
                clipInfo.bounds.y2 >= info->bounds.bottom)
            {
                if (info->type & CLIP) {
                    ::SelectClipRgn(info->hDC, (HRGN) NULL);
                    info->type ^= CLIP;
                }
            } else {
                // Make the window-relative rect a client-relative
                // one for Windows
                HRGN hrgn =
                    ::CreateRectRgn(clipInfo.bounds.x1 - wsdo->insets.left,
                                    clipInfo.bounds.y1 - wsdo->insets.top,
                                    clipInfo.bounds.x2 - wsdo->insets.left,
                                    clipInfo.bounds.y2 - wsdo->insets.top);
                ::SelectClipRgn(info->hDC, hrgn);
                ::DeleteObject(hrgn);
                info->type |= CLIP;
            }
        } else {
            int leftInset = wsdo->insets.left;
            int topInset = wsdo->insets.top;
            Region_StartIteration(env, &clipInfo);
            jint numrects = Region_CountIterationRects(&clipInfo);
            RGNDATA *lpRgnData;
            try {
                lpRgnData = (RGNDATA *) SAFE_SIZE_STRUCT_ALLOC(safe_Malloc,
                    sizeof(RGNDATAHEADER), numrects, sizeof(RECT));
            } catch (std::bad_alloc&) {
                JNU_ThrowOutOfMemoryError(env, "Initialization of surface region data failed.");
                return;
            }
            const DWORD nCount = sizeof(RGNDATAHEADER) + numrects * sizeof(RECT);
            lpRgnData->rdh.dwSize = sizeof(RGNDATAHEADER);
            lpRgnData->rdh.iType = RDH_RECTANGLES;
            lpRgnData->rdh.nCount = numrects;
            lpRgnData->rdh.nRgnSize = 0;
            lpRgnData->rdh.rcBound.left = clipInfo.bounds.x1 - leftInset;
            lpRgnData->rdh.rcBound.top = clipInfo.bounds.y1 - topInset;
            lpRgnData->rdh.rcBound.right = clipInfo.bounds.x2 - leftInset;
            lpRgnData->rdh.rcBound.bottom = clipInfo.bounds.y2 - topInset;
            RECT *pRect = (RECT *) &(((RGNDATA *)lpRgnData)->Buffer);
            while (Region_NextIteration(&clipInfo, &span)) {
                pRect->left = span.x1 - leftInset;
                pRect->top = span.y1 - topInset;
                pRect->right = span.x2 - leftInset;
                pRect->bottom = span.y2 - topInset;
                pRect++;
            }
            Region_EndIteration(env, &clipInfo);
            HRGN hrgn = ::ExtCreateRegion(NULL, nCount, lpRgnData);
            free(lpRgnData);
            ::SelectClipRgn(info->hDC, hrgn);
            ::DeleteObject(hrgn);
            info->type |= CLIP;
        }
        if (info->clip != NULL) {
            env->DeleteWeakGlobalRef(info->clip);
        }
        info->clip = env->NewWeakGlobalRef(clip);
        if (env->ExceptionCheck()) {
            return;
        }
    }

    // init composite
    if ((comp == NULL) || !env->IsInstanceOf(comp, xorCompClass)) {
        if (info->comp != NULL) {
            env->DeleteWeakGlobalRef(info->comp);
            info->comp = NULL;
            info->patrop = PATCOPY;
            ::SetROP2(info->hDC, R2_COPYPEN);
        }
    } else {
        if (!env->IsSameObject(comp, info->comp)) {
            info->xorcolor = GrPrim_CompGetXorColor(env, comp);
            if (info->comp != NULL) {
                env->DeleteWeakGlobalRef(info->comp);
            }
            info->comp = env->NewWeakGlobalRef(comp);
            info->patrop = PATINVERT;
            ::SetROP2(info->hDC, R2_XORPEN);
        }
        color ^= info->xorcolor;
    }

    if (patrop != NULL) {
        *patrop = info->patrop;
    }

    // init brush and pen
    if (type & BRUSH) {
        if (info->brushclr != color || (info->brush == NULL)) {
            if (info->type & BRUSH) {
                ::SelectObject(info->hDC, nullbrush);
                info->type ^= BRUSH;
            }
            if (info->brush != NULL) {
                info->brush->Release();
            }
            info->brush = AwtBrush::Get(CheckGrayColor(wsdo, color));
            info->brushclr = color;
        }
        if ((info->type & BRUSH) == 0) {
            ::SelectObject(info->hDC, info->brush->GetHandle());
            info->type ^= BRUSH;
        }
    } else if (type & NOBRUSH) {
        if (info->type & BRUSH) {
            ::SelectObject(info->hDC, nullbrush);
            info->type ^= BRUSH;
        }
    }
    if (type & PEN) {
        if (info->penclr != color || (info->pen == NULL)) {
            if (info->type & PEN) {
                ::SelectObject(info->hDC, nullpen);
                info->type ^= PEN;
            }
            if (info->pen != NULL) {
                info->pen->Release();
            }
            info->pen = AwtPen::Get(CheckGrayColor(wsdo, color));
            info->penclr = color;
        }
        if ((info->type & PEN) == 0) {
            ::SelectObject(info->hDC, info->pen->GetHandle());
            info->type ^= PEN;
        }
    } else if (type & NOPEN) {
        if (info->type & PEN) {
            ::SelectObject(info->hDC, nullpen);
            info->type ^= PEN;
        }
    }
}

static void GDIWinSD_ReleaseDC(JNIEnv *env, GDIWinSDOps *wsdo, HDC hDC)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_ReleaseDC");
    // Don't actually do anything here: every thread holds its own
    // wsdo-specific DC until the thread goes away or the wsdo
    // is disposed.
}


static void GDIWinSD_InvalidateSD(JNIEnv *env, GDIWinSDOps *wsdo)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_InvalidateSD");
    J2dTraceLn2(J2D_TRACE_VERBOSE, "  wsdo=0x%x wsdo->window=0x%x",
                wsdo, wsdo->window);

    wsdo->invalid = JNI_TRUE;
}



/*
 * Method:    GDIWinSD_Dispose
 */
static void
GDIWinSD_Dispose(JNIEnv *env, SurfaceDataOps *ops)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_Dispose");
    // ops is assumed non-null as it is checked in SurfaceData_DisposeOps
    GDIWinSDOps *wsdo = (GDIWinSDOps*)ops;
    if (wsdo->bitmap) {
        // delete old objects
        J2dTraceLn(J2D_TRACE_VERBOSE, "  disposing the GDI bitmap");
        if (wsdo->bmdc) {   // should not be null
            ::SelectObject(wsdo->bmdc, wsdo->oldmap);
            ::DeleteDC(wsdo->bmdc);
            wsdo->bmdc = 0;
        }
        ::DeleteObject(wsdo->bitmap);
        wsdo->bitmap = 0;
    }
    env->DeleteWeakGlobalRef(wsdo->peer);
    if (wsdo->device != NULL) {
        wsdo->device->Release();
        wsdo->device = NULL;
    }
    delete wsdo->surfaceLock;
}


/*
 * Class:     sun_java2d_windows_GDIWindowSurfaceData
 * Method:    invalidateSD
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_java2d_windows_GDIWindowSurfaceData_invalidateSD(JNIEnv *env, jobject wsd)
{
    J2dTraceLn(J2D_TRACE_INFO, "GDIWindowSurfaceData_invalidateSD");
    GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOpsNoSetup(env, wsd);
    if (wsdo != NULL) {
        wsdo->InvalidateSD(env, wsdo);
    }
}
