jdk/src/windows/native/sun/java2d/d3d/D3DUtils.cpp
changeset 930 2f703334f63f
parent 929 d958f883b42a
parent 923 e9301d8f49ef
child 932 2aabadbd9e85
equal deleted inserted replaced
929:d958f883b42a 930:2f703334f63f
     1 /*
       
     2  * Copyright 2005-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 
       
    27 #include "ddrawUtils.h"
       
    28 #include "D3DUtils.h"
       
    29 #include "D3DSurfaceData.h"
       
    30 
       
    31 #ifdef DEBUG
       
    32 // These strings must be in the same order as pixel
       
    33 // formats in D3DSurfaceData.java
       
    34 char * TR_NAMES[] = {
       
    35     "TR_OPAQUE",
       
    36     "TR_BITMASK",
       
    37     "TR_TRANSLUCENT"
       
    38 };
       
    39 
       
    40 char * PF_NAMES[] = {
       
    41     "PF_INVALID" ,
       
    42     "PF_INT_ARGB" ,
       
    43     "PF_INT_RGB" ,
       
    44     "PF_INT_RGBX",
       
    45     "PF_INT_BGR" ,
       
    46     "PF_USHORT_565_RGB" ,
       
    47     "PF_USHORT_555_RGB" ,
       
    48     "PF_USHORT_555_RGBX" ,
       
    49     "PF_INT_ARGB_PRE" ,
       
    50     "PF_USHORT_4444_ARGB"
       
    51 };
       
    52 #endif // DEBUG
       
    53 
       
    54 /**
       
    55  * This structure could be used when searching for a pixel
       
    56  * format with preferred bit depth.
       
    57  */
       
    58 typedef struct {
       
    59     // Pointer to a DDPIXELFORMAT structure where the found pixel
       
    60     // format will be copied to
       
    61     DDPIXELFORMAT *pddpf;
       
    62     // If TRUE, the search was successful, FALSE otherwise
       
    63     BOOL bFoundFormat;
       
    64     // Preferred bit depth
       
    65     int preferredDepth;
       
    66 } PixelFormatSearchStruct;
       
    67 
       
    68 jint D3DUtils_GetPixelFormatType(DDPIXELFORMAT*lpddpf);
       
    69 
       
    70 HRESULT WINAPI EnumAlphaTextureFormatsCallback(DDPIXELFORMAT* pddpf,
       
    71                                                VOID* pContext )
       
    72 {
       
    73     J2dTraceLn(J2D_TRACE_VERBOSE, "EnumAlphaTextureFormatsCallback");
       
    74     DDPIXELFORMAT* pddpfOut = (DDPIXELFORMAT*)pContext;
       
    75 
       
    76     // Looking for a 8-bit luminance texture (and probably not alpha-luminance)
       
    77     if((pddpf->dwFlags & DDPF_ALPHA) && (pddpf->dwAlphaBitDepth == 8))
       
    78     {
       
    79         memcpy(pddpfOut, pddpf, sizeof(DDPIXELFORMAT));
       
    80         return D3DENUMRET_CANCEL;
       
    81     }
       
    82 
       
    83     return D3DENUMRET_OK;
       
    84 }
       
    85 
       
    86 HRESULT CALLBACK
       
    87 D3DUtils_TextureSearchCallback(DDPIXELFORMAT *lpddpf,
       
    88                                void *param)
       
    89 {
       
    90     J2dTraceLn(J2D_TRACE_VERBOSE, "D3DUtils_TextureSearchCallback");
       
    91     jint pfType = D3DUtils_GetPixelFormatType(lpddpf);
       
    92     if (pfType == PF_INVALID) {
       
    93         return DDENUMRET_OK;
       
    94     }
       
    95 
       
    96     DWORD dwAlphaBitCount = 0;
       
    97     if (lpddpf->dwFlags & DDPF_ALPHAPIXELS) {
       
    98         DWORD dwMask = lpddpf->dwRGBAlphaBitMask;
       
    99         while( dwMask ) {
       
   100             dwMask = dwMask & ( dwMask - 1 );
       
   101             dwAlphaBitCount++;
       
   102         }
       
   103     }
       
   104 
       
   105     DWORD dwRGBBitCount = lpddpf->dwRGBBitCount;
       
   106     WORD wDepthIndex = D3D_DEPTH_IDX(dwRGBBitCount);
       
   107     WORD wTransparencyIndex =
       
   108         dwAlphaBitCount > 0 ? TR_TRANSLUCENT_IDX : TR_OPAQUE_IDX;
       
   109 
       
   110     D3DTextureTable *table = (D3DTextureTable*)param;
       
   111     D3DTextureTableCell *cell = &(*table)[wTransparencyIndex][wDepthIndex];
       
   112     if (cell->pfType == PF_INVALID || pfType < cell->pfType) {
       
   113         // set only if it wasn't set or if current pfType is better than
       
   114         // the one found previously: it's better to use 565 than 555
       
   115         memcpy(&cell->pddpf, lpddpf, sizeof(DDPIXELFORMAT));
       
   116         cell->pfType = pfType;
       
   117     }
       
   118     // continue for all pixel formats
       
   119     return DDENUMRET_OK;
       
   120 }
       
   121 
       
   122 HRESULT
       
   123 WINAPI EnumZBufferFormatsCallback(DDPIXELFORMAT* pddpf,
       
   124                                   VOID* pContext )
       
   125 {
       
   126     J2dTraceLn(J2D_TRACE_VERBOSE, "EnumZBufferFormatsCallback");
       
   127     PixelFormatSearchStruct *ppfss = (PixelFormatSearchStruct*)pContext;
       
   128     DDPIXELFORMAT* pddpfOut = ppfss->pddpf;
       
   129 
       
   130     // if found a format with the exact depth, return it
       
   131     if (pddpf->dwZBufferBitDepth == (DWORD)ppfss->preferredDepth) {
       
   132         ppfss->bFoundFormat = TRUE;
       
   133         memcpy(pddpfOut, pddpf, sizeof(DDPIXELFORMAT));
       
   134         return D3DENUMRET_CANCEL;
       
   135     }
       
   136     // If a format with exact depth can't be found, look for the best
       
   137     // available, preferring those with the lowest bit depth to save
       
   138     // video memory. Also, prefer formats with no stencil bits.
       
   139     if (!ppfss->bFoundFormat ||
       
   140         (pddpfOut->dwZBufferBitDepth > pddpf->dwZBufferBitDepth &&
       
   141          !(pddpf->dwFlags & DDPF_STENCILBUFFER)))
       
   142     {
       
   143         ppfss->bFoundFormat = TRUE;
       
   144         memcpy(pddpfOut, pddpf, sizeof(DDPIXELFORMAT));
       
   145     }
       
   146 
       
   147     return D3DENUMRET_OK;
       
   148 }
       
   149 
       
   150 HRESULT
       
   151 WINAPI DeviceEnumCallback(LPSTR strDesc, LPSTR strName,
       
   152                           LPD3DDEVICEDESC7 pDesc,
       
   153                           LPVOID pParentInfo)
       
   154 {
       
   155     J2dTraceLn(J2D_TRACE_VERBOSE, "DeviceEnumCallback");
       
   156     DEVICES_INFO *devinfo = (DEVICES_INFO*)pParentInfo;
       
   157 
       
   158     if (pDesc->deviceGUID == IID_IDirect3DHALDevice) {
       
   159         devinfo->pGUIDs[HAL_IDX] = &IID_IDirect3DHALDevice;
       
   160     } else if (pDesc->deviceGUID == IID_IDirect3DTnLHalDevice) {
       
   161         devinfo->pGUIDs[TNL_IDX] = &IID_IDirect3DTnLHalDevice;
       
   162     } else if (pDesc->deviceGUID == IID_IDirect3DRGBDevice) {
       
   163         devinfo->pGUIDs[RGB_IDX] = &IID_IDirect3DRGBDevice;
       
   164     } else if (pDesc->deviceGUID == IID_IDirect3DRefDevice) {
       
   165         devinfo->pGUIDs[REF_IDX] = &IID_IDirect3DRefDevice;
       
   166     }
       
   167     return D3DENUMRET_OK;
       
   168 }
       
   169 
       
   170 HRESULT
       
   171 D3DUtils_FindMaskTileTextureFormat(IDirect3DDevice7 *d3dDevice,
       
   172                                    DDPIXELFORMAT* pddpf)
       
   173 {
       
   174     J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_FindMaskTileTextureFormat");
       
   175     d3dDevice->EnumTextureFormats(EnumAlphaTextureFormatsCallback,
       
   176                                   (void*)pddpf);
       
   177     if (pddpf->dwAlphaBitDepth == 8) {
       
   178         return D3D_OK;
       
   179     }
       
   180     return DDERR_GENERIC;
       
   181 }
       
   182 
       
   183 HRESULT
       
   184 D3DUtils_FindDepthBufferFormat(IDirect3D7 *d3dObject,
       
   185                                int preferredDepth,
       
   186                                DDPIXELFORMAT* pddpf,
       
   187                                const GUID *pDeviceGUID)
       
   188 {
       
   189     J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_FindDepthBufferFormat");
       
   190     PixelFormatSearchStruct pfss;
       
   191     pfss.pddpf = pddpf;
       
   192     pfss.bFoundFormat = FALSE;
       
   193     pfss.preferredDepth = preferredDepth;
       
   194 
       
   195     d3dObject->EnumZBufferFormats(*pDeviceGUID,
       
   196                                   EnumZBufferFormatsCallback,
       
   197                                   (void*)&pfss);
       
   198 
       
   199     return pfss.bFoundFormat ? D3D_OK : DDERR_GENERIC;
       
   200 }
       
   201 
       
   202 jint D3DUtils_GetPixelFormatType(DDPIXELFORMAT*lpddpf)
       
   203 {
       
   204     J2dTraceLn(J2D_TRACE_VERBOSE, "D3DUtils_GetPixelFormatType");
       
   205 
       
   206     if (lpddpf == NULL) return PF_INVALID;
       
   207 
       
   208     DWORD dwFlags = lpddpf->dwFlags;
       
   209     // skip weird formats
       
   210     if (lpddpf->dwRGBBitCount < 16   ||
       
   211         dwFlags & DDPF_ALPHA         || dwFlags & DDPF_ZBUFFER       ||
       
   212         dwFlags & DDPF_ZPIXELS       || dwFlags & DDPF_LUMINANCE     ||
       
   213         dwFlags & DDPF_FOURCC        || dwFlags & DDPF_STENCILBUFFER ||
       
   214         dwFlags & DDPF_BUMPLUMINANCE || dwFlags & DDPF_BUMPDUDV)
       
   215     {
       
   216         return PF_INVALID;
       
   217     }
       
   218 
       
   219     jint pfType = PF_INVALID;
       
   220     DWORD aMask = lpddpf->dwRGBAlphaBitMask;
       
   221     DWORD rMask = lpddpf->dwRBitMask;
       
   222     DWORD gMask = lpddpf->dwGBitMask;
       
   223     DWORD bMask = lpddpf->dwBBitMask;
       
   224 
       
   225     if (rMask == 0x0000f800 &&
       
   226         gMask == 0x000007e0 &&
       
   227         bMask == 0x0000001f &&
       
   228         aMask == 0x00000000)
       
   229     {
       
   230         pfType = PF_USHORT_565_RGB;
       
   231     } else if (rMask == 0x00007C00 &&
       
   232                gMask == 0x000003E0 &&
       
   233                bMask == 0x0000001f &&
       
   234                aMask == 0x00000000)
       
   235     {
       
   236         pfType = PF_USHORT_555_RGB;
       
   237     } else if (rMask == 0x00000f00 &&
       
   238                gMask == 0x000000f0 &&
       
   239                bMask == 0x0000000f &&
       
   240                aMask == 0x0000f000)
       
   241     {
       
   242         // REMIND: we currently don't support this
       
   243         // pixel format, since we don't have the loops for a
       
   244         // premultiplied version of it. So we'll just use INT_ARGB
       
   245         // for now
       
   246         pfType = PF_INVALID;
       
   247         // pfType = PF_USHORT_4444_ARGB;
       
   248     } else if (rMask == 0x00ff0000 &&
       
   249                gMask == 0x0000ff00 &&
       
   250                bMask == 0x000000ff)
       
   251     {
       
   252         if (lpddpf->dwRGBBitCount == 32) {
       
   253             pfType = (dwFlags & DDPF_ALPHAPIXELS) ?
       
   254                 PF_INT_ARGB : PF_INT_RGB;
       
   255         } else {
       
   256             // We currently don't support this format.
       
   257             // pfType = PF_3BYTE_BGR;
       
   258             pfType = PF_INVALID;
       
   259         }
       
   260     }
       
   261 
       
   262     return pfType;
       
   263 }
       
   264 
       
   265 void
       
   266 D3DUtils_SetupTextureFormats(IDirect3DDevice7 *d3dDevice,
       
   267                              D3DTextureTable &table)
       
   268 {
       
   269     J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_SetupTextureFormats");
       
   270     if (d3dDevice == NULL || table == NULL) {
       
   271         return;
       
   272     }
       
   273 
       
   274     ZeroMemory(table, sizeof(D3DTextureTable));
       
   275     int t;
       
   276     for (t = TR_OPAQUE_IDX; t < TR_MAX_IDX; t++) {
       
   277         for (int d = DEPTH16_IDX; d < DEPTH_MAX_IDX; d++) {
       
   278             table[t][d].pfType = PF_INVALID;
       
   279         }
       
   280     }
       
   281     d3dDevice->EnumTextureFormats(D3DUtils_TextureSearchCallback, table);
       
   282 
       
   283     // We've retrieved the pixel formats for this device. The matrix may
       
   284     // look something like this, depending on the formats the device supports:
       
   285     // Transparency/Depth        Depth 16            Depth 24          Depth 32
       
   286     // ------------------------------------------------------------------------
       
   287     //      TR_OPAQUE   PF_USHORT_565_RGB          PF_INVALID        PF_INT_RGB
       
   288     //     TR_BITMASK          PF_INVALID          PF_INVALID        PF_INVALID
       
   289     // TR_TRANSLUCENT          PF_INVALID          PF_INVALID       PF_INT_ARGB
       
   290 
       
   291 
       
   292     // we'll be using translucent pixel formats for bitmask images
       
   293     // for now, this may change later
       
   294     memcpy(&table[TR_BITMASK_IDX], &table[TR_TRANSLUCENT_IDX],
       
   295            sizeof(D3DTextureTableCell[DEPTH_MAX_IDX]));
       
   296     // Transparency/Depth        Depth 16            Depth 24          Depth 32
       
   297     // ------------------------------------------------------------------------
       
   298     //      TR_OPAQUE   PF_USHORT_565_RGB          PF_INVALID        PF_INT_RGB
       
   299     //     TR_BITMASK          PF_INVALID          PF_INVALID       PF_INT_ARGB
       
   300     // TR_TRANSLUCENT          PF_INVALID          PF_INVALID       PF_INT_ARGB
       
   301 
       
   302     // REMIND: crude force
       
   303     // Find substitutes for pixel formats which we didn't find.
       
   304     // For example, if we didn't find a 24-bit format, 32-bit will be
       
   305     // a first choice for substitution. But if it wasn't found either,
       
   306     // then use 16-bit format
       
   307     D3DTextureTableCell *cell16, *cell24, *cell32;
       
   308     for (t = TR_OPAQUE_IDX; t < TR_MAX_IDX; t++) {
       
   309         cell16 = &table[t][DEPTH16_IDX];
       
   310         cell24 = &table[t][DEPTH24_IDX];
       
   311         cell32 = &table[t][DEPTH32_IDX];
       
   312         if (cell32->pfType == PF_INVALID) {
       
   313             if (cell24->pfType != PF_INVALID) {
       
   314                 memcpy(cell32, cell24, sizeof(D3DTextureTableCell));
       
   315             } else if (cell16->pfType != PF_INVALID) {
       
   316                 memcpy(cell32, cell16, sizeof(D3DTextureTableCell));
       
   317             } else {
       
   318                 // no valid pixel formats for this transparency
       
   319                 // type were found
       
   320                 continue;
       
   321             }
       
   322         }
       
   323         // now we know that 32-bit is valid
       
   324         if (cell24->pfType == PF_INVALID) {
       
   325             // use 32-bit format as a substitution for 24-bit
       
   326             memcpy(cell24, cell32, sizeof(D3DTextureTableCell));
       
   327         }
       
   328         // now we know that 32- and 24-bit are valid
       
   329         if (cell16->pfType == PF_INVALID) {
       
   330             // use 24-bit format as a substitution for 16-bit
       
   331             memcpy(cell16, cell24, sizeof(D3DTextureTableCell));
       
   332         }
       
   333     }
       
   334     // After this loop the matrix may look something like this:
       
   335     // Transparency/Depth        Depth 16            Depth 24          Depth 32
       
   336     // ------------------------------------------------------------------------
       
   337     //      TR_OPAQUE   PF_USHORT_565_RGB          PF_INT_RGB        PF_INT_RGB
       
   338     //     TR_BITMASK         PF_INT_ARGB         PF_INT_ARGB       PF_INT_ARGB
       
   339     // TR_TRANSLUCENT         PF_INT_ARGB         PF_INT_ARGB       PF_INT_ARGB
       
   340 
       
   341 #ifdef DEBUG
       
   342     // Print out the matrix (should look something like the comment above)
       
   343     J2dTraceLn1(J2D_TRACE_INFO,
       
   344                 "Texutre formats table for device %x", d3dDevice);
       
   345     J2dTraceLn(J2D_TRACE_INFO, "Transparency/Depth     Depth 16            "\
       
   346                "Depth 24            Depth 32");
       
   347     J2dTraceLn(J2D_TRACE_INFO, "-------------------------------------------"\
       
   348                "----------------------------");
       
   349     for (t = TR_OPAQUE_IDX; t < TR_MAX_IDX; t++) {
       
   350         J2dTrace1(J2D_TRACE_INFO, "%15s", TR_NAMES[t]);
       
   351         for (int d = DEPTH16_IDX; d < DEPTH_MAX_IDX; d++) {
       
   352             J2dTrace1(J2D_TRACE_INFO, "%20s",
       
   353                       PF_NAMES[table[t][d].pfType]);
       
   354         }
       
   355         J2dTrace(J2D_TRACE_INFO, "\n");
       
   356     }
       
   357 #endif // DEBUG
       
   358 }
       
   359 
       
   360 const GUID *
       
   361 D3DUtils_SelectDeviceGUID(IDirect3D7 *d3dObject)
       
   362 {
       
   363     static char * RASTERIZER_NAMES[] = {
       
   364         "TNL", "HAL", "REFERENCE", "RGB"
       
   365     };
       
   366     // try to use TnL rasterizer by default
       
   367     int defIndex = TNL_IDX;
       
   368 
       
   369     J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_SelectDeviceGUID");
       
   370     // unless a different one was requested
       
   371     char *pRasterizer = getenv("J2D_D3D_RASTERIZER");
       
   372     if (pRasterizer != NULL) {
       
   373         if (strncmp(pRasterizer, "ref", 3) == 0) {
       
   374             defIndex = REF_IDX;
       
   375         } else if (strncmp(pRasterizer, "rgb", 3) == 0) {
       
   376             defIndex = RGB_IDX;
       
   377         } else if (strncmp(pRasterizer, "hal", 3) == 0) {
       
   378             defIndex = HAL_IDX;
       
   379         } else if (strncmp(pRasterizer, "tnl", 3) == 0) {
       
   380             defIndex = TNL_IDX;
       
   381         }
       
   382         J2dTraceLn1(J2D_TRACE_VERBOSE,
       
   383                     "  rasterizer requested: %s",
       
   384                     RASTERIZER_NAMES[defIndex]);
       
   385     }
       
   386 
       
   387     DEVICES_INFO devInfo;
       
   388     memset(&devInfo, 0, sizeof(devInfo));
       
   389     HRESULT res;
       
   390     if (FAILED(res = d3dObject->EnumDevices(DeviceEnumCallback,
       
   391                                             (VOID*)&devInfo)))
       
   392     {
       
   393         DebugPrintDirectDrawError(res, "D3DUtils_SelectDeviceGUID: "\
       
   394                                   "EnumDevices failed");
       
   395         return NULL;
       
   396     }
       
   397 
       
   398     // return requested rasterizer's guid if it's present
       
   399     if (devInfo.pGUIDs[defIndex] != NULL) {
       
   400         J2dRlsTraceLn1(J2D_TRACE_VERBOSE,
       
   401                        "D3DUtils_SelectDeviceGUID: using %s rasterizer",
       
   402                        RASTERIZER_NAMES[defIndex]);
       
   403         return devInfo.pGUIDs[defIndex];
       
   404     }
       
   405     // if not, try to find one, starting with the best available
       
   406     defIndex = TNL_IDX;
       
   407     do {
       
   408         if (devInfo.pGUIDs[defIndex] != NULL) {
       
   409             J2dRlsTraceLn1(J2D_TRACE_VERBOSE,
       
   410                            "D3DUtils_SelectDeviceGUID: using %s rasterizer",
       
   411                            RASTERIZER_NAMES[defIndex]);
       
   412             return devInfo.pGUIDs[defIndex];
       
   413         }
       
   414         // While we could use the rgb and ref rasterizers if tnl and
       
   415         // hal aren't present, it's not practical for performance purposes.
       
   416         // so we just leave an opportunity to force them.
       
   417     } while (++defIndex < REF_IDX /*DEV_IDX_MAX*/);
       
   418 
       
   419 
       
   420     J2dRlsTraceLn(J2D_TRACE_ERROR,
       
   421                   "D3DUtils_SelectDeviceGUID: "\
       
   422                   "No Accelerated Rasterizers Found");
       
   423     return NULL;
       
   424 }
       
   425 
       
   426 
       
   427 /*
       
   428  * This function sets passed matrix to be a custom left-hand off-center
       
   429  * orthogonal matrix. The output is identical to D3DX's function call
       
   430  * D3DXMatrixOrthoOffCenterLH((D3DXMATRIX*)&tx,
       
   431  *                            0.0, width, height, 0.0, -1.0, 1.0);
       
   432  */
       
   433 void
       
   434 D3DUtils_SetOrthoMatrixOffCenterLH(D3DMATRIX *m,
       
   435                                    float width, float height)
       
   436 {
       
   437     DASSERT((m != NULL) && (width > 0.0f) && (height > 0.0f));
       
   438     memset(m, 0, sizeof(D3DMATRIX));
       
   439     m->_11 =  2.0f/width;
       
   440     m->_22 = -2.0f/height;
       
   441     m->_33 =  0.5f;
       
   442     m->_44 =  1.0f;
       
   443 
       
   444     m->_41 = -1.0f;
       
   445     m->_42 =  1.0f;
       
   446     m->_43 =  0.5f;
       
   447 }
       
   448 
       
   449 void
       
   450 D3DUtils_SetIdentityMatrix(D3DMATRIX *m, BOOL adjust)
       
   451 {
       
   452     DASSERT(m != NULL);
       
   453     m->_12 = m->_13 = m->_14 = m->_21 = m->_23 = m->_24 = 0.0f;
       
   454     m->_31 = m->_32 = m->_34 = m->_43 = 0.0f;
       
   455     m->_11 = m->_22 = m->_33 = m->_44 = 1.0f;
       
   456     if (adjust) {
       
   457         // This is required for proper texel alignment
       
   458         m->_41 = m->_42 = -0.5f;
       
   459     } else {
       
   460         m->_41 = m->_42 = 0.0f;
       
   461     }
       
   462 }
       
   463 
       
   464 DDrawSurface *
       
   465 D3DUtils_CreatePlainSurface(JNIEnv *env,
       
   466                             DDraw *ddObject,
       
   467                             D3DContext *d3dContext,
       
   468                             int w, int h)
       
   469 {
       
   470     DXSurface *dxSurface;
       
   471     jint pType;
       
   472     J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_CreatePlainSurface");
       
   473     if (FAILED(d3dContext->CreateSurface(env, w, h, 32,
       
   474                                          TR_OPAQUE, D3D_PLAIN_SURFACE,
       
   475                                          &dxSurface, &pType)))
       
   476     {
       
   477         return NULL;
       
   478     }
       
   479     return new DDrawSurface(ddObject, dxSurface);
       
   480 }
       
   481 
       
   482 DDrawSurface *
       
   483 D3DUtils_CreateTexture(JNIEnv *env,
       
   484                        DDraw *ddObject,
       
   485                        D3DContext *d3dContext,
       
   486                        int transparency,
       
   487                        int w, int h)
       
   488 {
       
   489     J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_CreateTexture");
       
   490     DXSurface *dxSurface;
       
   491     jint pType;
       
   492     if (FAILED(d3dContext->CreateSurface(env, w, h, 32,
       
   493                                          transparency, D3D_TEXTURE_SURFACE,
       
   494                                          &dxSurface, &pType)))
       
   495     {
       
   496         return NULL;
       
   497     }
       
   498     return new DDrawSurface(ddObject, dxSurface);
       
   499 }
       
   500 
       
   501 HRESULT
       
   502 D3DUtils_UploadIntImageToXRGBTexture(DDrawSurface *lpTexture,
       
   503                                      int *pSrc, int width, int height)
       
   504 {
       
   505     HRESULT res;
       
   506     int texW = lpTexture->GetDXSurface()->GetWidth();
       
   507     int texH = lpTexture->GetDXSurface()->GetHeight();
       
   508     int srcStride = width * 4;
       
   509 
       
   510     J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_UploadIntImageToXRGBTexture");
       
   511     if (width > texW) {
       
   512         width = texW;
       
   513     }
       
   514     if (height > texH) {
       
   515         height = texH;
       
   516     }
       
   517 
       
   518     SurfaceDataRasInfo rasInfo;
       
   519     if (SUCCEEDED(res = lpTexture->Lock(NULL, &rasInfo,
       
   520                                         DDLOCK_WAIT|DDLOCK_NOSYSLOCK, NULL)))
       
   521     {
       
   522         void *pDstPixels = rasInfo.rasBase;
       
   523         void *pSrcPixels = (void*)pSrc;
       
   524 
       
   525         // REMIND: clear the dest first
       
   526         memset(pDstPixels, 0, texH * rasInfo.scanStride);
       
   527         do {
       
   528             memcpy(pDstPixels, pSrcPixels, width * 4);
       
   529             pSrcPixels = PtrAddBytes(pSrcPixels, srcStride);
       
   530             pDstPixels = PtrAddBytes(pDstPixels, rasInfo.scanStride);
       
   531         } while (--height > 0);
       
   532         res = lpTexture->Unlock(NULL);
       
   533     }
       
   534     return res;
       
   535 }
       
   536 
       
   537 HRESULT
       
   538 D3DUtils_CheckD3DCaps(LPD3DDEVICEDESC7 lpDesc7)
       
   539 {
       
   540     // The device must support fast rasterization
       
   541     static DWORD dwDevCaps =
       
   542         (D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_HWRASTERIZATION);
       
   543     BOOL vt = lpDesc7->dwDevCaps & D3DDEVCAPS_DRAWPRIMTLVERTEX;
       
   544     BOOL rz = lpDesc7->dwDevCaps & D3DDEVCAPS_HWRASTERIZATION;
       
   545 
       
   546     J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_CheckD3DCaps");
       
   547     return (lpDesc7->dwDevCaps & dwDevCaps) ?
       
   548         D3D_OK :
       
   549         DDERR_GENERIC;
       
   550 }
       
   551 
       
   552 HRESULT
       
   553 D3DUtils_CheckTextureCaps(LPD3DDEVICEDESC7 lpDesc7)
       
   554 {
       
   555     J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_CheckTextureCaps");
       
   556     // REMIND: we should really check both Tri and Lin caps,
       
   557     // but hopefully we won't be using line strips soon
       
   558     LPD3DPRIMCAPS lpDpcTriCaps = &lpDesc7->dpcTriCaps;
       
   559     // Filtering requirements
       
   560     static DWORD dwFilterCaps =
       
   561         (D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_NEAREST);
       
   562     // Check for caps used for alpha compositing (implementation of
       
   563     // Porter-Duff rules)
       
   564     static DWORD dwBlendCaps =
       
   565         (D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE |
       
   566          D3DPBLENDCAPS_SRCALPHA  | D3DPBLENDCAPS_INVSRCALPHA |
       
   567          D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA);
       
   568 
       
   569     if ((lpDesc7->dwTextureOpCaps & D3DTEXOPCAPS_MODULATE) &&
       
   570         (lpDpcTriCaps->dwTextureFilterCaps & dwFilterCaps) &&
       
   571         (lpDpcTriCaps->dwSrcBlendCaps  & dwBlendCaps) &&
       
   572         (lpDpcTriCaps->dwDestBlendCaps & dwBlendCaps))
       
   573     {
       
   574         return D3D_OK;
       
   575     }
       
   576     return DDERR_GENERIC;
       
   577 }
       
   578 
       
   579 HRESULT
       
   580 D3DUtils_CheckDeviceCaps(LPD3DDEVICEDESC7 lpDesc7) {
       
   581     J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_CheckDeviceCaps");
       
   582     if (SUCCEEDED(D3DUtils_CheckD3DCaps(lpDesc7)) &&
       
   583         SUCCEEDED(D3DUtils_CheckTextureCaps(lpDesc7)) &&
       
   584         SUCCEEDED(D3DUtils_CheckDepthCaps(lpDesc7)))
       
   585     {
       
   586         return D3D_OK;
       
   587     }
       
   588     return DDERR_GENERIC;
       
   589 }
       
   590 
       
   591 HRESULT
       
   592 D3DUtils_CheckDepthCaps(LPD3DDEVICEDESC7 lpDesc7)
       
   593 {
       
   594     J2dTraceLn(J2D_TRACE_INFO, "D3DUtils_CheckDepthCaps");
       
   595     // Check for required depth-buffer operations
       
   596     // (see D3DContext::SetClip() for more info).
       
   597     static DWORD dwZCmpCaps = (D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_LESS);
       
   598     // D3DPMISCCAPS_MASKZ capability allows enabling/disabling
       
   599     // depth buffer updates.
       
   600     if ((lpDesc7->dpcTriCaps.dwMiscCaps & D3DPMISCCAPS_MASKZ) &&
       
   601         (lpDesc7->dpcTriCaps.dwZCmpCaps & dwZCmpCaps))
       
   602     {
       
   603         return D3D_OK;
       
   604     }
       
   605     return DDERR_GENERIC;
       
   606 }