jdk/src/windows/native/sun/java2d/windows/Win32OffScreenSurfaceData.cpp
changeset 1024 2253d6d6cf2c
parent 1023 9a1c25552b10
parent 945 6838c1a3296a
child 1025 a9ba5ea0f1f7
equal deleted inserted replaced
1023:9a1c25552b10 1024:2253d6d6cf2c
     1 /*
       
     2  * Copyright 2000-2006 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 #include "sun_java2d_windows_Win32OffScreenSurfaceData.h"
       
    27 
       
    28 #include "Win32SurfaceData.h"
       
    29 
       
    30 #include "Trace.h"
       
    31 #include "Region.h"
       
    32 #include "awt_Component.h"
       
    33 #include "debug_trace.h"
       
    34 #include "ddrawUtils.h"
       
    35 #include "awt_Win32GraphicsDevice.h"
       
    36 #include "D3DContext.h"
       
    37 
       
    38 #include "jni_util.h"
       
    39 
       
    40 /**
       
    41  * This source file contains support code for loops using the
       
    42  * SurfaceData interface to talk to a Win32 drawable from native
       
    43  * code.
       
    44  */
       
    45 
       
    46 JNIEXPORT void JNICALL
       
    47 Win32OSSD_InitDC(JNIEnv *env, Win32SDOps *wsdo, HDC hdc,
       
    48                  jint type, jint *patrop,
       
    49                  jobject clip, jobject comp, jint color);
       
    50 jfieldID ddSurfacePuntedID;
       
    51 jmethodID markSurfaceLostMID;
       
    52 static HBRUSH   nullbrush;
       
    53 static HPEN     nullpen;
       
    54 
       
    55 extern BOOL ddVramForced;
       
    56 
       
    57 LockFunc Win32OSSD_Lock;
       
    58 GetRasInfoFunc Win32OSSD_GetRasInfo;
       
    59 UnlockFunc Win32OSSD_Unlock;
       
    60 DisposeFunc Win32OSSD_Dispose;
       
    61 GetDCFunc Win32OSSD_GetDC;
       
    62 ReleaseDCFunc Win32OSSD_ReleaseDC;
       
    63 InvalidateSDFunc Win32OSSD_InvalidateSD;
       
    64 RestoreSurfaceFunc Win32OSSD_RestoreSurface;
       
    65 
       
    66 extern "C" {
       
    67 
       
    68 /*
       
    69  * Class:     sun_java2d_windows_Win32OffScreenSurfaceData
       
    70  * Method:    initIDs
       
    71  * Signature: ()V
       
    72  */
       
    73 JNIEXPORT void JNICALL
       
    74 Java_sun_java2d_windows_Win32OffScreenSurfaceData_initIDs(JNIEnv *env,
       
    75                                                           jclass wsd)
       
    76 {
       
    77     J2dTraceLn(J2D_TRACE_INFO, "Win32OffScreenSurfaceData_initIDs");
       
    78     ddSurfacePuntedID = env->GetFieldID(wsd, "ddSurfacePunted", "Z");
       
    79     markSurfaceLostMID = env->GetMethodID(wsd, "markSurfaceLost", "()V");
       
    80     nullbrush = (HBRUSH) ::GetStockObject(NULL_BRUSH);
       
    81     nullpen = (HPEN) ::GetStockObject(NULL_PEN);
       
    82 }
       
    83 
       
    84 void Win32OSSD_DisableDD(JNIEnv *env, Win32SDOps *wsdo)
       
    85 {
       
    86     J2dTraceLn(J2D_TRACE_INFO, "Win32OSSD_DisableDD");
       
    87 
       
    88     wsdo->RestoreSurface(env, wsdo);
       
    89     jobject sdObject = env->NewLocalRef(wsdo->sdOps.sdObject);
       
    90     if (sdObject != NULL) {
       
    91         J2dRlsTraceLn1(J2D_TRACE_ERROR,
       
    92                        "Win32OSSD_DisableDD: disabling DirectDraw"\
       
    93                        " for surface 0x%x", wsdo);
       
    94         JNU_CallMethodByName(env, NULL, sdObject, "disableDD", "()V");
       
    95         env->DeleteLocalRef(sdObject);
       
    96     }
       
    97 }
       
    98 
       
    99 void disposeOSSD_WSDO(JNIEnv* env, Win32SDOps* wsdo)
       
   100 {
       
   101     J2dTraceLn(J2D_TRACE_INFO, "disposeOSSD_WSDO");
       
   102     if (wsdo->device != NULL) {
       
   103         wsdo->device->Release();
       
   104         wsdo->device = NULL;
       
   105     }
       
   106     delete wsdo->surfaceLock;
       
   107 }
       
   108 
       
   109 jboolean initOSSD_WSDO(JNIEnv* env, Win32SDOps* wsdo, jint width, jint height,
       
   110                        jint screen, jint transparency)
       
   111 {
       
   112     J2dTraceLn1(J2D_TRACE_INFO, "initOSSD_WSDO screen=%d", screen);
       
   113 
       
   114     {
       
   115         Devices::InstanceAccess devices;
       
   116         wsdo->device = devices->GetDeviceReference(screen, FALSE);
       
   117     }
       
   118     if (wsdo->device == NULL) {
       
   119         J2dTraceLn1(J2D_TRACE_WARNING,
       
   120                     "initOSSD_WSDO: Incorrect "\
       
   121                     "screen number (screen=%d)", screen);
       
   122         wsdo->invalid = TRUE;
       
   123         return JNI_FALSE;
       
   124     }
       
   125 
       
   126     wsdo->transparency = transparency;
       
   127     wsdo->w = width;
       
   128     wsdo->h = height;
       
   129     wsdo->surfacePuntData.disablePunts = TRUE;
       
   130     return JNI_TRUE;
       
   131 }
       
   132 
       
   133 JNIEXPORT void JNICALL
       
   134 Java_sun_java2d_windows_Win32OffScreenSurfaceData_initSurface
       
   135     (JNIEnv *env,
       
   136      jobject sData,
       
   137      jint depth,
       
   138      jint width, jint height,
       
   139      jint screen,
       
   140      jboolean isVolatile,
       
   141      jint transparency)
       
   142 {
       
   143     Win32SDOps *wsdo = (Win32SDOps *)SurfaceData_GetOps(env, sData);
       
   144 
       
   145     J2dTraceLn(J2D_TRACE_INFO, "Win32OSSD_initSurface");
       
   146     jboolean status =
       
   147         initOSSD_WSDO(env, wsdo, width, height, screen, transparency);
       
   148 
       
   149     if (status == JNI_FALSE || !DDCreateSurface(wsdo)) {
       
   150         J2dRlsTraceLn1(J2D_TRACE_ERROR,
       
   151                        "Win32OffScreenSurfaceData_initSurface: Error creating "\
       
   152                        "offscreen surface (transparency=%d), throwing IPE",
       
   153                        transparency);
       
   154         SurfaceData_ThrowInvalidPipeException(env,
       
   155                                               "Can't create offscreen surf");
       
   156         return;
       
   157     } else {
       
   158         wsdo->surfacePuntData.lpSurfaceVram = wsdo->lpSurface;
       
   159     }
       
   160     // 8 is somewhat arbitrary; we want the threshhold to represent a
       
   161     // significant portion of the surface area in order to avoid
       
   162     // punting for occasional, small reads
       
   163     wsdo->surfacePuntData.pixelsReadThreshold = width * height / 8;
       
   164     /**
       
   165      * Only enable our punt-to-sysmem-surface scheme for surfaces that are:
       
   166      *   - non-transparent (we really only intended this workaround for
       
   167      *     back buffers, which are usually opaque)
       
   168      *   - volatile (non-volatile images should not even get into the punt
       
   169      *     situation since they should not be a rendering destination, but
       
   170      *     we check this just to make sure)
       
   171      * And only do so if the user did not specify that punting be disabled
       
   172      */
       
   173     wsdo->surfacePuntData.disablePunts = (transparency != TR_OPAQUE) ||
       
   174                                          !isVolatile                 ||
       
   175                                          ddVramForced;
       
   176 }
       
   177 
       
   178 /*
       
   179  * Class:     sun_java2d_windows_Win32OffScreenSurfaceData
       
   180  * Method:    restoreSurface
       
   181  * Signature: ()V
       
   182  */
       
   183 JNIEXPORT void JNICALL
       
   184 Java_sun_java2d_windows_Win32OffScreenSurfaceData_restoreSurface(JNIEnv *env,
       
   185                                                                  jobject sData)
       
   186 {
       
   187     J2dTraceLn(J2D_TRACE_INFO,
       
   188                "Win32OSSD_restoreSurface: restoring offscreen");
       
   189     Win32SDOps *wsdo = (Win32SDOps *)SurfaceData_GetOps(env, sData);
       
   190 
       
   191     // Might have gotten here by some default action.  Make sure that the
       
   192     // surface is marked as lost before bothering to try to restore it.
       
   193     if (!wsdo->surfaceLost) {
       
   194         return;
       
   195     }
       
   196 
       
   197     // Attempt to restore and lock the surface (to make sure the restore worked)
       
   198     if (DDRestoreSurface(wsdo) && DDLock(env, wsdo, NULL, NULL)) {
       
   199         DDUnlock(env, wsdo);
       
   200         wsdo->surfaceLost = FALSE;
       
   201     } else {
       
   202         // Failure - throw exception
       
   203         J2dRlsTraceLn(J2D_TRACE_ERROR,
       
   204                       "Win32OSSD_restoreSurface: problems"\
       
   205                       " restoring, throwing IPE");
       
   206         SurfaceData_ThrowInvalidPipeException(env, "RestoreSurface failure");
       
   207     }
       
   208 }
       
   209 
       
   210 
       
   211 /*
       
   212  * Class:     sun_java2d_windows_Win32OffScreenSurfaceData
       
   213  * Method:    initOps
       
   214  * Signature: (Ljava/lang/Object;)V
       
   215  */
       
   216 JNIEXPORT void JNICALL
       
   217 Java_sun_java2d_windows_Win32OffScreenSurfaceData_initOps(JNIEnv *env,
       
   218                                                           jobject wsd,
       
   219                                                           jint depth,
       
   220                                                           jint transparency)
       
   221 {
       
   222     J2dTraceLn(J2D_TRACE_INFO, "Win32OffScreenSurfaceData_initOps");
       
   223     Win32SDOps *wsdo =
       
   224         (Win32SDOps *)SurfaceData_InitOps(env, wsd, sizeof(Win32SDOps));
       
   225     wsdo->sdOps.Lock = Win32OSSD_Lock;
       
   226     wsdo->sdOps.GetRasInfo = Win32OSSD_GetRasInfo;
       
   227     wsdo->sdOps.Unlock = Win32OSSD_Unlock;
       
   228     wsdo->sdOps.Dispose = Win32OSSD_Dispose;
       
   229     wsdo->RestoreSurface = Win32OSSD_RestoreSurface;
       
   230     wsdo->GetDC = Win32OSSD_GetDC;
       
   231     wsdo->ReleaseDC = Win32OSSD_ReleaseDC;
       
   232     wsdo->InvalidateSD = Win32OSSD_InvalidateSD;
       
   233     wsdo->invalid = JNI_FALSE;
       
   234     wsdo->lockType = WIN32SD_LOCK_UNLOCKED;
       
   235     wsdo->window = NULL;
       
   236     wsdo->backBufferCount = 0;
       
   237     wsdo->depth = depth;
       
   238     switch (depth) {
       
   239         case 8:
       
   240             wsdo->pixelStride = 1;
       
   241             break;
       
   242         case 15: //555
       
   243             wsdo->pixelStride = 2;
       
   244             wsdo->pixelMasks[0] = 0x1f << 10;
       
   245             wsdo->pixelMasks[1] = 0x1f << 5;
       
   246             wsdo->pixelMasks[2] = 0x1f;
       
   247             break;
       
   248         case 16: //565
       
   249             wsdo->pixelStride = 2;
       
   250             wsdo->pixelMasks[0] = 0x1f << 11;
       
   251             wsdo->pixelMasks[1] = 0x3f << 5;
       
   252             wsdo->pixelMasks[2] = 0x1f;
       
   253             break;
       
   254         case 24:
       
   255             wsdo->pixelStride = 3;
       
   256             break;
       
   257         case 32: //888
       
   258             wsdo->pixelStride = 4;
       
   259             wsdo->pixelMasks[0] = 0xff0000;
       
   260             wsdo->pixelMasks[1] = 0x00ff00;
       
   261             wsdo->pixelMasks[2] = 0x0000ff;
       
   262             break;
       
   263     }
       
   264     wsdo->surfaceLock = new CriticalSection();
       
   265     wsdo->surfaceLost = FALSE;
       
   266     wsdo->transparency = transparency;
       
   267     wsdo->surfacePuntData.usingDDSystem = FALSE;
       
   268     wsdo->surfacePuntData.lpSurfaceSystem = NULL;
       
   269     wsdo->surfacePuntData.lpSurfaceVram = NULL;
       
   270     wsdo->surfacePuntData.numBltsSinceRead = 0;
       
   271     wsdo->surfacePuntData.pixelsReadSinceBlt = 0;
       
   272     wsdo->surfacePuntData.numBltsThreshold = 2;
       
   273     wsdo->gdiOpPending = FALSE;
       
   274 }
       
   275 
       
   276 JNIEXPORT Win32SDOps * JNICALL
       
   277 Win32OffScreenSurfaceData_GetOps(JNIEnv *env, jobject sData)
       
   278 {
       
   279     J2dTraceLn(J2D_TRACE_VERBOSE, "Win32OffScreenSurfaceData_GetOps");
       
   280     SurfaceDataOps *ops = SurfaceData_GetOps(env, sData);
       
   281     if (ops == NULL) {
       
   282         JNU_ThrowNullPointerException(env, "SurfaceData native ops");
       
   283     } else if (ops->Lock != Win32OSSD_Lock) {
       
   284         SurfaceData_ThrowInvalidPipeException(env, "not a Win32 SurfaceData");
       
   285         ops = NULL;
       
   286     }
       
   287     return (Win32SDOps *) ops;
       
   288 }
       
   289 
       
   290 } /* extern "C" */
       
   291 
       
   292 void Win32OSSD_RestoreSurface(JNIEnv *env, Win32SDOps *wsdo)
       
   293 {
       
   294     J2dTraceLn(J2D_TRACE_INFO, "Win32OSSD_RestoreSurface");
       
   295     wsdo->surfaceLost = TRUE;
       
   296     jobject sdObject = env->NewLocalRef(wsdo->sdOps.sdObject);
       
   297     if (sdObject != NULL) {
       
   298         // markSurfaceLost will end up throwing an InvalidPipeException
       
   299         // if this surface belongs to a managed image.
       
   300         env->CallVoidMethod(sdObject, markSurfaceLostMID);
       
   301         env->DeleteLocalRef(sdObject);
       
   302     }
       
   303 }
       
   304 
       
   305 void Win32OSSD_LockByDD(JNIEnv *env, Win32SDOps *wsdo, jint lockflags,
       
   306                         SurfaceDataRasInfo *pRasInfo)
       
   307 {
       
   308     J2dTraceLn(J2D_TRACE_INFO, "Win32OSSD_LockByDD");
       
   309 
       
   310     if ((lockflags & SD_LOCK_READ) &&
       
   311         !wsdo->surfacePuntData.disablePunts)
       
   312     {
       
   313         wsdo->surfacePuntData.numBltsSinceRead = 0;
       
   314         if (!wsdo->surfacePuntData.usingDDSystem) {
       
   315             int w = pRasInfo->bounds.x2 - pRasInfo->bounds.x1;
       
   316             int h = pRasInfo->bounds.y2 - pRasInfo->bounds.y1;
       
   317             wsdo->surfacePuntData.pixelsReadSinceBlt += w * h;
       
   318             // Note that basing this decision on the bounds is somewhat
       
   319             // incorrect because locks of type FASTEST will simply send
       
   320             // in bounds that equal the area of the entire surface.
       
   321             // To do this correctly, we would need to return
       
   322             // SLOWLOCK and recalculate the punt data in GetRasInfo()
       
   323             if (wsdo->surfacePuntData.pixelsReadSinceBlt >
       
   324                 wsdo->surfacePuntData.pixelsReadThreshold)
       
   325             {
       
   326                 // Create the system surface if it doesn't exist
       
   327                 if (!wsdo->surfacePuntData.lpSurfaceSystem) {
       
   328                     wsdo->surfacePuntData.lpSurfaceSystem =
       
   329                         wsdo->ddInstance->ddObject->CreateDDOffScreenSurface(
       
   330                         wsdo->w, wsdo->h, wsdo->depth,
       
   331                         wsdo->transparency, DDSCAPS_SYSTEMMEMORY);
       
   332                     if (wsdo->surfacePuntData.lpSurfaceSystem) {
       
   333                         // 4941350: Double-check that the surface we created
       
   334                         // matches the depth expected.
       
   335                         int sysmemDepth =
       
   336                             wsdo->surfacePuntData.lpSurfaceSystem->GetSurfaceDepth();
       
   337                         if (!DDSurfaceDepthsCompatible(wsdo->depth, sysmemDepth)) {
       
   338                             // There is clearly a problem here; release
       
   339                             // the punting surface
       
   340                             J2dTraceLn2(J2D_TRACE_WARNING,
       
   341                                         "Win32OSSD_LockByDD: Punting error: "\
       
   342                                         "wsdo->depth=%d memory surface depth=%d",
       
   343                                         wsdo->depth, sysmemDepth);
       
   344                             DDReleaseSurfaceMemory(wsdo->surfacePuntData.
       
   345                                 lpSurfaceSystem);
       
   346                             wsdo->surfacePuntData.lpSurfaceSystem = NULL;
       
   347                         } else {
       
   348                             DDCOLORKEY ddck;
       
   349                             HRESULT ddResult =
       
   350                                 wsdo->surfacePuntData.lpSurfaceVram->GetColorKey(
       
   351                                 DDCKEY_SRCBLT, &ddck);
       
   352                             if (ddResult == DD_OK) {
       
   353                                 // Vram surface has colorkey - use same colorkey on sys
       
   354                                 ddResult =
       
   355                                     wsdo->surfacePuntData.lpSurfaceSystem->SetColorKey(
       
   356                                     DDCKEY_SRCBLT, &ddck);
       
   357                             }
       
   358                         }
       
   359                     }
       
   360                 }
       
   361                 // Assuming no errors in system creation, copy contents
       
   362                 if (wsdo->surfacePuntData.lpSurfaceSystem) {
       
   363                     if (wsdo->surfacePuntData.lpSurfaceSystem->Blt(NULL,
       
   364                             wsdo->surfacePuntData.lpSurfaceVram, NULL,
       
   365                             DDBLT_WAIT, NULL) == DD_OK)
       
   366                     {
       
   367                         J2dTraceLn2(J2D_TRACE_INFO,
       
   368                                     "Win32OSSD_LockByDD: punting VRAM to sys: "\
       
   369                                     "0x%x -> 0x%x",
       
   370                                     wsdo->surfacePuntData.lpSurfaceVram,
       
   371                                     wsdo->surfacePuntData.lpSurfaceSystem);
       
   372                         wsdo->lpSurface = wsdo->surfacePuntData.lpSurfaceSystem;
       
   373                         wsdo->surfacePuntData.usingDDSystem = TRUE;
       
   374                         // Notify the Java level that this surface has
       
   375                         // been punted to avoid performance penalties from
       
   376                         // copying from VRAM cached versions of other images
       
   377                         // when we should use system memory versions instead.
       
   378                         jobject sdObject =
       
   379                             env->NewLocalRef(wsdo->sdOps.sdObject);
       
   380                         if (sdObject) {
       
   381                             // Only bother with this optimization if the
       
   382                             // reference is still valid
       
   383                             env->SetBooleanField(sdObject, ddSurfacePuntedID,
       
   384                                                  JNI_TRUE);
       
   385                             env->DeleteLocalRef(sdObject);
       
   386                         }
       
   387                     }
       
   388                 }
       
   389             }
       
   390         }
       
   391     }
       
   392 
       
   393     if (!DDLock(env, wsdo, NULL, pRasInfo))
       
   394         return;
       
   395 
       
   396     wsdo->lockType = WIN32SD_LOCK_BY_DDRAW;
       
   397 }
       
   398 
       
   399 
       
   400 jint Win32OSSD_Lock(JNIEnv *env,
       
   401                     SurfaceDataOps *ops,
       
   402                     SurfaceDataRasInfo *pRasInfo,
       
   403                     jint lockflags)
       
   404 {
       
   405     Win32SDOps *wsdo = (Win32SDOps *) ops;
       
   406     J2dTraceLn1(J2D_TRACE_INFO, "Win32OSSD_Lock: lockflags=0x%x",
       
   407                 lockflags);
       
   408     wsdo->surfaceLock->Enter();
       
   409     if (wsdo->invalid) {
       
   410         wsdo->surfaceLock->Leave();
       
   411         SurfaceData_ThrowInvalidPipeException(env, "invalid sd");
       
   412         return SD_FAILURE;
       
   413     }
       
   414 
       
   415     if (wsdo->lockType != WIN32SD_LOCK_UNLOCKED) {
       
   416         wsdo->surfaceLock->Leave();
       
   417         JNU_ThrowInternalError(env, "Win32OSSD_Lock cannot nest locks");
       
   418         return SD_FAILURE;
       
   419     }
       
   420 
       
   421     if (lockflags & SD_LOCK_RD_WR) {
       
   422         if (pRasInfo->bounds.x1 < 0) pRasInfo->bounds.x1 = 0;
       
   423         if (pRasInfo->bounds.y1 < 0) pRasInfo->bounds.y1 = 0;
       
   424         if (pRasInfo->bounds.x2 > wsdo->w) pRasInfo->bounds.x2 = wsdo->w;
       
   425         if (pRasInfo->bounds.y2 > wsdo->h) pRasInfo->bounds.y2 = wsdo->h;
       
   426         if (DDUseDDraw(wsdo)) {
       
   427             Win32OSSD_LockByDD(env, wsdo, lockflags, pRasInfo);
       
   428         }
       
   429         if (wsdo->lockType == WIN32SD_LOCK_UNLOCKED) {
       
   430             wsdo->lockFlags = lockflags;
       
   431             wsdo->surfaceLock->Leave();
       
   432             return SD_FAILURE;
       
   433         }
       
   434     } else {
       
   435         // They didn't ask for a lock, so they don't get one
       
   436         wsdo->lockType = WIN32SD_LOCK_BY_NULL;
       
   437     }
       
   438     wsdo->lockFlags = lockflags;
       
   439     J2dTraceLn2(J2D_TRACE_VERBOSE, "Win32OSSD_Lock: flags=0x%x type=%d",
       
   440                 wsdo->lockFlags, wsdo->lockType);
       
   441     return 0;
       
   442 }
       
   443 
       
   444 void Win32OSSD_GetRasInfo(JNIEnv *env,
       
   445                           SurfaceDataOps *ops,
       
   446                           SurfaceDataRasInfo *pRasInfo)
       
   447 {
       
   448     Win32SDOps *wsdo = (Win32SDOps *) ops;
       
   449     jint lockflags = wsdo->lockFlags;
       
   450 
       
   451     J2dTraceLn(J2D_TRACE_INFO, "Win32OSSD_GetRasInfo");
       
   452 
       
   453     if (wsdo->lockType == WIN32SD_LOCK_UNLOCKED) {
       
   454         J2dRlsTraceLn(J2D_TRACE_ERROR,
       
   455                       "Win32OSSD_GetRasInfo: lockType=UNLOCKED");
       
   456         memset(pRasInfo, 0, sizeof(*pRasInfo));
       
   457         return;
       
   458     }
       
   459 
       
   460     if (wsdo->lockType != WIN32SD_LOCK_BY_DDRAW) {
       
   461         /* They didn't lock for anything - we won't give them anything */
       
   462         pRasInfo->rasBase = NULL;
       
   463         pRasInfo->pixelStride = 0;
       
   464         pRasInfo->pixelBitOffset = 0;
       
   465         pRasInfo->scanStride = 0;
       
   466     }
       
   467     if (wsdo->lockFlags & SD_LOCK_LUT) {
       
   468         pRasInfo->lutBase =
       
   469             (long *) wsdo->device->GetSystemPaletteEntries();
       
   470         pRasInfo->lutSize = 256;
       
   471     } else {
       
   472         pRasInfo->lutBase = NULL;
       
   473         pRasInfo->lutSize = 0;
       
   474     }
       
   475     if (wsdo->lockFlags & SD_LOCK_INVCOLOR) {
       
   476         pRasInfo->invColorTable = wsdo->device->GetSystemInverseLUT();
       
   477         ColorData *cData = wsdo->device->GetColorData();
       
   478         pRasInfo->redErrTable = cData->img_oda_red;
       
   479         pRasInfo->grnErrTable = cData->img_oda_green;
       
   480         pRasInfo->bluErrTable = cData->img_oda_blue;
       
   481     } else {
       
   482         pRasInfo->invColorTable = NULL;
       
   483         pRasInfo->redErrTable = NULL;
       
   484         pRasInfo->grnErrTable = NULL;
       
   485         pRasInfo->bluErrTable = NULL;
       
   486     }
       
   487     if (wsdo->lockFlags & SD_LOCK_INVGRAY) {
       
   488         pRasInfo->invGrayTable =
       
   489             wsdo->device->GetColorData()->pGrayInverseLutData;
       
   490     } else {
       
   491         pRasInfo->invGrayTable = NULL;
       
   492     }
       
   493 }
       
   494 
       
   495 void Win32OSSD_Unlock(JNIEnv *env,
       
   496                       SurfaceDataOps *ops,
       
   497                       SurfaceDataRasInfo *pRasInfo)
       
   498 {
       
   499     Win32SDOps *wsdo = (Win32SDOps *) ops;
       
   500 
       
   501     J2dTraceLn(J2D_TRACE_INFO, "Win32OSSD_Unlock");
       
   502 
       
   503     if (wsdo->lockType == WIN32SD_LOCK_UNLOCKED) {
       
   504         JNU_ThrowInternalError(env, "Unmatched unlock on Win32OS SurfaceData");
       
   505         return;
       
   506     }
       
   507 
       
   508     if (wsdo->lockType == WIN32SD_LOCK_BY_DDRAW) {
       
   509         DDUnlock(env, wsdo);
       
   510     }
       
   511     wsdo->lockType = WIN32SD_LOCK_UNLOCKED;
       
   512     wsdo->surfaceLock->Leave();
       
   513 }
       
   514 
       
   515 static void
       
   516 GetClipFromRegion(JNIEnv *env, jobject clip, RECT &r)
       
   517 {
       
   518     SurfaceDataBounds bounds;
       
   519     Region_GetBounds(env, clip, &bounds);
       
   520     r.left = bounds.x1;
       
   521     r.top = bounds.y1;
       
   522     r.right = bounds.x2;
       
   523     r.bottom = bounds.y2;
       
   524 }
       
   525 
       
   526 /*
       
   527  * REMIND: This mechanism is just a prototype of a way to manage a
       
   528  * small cache of DC objects.  It is incomplete in the following ways:
       
   529  *
       
   530  * - It is not thread-safe!  It needs appropriate locking and release calls
       
   531  *   (perhaps the AutoDC mechanisms from Kestrel)
       
   532  * - It does hardly any error checking (What if GetDCEx returns NULL?)
       
   533  * - It cannot handle printer DCs, their resolution, or Embedded DCs
       
   534  * - It always selects a clip region, even if the clip is the window bounds
       
   535  * - There is very little error checking (null DC returned from GetDCEx, etc)
       
   536  * - It should probably "live" in the native SurfaceData object to allow
       
   537  *   alternate implementations for printing and embedding
       
   538  * - It doesn't handle XOR
       
   539  * - It caches the client bounds to determine if clipping is really needed
       
   540  *   (no way to invalidate the cached bounds and there is probably a better
       
   541  *    way to manage clip validation in any case)
       
   542  */
       
   543 
       
   544 extern COLORREF CheckGrayColor(Win32SDOps *wsdo, int c);
       
   545 HDC Win32OSSD_GetDC(JNIEnv *env, Win32SDOps *wsdo,
       
   546                     jint type, jint *patrop,
       
   547                     jobject clip, jobject comp, jint color)
       
   548 {
       
   549     // REMIND: Should lock around all accesses to "last<mumble>"
       
   550     J2dTraceLn1(J2D_TRACE_INFO, "Win32OSSD_GetDC: color=0x%x", color);
       
   551 
       
   552     if (wsdo->invalid) {
       
   553         SurfaceData_ThrowInvalidPipeException(env, "invalid sd");
       
   554         return (HDC) NULL;
       
   555     }
       
   556 
       
   557     HDC hdc;
       
   558     HRESULT res = wsdo->lpSurface->GetDC(&hdc);
       
   559     if (res != DD_OK) {
       
   560         if (res == DDERR_CANTCREATEDC) {
       
   561             // this may be a manifestations of an unrecoverable error caused by
       
   562             // address space exaustion when heap size is too large
       
   563             Win32OSSD_DisableDD(env, wsdo);
       
   564         }
       
   565         // Note: DDrawSurface::GetDC() releases its surfaceLock
       
   566         // when it returns an error here, so do not call ReleaseDC()
       
   567         // to force the release of surfaceLock
       
   568         SurfaceData_ThrowInvalidPipeException(env, "invalid sd");
       
   569         return (HDC) NULL;
       
   570     }
       
   571 
       
   572     // Initialize the DC
       
   573     Win32OSSD_InitDC(env, wsdo, hdc, type, patrop, clip, comp, color);
       
   574     return hdc;
       
   575 }
       
   576 
       
   577 JNIEXPORT void JNICALL
       
   578 Win32OSSD_InitDC(JNIEnv *env, Win32SDOps *wsdo, HDC hdc,
       
   579                  jint type, jint *patrop,
       
   580                  jobject clip, jobject comp, jint color)
       
   581 {
       
   582     J2dTraceLn(J2D_TRACE_INFO, "Win32OSSD_InitDC");
       
   583     // Initialize DC.  Assume nothing about the DC since ddraw DC's are
       
   584     // created from scratch every time
       
   585 
       
   586     // Since we can't get here in XOR mode (ISCOPY only), we will ignore the
       
   587     // comp and force the patrop to PATCOPY if necessary.
       
   588     if (patrop != NULL) {
       
   589         *patrop = PATCOPY;
       
   590     }
       
   591 
       
   592     if (clip == NULL) {
       
   593         ::SelectClipRgn(hdc, (HRGN) NULL);
       
   594     } else {
       
   595         RECT r;
       
   596         GetClipFromRegion(env, clip, r);
       
   597         // Only bother setting clip if it's smaller than our window
       
   598         if ((r.left > 0) || (r.top > 0) ||
       
   599             (r.right < wsdo->w) || (r.bottom < wsdo->h)) {
       
   600             J2dTraceLn4(J2D_TRACE_VERBOSE,
       
   601                         "Win32OSSD_InitDC: clipRect "\
       
   602                         "l=%-4d t=%-4d r=%-4d b=%-4d",
       
   603                         r.left, r.top, r.right, r.bottom);
       
   604             //Make the window-relative rect a client-relative one for Windows
       
   605             ::OffsetRect(&r, -wsdo->insets.left, -wsdo->insets.top);
       
   606             if (r.left > r.right) r.left = r.right;
       
   607             if (r.top > r.bottom) r.top = r.bottom;
       
   608             HRGN hrgn = ::CreateRectRgnIndirect(&r);
       
   609             ::SelectClipRgn(hdc, hrgn);
       
   610             ::DeleteObject(hrgn);
       
   611         }
       
   612     }
       
   613     if (type & BRUSH) {
       
   614         if (wsdo->brushclr != color || (wsdo->brush == NULL)) {
       
   615             if (wsdo->brush != NULL) {
       
   616                 wsdo->brush->Release();
       
   617             }
       
   618             wsdo->brush = AwtBrush::Get(CheckGrayColor(wsdo, color));
       
   619             wsdo->brushclr = color;
       
   620         }
       
   621         // always select a new brush - the DC is new every time
       
   622         ::SelectObject(hdc, wsdo->brush->GetHandle());
       
   623     } else if (type & NOBRUSH) {
       
   624         ::SelectObject(hdc, nullbrush);
       
   625     }
       
   626     if (type & PEN) {
       
   627         if (wsdo->penclr != color || (wsdo->pen == NULL)) {
       
   628             if (wsdo->pen != NULL) {
       
   629                 wsdo->pen->Release();
       
   630             }
       
   631             wsdo->pen = AwtPen::Get(CheckGrayColor(wsdo, color));
       
   632             wsdo->penclr = color;
       
   633         }
       
   634         // always select a new pen - the DC is new every time
       
   635         ::SelectObject(hdc, wsdo->pen->GetHandle());
       
   636     } else if (type & NOPEN) {
       
   637         ::SelectObject(hdc, nullpen);
       
   638     }
       
   639 }
       
   640 
       
   641 void Win32OSSD_ReleaseDC(JNIEnv *env, Win32SDOps *wsdo, HDC hdc)
       
   642 {
       
   643     J2dTraceLn(J2D_TRACE_INFO, "Win32OSSD_ReleaseDC");
       
   644     wsdo->lpSurface->ReleaseDC(hdc);
       
   645     wsdo->gdiOpPending = TRUE;
       
   646 }
       
   647 
       
   648 void Win32OSSD_InvalidateSD(JNIEnv *env, Win32SDOps *wsdo)
       
   649 {
       
   650     J2dTraceLn(J2D_TRACE_INFO, "Win32OSSD_InvalidateSD");
       
   651     wsdo->invalid = JNI_TRUE;
       
   652 }
       
   653 
       
   654 /*
       
   655  * Class:     sun_java2d_windows_Win32OffScreenSurfaceData
       
   656  * Method:    invalidateSD
       
   657  * Signature: ()V
       
   658  */
       
   659 JNIEXPORT void JNICALL
       
   660 Java_sun_java2d_windows_Win32OffScreenSurfaceData_nativeInvalidate(JNIEnv *env,
       
   661                                                                    jobject wsd)
       
   662 {
       
   663     J2dTraceLn(J2D_TRACE_INFO, "Win32OffScreenSurfaceData_nativeInvalidate");
       
   664     Win32SDOps *wsdo = (Win32SDOps *)SurfaceData_GetOps(env, wsd);
       
   665     if (wsdo != NULL) {
       
   666         wsdo->InvalidateSD(env, wsdo);
       
   667     }
       
   668 }
       
   669 
       
   670 
       
   671 /*
       
   672  * Method:    Win32OSSD_Dispose
       
   673  */
       
   674 void
       
   675 Win32OSSD_Dispose(JNIEnv *env, SurfaceDataOps *ops)
       
   676 {
       
   677     Win32SDOps *wsdo = (Win32SDOps*)ops;
       
   678     J2dTraceLn2(J2D_TRACE_VERBOSE, "Win32OSSD_Dispose vram=0%x sysm=0%x",
       
   679                 wsdo->surfacePuntData.lpSurfaceVram,
       
   680                 wsdo->surfacePuntData.lpSurfaceSystem);
       
   681     // REMIND: Need to delete a lot of other things here as well, starting
       
   682     // with the offscreen surface
       
   683 
       
   684     // ops is assumed non-null as it is checked in SurfaceData_DisposeOps
       
   685     if (wsdo->surfacePuntData.lpSurfaceVram) {
       
   686         delete wsdo->surfacePuntData.lpSurfaceVram;
       
   687     }
       
   688     if (wsdo->surfacePuntData.lpSurfaceSystem) {
       
   689         delete wsdo->surfacePuntData.lpSurfaceSystem;
       
   690     }
       
   691     if (wsdo->brush != NULL) {
       
   692         wsdo->brush->Release();
       
   693     }
       
   694     if (wsdo->pen != NULL) {
       
   695         wsdo->pen->Release();
       
   696     }
       
   697     wsdo->lpSurface = NULL;
       
   698     disposeOSSD_WSDO(env, wsdo);
       
   699 }
       
   700 
       
   701 JNIEXPORT void JNICALL
       
   702 Java_sun_java2d_windows_Win32OffScreenSurfaceData_setTransparentPixel(JNIEnv *env,
       
   703                                                                       jobject wsd,
       
   704                                                                       jint pixel)
       
   705 {
       
   706     Win32SDOps *wsdo = (Win32SDOps *)SurfaceData_GetOps(env, wsd);
       
   707     DDSetColorKey(env, wsdo, pixel);
       
   708 }
       
   709 
       
   710 /*
       
   711  * Class:     sun_java2d_windows_Win32OffScreenSurfaceData
       
   712  * Method:    flush
       
   713  * Signature: ()V
       
   714  */
       
   715 JNIEXPORT void JNICALL
       
   716 Java_sun_java2d_windows_Win32OffScreenSurfaceData_flush(JNIEnv *env,
       
   717                                                         jobject wsd)
       
   718 {
       
   719     J2dTraceLn(J2D_TRACE_INFO, "Win32OffScreenSurfaceData_flush");
       
   720     Win32SDOps *wsdo = (Win32SDOps *)SurfaceData_GetOps(env, wsd);
       
   721     if (wsdo != NULL) {
       
   722         // Note that wsdo may be null if there was some error during
       
   723         // construction, such as a surface depth we could not handle
       
   724         DDReleaseSurfaceMemory(wsdo->surfacePuntData.lpSurfaceSystem);
       
   725         DDReleaseSurfaceMemory(wsdo->surfacePuntData.lpSurfaceVram);
       
   726     }
       
   727 }