Main Page | Alphabetical List | Compound List | File List | Compound Members | File Members

dmodes.c

Go to the documentation of this file.
00001 /****************************************************************************************/
00002 /*  dmodes.c                                                                            */
00003 /*                                                                                      */
00004 /*  Author:       Ken Baird                                                             */
00005 /*  Description:  Directdraw related stuff                                              */
00006 /*                                                                                      */
00007 /*  The contents of this file are subject to the Genesis3D Public License               */
00008 /*  Version 1.01 (the "License"); you may not use this file except in                   */
00009 /*  compliance with the License. You may obtain a copy of the License at                */
00010 /*  http://www.genesis3d.com                                                            */
00011 /*                                                                                      */
00012 /*  Software distributed under the License is distributed on an "AS IS"                 */
00013 /*  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See                */
00014 /*  the License for the specific language governing rights and limitations              */
00015 /*  under the License.                                                                  */
00016 /*                                                                                      */
00017 /*  The Original Code is Genesis3D, released March 25, 1999.                            */
00018 /*Genesis3D Version 1.1 released November 15, 1999                            */
00019 /*  Copyright (C) 1999 WildTangent, Inc. All Rights Reserved           */
00020 /*                                                                                      */
00021 /****************************************************************************************/
00022 #define INITGUID
00023 #include <windows.h>
00024 #include "softdrv.h"
00025 #include "ddraw.h"
00026 #include <stdio.h>
00027 
00028 LPDIRECTDRAW                    lpDD;                   // DirectDraw object
00029 LPDIRECTDRAW4                   lpDD4;
00030 LPDIRECTDRAWSURFACE4    lpDDSPrimary;   // DirectDraw primary surface
00031 LPDIRECTDRAWSURFACE4    lpDDSBack;              // DirectDraw back surface
00032 BOOL                                    bActive         =TRUE;
00033 BOOL                                    bInitDone       =FALSE;
00034 BOOL                                    bWindowed       =FALSE;
00035 HWND                                    mhWnd           =NULL;
00036 static BOOL                             bDMA            =FALSE;
00037 static BOOL                             bHardBlt        =FALSE;
00038 static BOOL                             bDMAPageLock=FALSE;
00039 BOOL                                    bBackLocked     =FALSE;
00040 #ifdef STRICT
00041 WNDPROC                                 pOldWndProc;
00042 #else
00043 FARPROC                                 pOldWndProc;
00044 #endif
00045 HINSTANCE                               ddrawinst;
00046 
00047 typedef HRESULT (WINAPI *LPDIRECTDRAWCREATE)( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter );
00048 
00049 extern  int     NumDevices;
00050 typedef struct DecalDelayTag
00051 {
00052         LPDIRECTDRAWSURFACE4    surf;
00053         RECT                                    srect;
00054         S32                                             x;
00055         S32                                             y;
00056 }       DecalDelay;
00057 
00058 static  DecalDelay      DecalQ[8192];
00059 static  int                     NumDecalsQd;
00060 char* MyErrorToString(HRESULT error);
00061 
00062 //these statics must be eliminated soon
00063 static  int CurrentModeWidth, CurrentModeHeight, CurrentModeDepth;
00064 
00065 
00066 BOOL    WINAPI  DDrawDriverEnumCallbackEx(GUID *pGUID, LPSTR pDescription, LPSTR pName, LPVOID pContext, HMONITOR hm)
00067 {
00068         LPDIRECTDRAWCREATE      lpDDCreate;
00069         LPDIRECTDRAW            pDD;
00070         LPDIRECTDRAW4           pDD4    =NULL;
00071         HRESULT                         hRet;
00072         VidEnumInfo                     *vinfo  =&((VidEnumInfo *)pContext)[NumDevices];
00073         
00074         ddrawinst       =LoadLibrary("ddraw.dll");
00075 
00076         if(!ddrawinst)
00077         {
00078                 return  DDENUMRET_CANCEL;
00079         }
00080 
00081         lpDDCreate      =(LPDIRECTDRAWCREATE)GetProcAddress(ddrawinst, "DirectDrawCreate");
00082         if(lpDDCreate)
00083         {
00084                 hRet    =lpDDCreate(NULL, &pDD, NULL);
00085         }
00086         else
00087         {
00088                 return  DDENUMRET_CANCEL;
00089         }
00090         vinfo->DeviceGuid       =pGUID;
00091         
00092         if(hRet != DD_OK)
00093         {
00094                 ErrorPrintf("DirectDrawCreate FAILED : DDrawDriverEnumCallbackEx\n");
00095                 return  DDENUMRET_CANCEL;
00096         }
00097 
00098         hRet    =pDD->lpVtbl->QueryInterface(pDD, &IID_IDirectDraw4, (LPVOID *)&pDD4);
00099         if(hRet != DD_OK)
00100         {
00101                 ErrorPrintf("QueryInterface FAILED : DDrawDriverEnumCallbackEx\n");
00102                 return  DDENUMRET_CANCEL;
00103         }
00104         
00105         hRet    =pDD4->lpVtbl->GetDeviceIdentifier(pDD4, &vinfo->DeviceInfo,0);
00106         hRet    =pDD4->lpVtbl->GetDeviceIdentifier(pDD4, &vinfo->DeviceInfoHost, DDGDI_GETHOSTIDENTIFIER);
00107         
00108         if(pDD4)
00109         {
00110                 pDD4->lpVtbl->Release(pDD4);
00111         }
00112 
00113         FreeLibrary(ddrawinst);
00114         
00115         if(NumDevices < 16)
00116         {
00117                 NumDevices++;
00118         }
00119         else
00120         {
00121                 return  DDENUMRET_CANCEL;
00122         }
00123         return  DDENUMRET_OK;
00124 }
00125 
00126 BOOL    WINAPI  OldDDrawDriverEnumCallback(GUID *pGUID, LPSTR pDescription, LPSTR pName, LPVOID context)
00127 {
00128         return  (DDrawDriverEnumCallbackEx(pGUID, pDescription, pName, context, NULL));
00129 }
00130 
00131 HRESULT WINAPI ModeCallback(LPDDSURFACEDESC2 pdds, LPVOID lParam)
00132 {
00133         VidEnumInfo     *vinfo  =(VidEnumInfo *)lParam;
00134 
00135         if(pdds->ddpfPixelFormat.dwRGBBitCount==vinfo->bpp)
00136         {
00137                 vinfo->VidModes[vinfo->NumVidModes].width       =pdds->dwWidth;
00138                 vinfo->VidModes[vinfo->NumVidModes].flags       =0;
00139                 vinfo->VidModes[vinfo->NumVidModes].height      =pdds->dwHeight;
00140                 vinfo->VidModes[vinfo->NumVidModes++].bpp       =pdds->ddpfPixelFormat.dwRGBBitCount;
00141         }
00142         
00143         return  S_FALSE;
00144 }
00145 
00146 void    FreeDDraw(VidEnumInfo *vinfo)
00147 {
00148         int     x       =0;
00149 
00150         if(lpDD4)
00151         {
00152                 if(vinfo->VidModes[vinfo->CurrentVidMode].current & FLIP)
00153                 {
00154                         lpDDSBack       =NULL;
00155                 }
00156                 else
00157                 {
00158                         if(lpDDSBack)
00159                         {
00160                                 lpDDSBack->lpVtbl->Release(lpDDSBack);
00161                                 lpDDSBack       =NULL;
00162                         }
00163                 }
00164                 if(lpDDSPrimary)
00165                 {
00166                         lpDDSPrimary->lpVtbl->Release(lpDDSPrimary);
00167                         lpDDSPrimary    =NULL;
00168                 }
00169                 lpDD4->lpVtbl->Release(lpDD4);
00170                 lpDD4   =NULL;
00171         }
00172         FreeLibrary(ddrawinst);
00173 }
00174 
00175 HRESULT RestoreAll(void)
00176 {
00177         HRESULT ddrval;
00178 
00179         ddrval  =lpDD4->lpVtbl->SetCooperativeLevel(lpDD4, mhWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
00180         if(ddrval!=DD_OK)
00181         {
00182                 ErrorPrintf("Error During SetCooperativeLevel() in RestoreAll()\n%s\n", MyErrorToString(ddrval));
00183                 return  FALSE;
00184         }
00185 
00186         ddrval  =lpDD4->lpVtbl->SetDisplayMode(lpDD4, CurrentModeWidth, CurrentModeHeight, CurrentModeDepth, 0, 0);
00187         if(ddrval!=DD_OK)
00188         {
00189                 ErrorPrintf("Error During SetDisplayMode() in RestoreAll()\n%s\n", MyErrorToString(ddrval));
00190                 return  FALSE;
00191         }
00192         ddrval  =lpDD4->lpVtbl->RestoreAllSurfaces(lpDD4);
00193         if(ddrval!=DD_OK)
00194         {
00195                 ErrorPrintf("Error During RestoreAllSurfaces() in RestoreAll()\n%s\n", MyErrorToString(ddrval));
00196                 return  FALSE;
00197         }
00198         return  ddrval;
00199 }
00200 
00201 void    SetDDrawWindow(HWND hwnd)
00202 {
00203         mhWnd           =hwnd;
00204 }
00205 
00206 BOOL    LockDDrawBackBuffer(DRV_Window *cwnd, RECT *wrect)
00207 {
00208         HRESULT                 ddrval;
00209         DDSURFACEDESC2  ddsd;
00210 
00211         if(!bActive)
00212                 return TRUE;
00213 
00214         memset(&ddsd, 0, sizeof(DDSCAPS2));
00215         ddsd.dwSize     =sizeof(ddsd);
00216         ddsd.dwFlags=DDSD_HEIGHT | DDSD_WIDTH;
00217 
00218         lpDDSBack->lpVtbl->GetSurfaceDesc(lpDDSBack, &ddsd);
00219         if(((int)ddsd.dwWidth < wrect->right) || ((int)ddsd.dwHeight < wrect->bottom))
00220         {
00221                 ErrorPrintf("ERROR:  World render rect passed by the engine is larger than the drawing surface.\n");
00222                 ErrorPrintf("WorldRect: %d, %d, %d, %d\n", wrect->left, wrect->top, wrect->right, wrect->bottom);
00223                 ErrorPrintf("Surface:  %d, %d\n", ddsd.dwWidth, ddsd.dwHeight);
00224                 return  FALSE;
00225         }
00226 
00227         while(1)
00228         {
00229                 ddrval  =lpDDSBack->lpVtbl->Lock(lpDDSBack, wrect, &ddsd, DDLOCK_SURFACEMEMORYPTR, NULL);
00230                 if(ddrval==DD_OK)
00231                 {
00232                         break;
00233                 }
00234 
00235                 if(ddrval==DDERR_SURFACELOST)
00236                 {
00237                         ddrval  =RestoreAll();
00238                         if(ddrval!=DD_OK )
00239                         {
00240                                 ErrorPrintf("Error During Lock() in LockDDrawBackBuffer()...\n");
00241                                 ErrorPrintf("DirectDraw Surfaces were lost and could not be restored : %s\n", MyErrorToString(ddrval));
00242                                 return  FALSE;
00243                         }
00244                 }
00245                 else if(ddrval!=DDERR_WASSTILLDRAWING)
00246                 {
00247                         ErrorPrintf("Error During Lock() in LockDDrawBackBuffer() : %s\n", MyErrorToString(ddrval));
00248                         return  FALSE;
00249                 }
00250                 SleepEx(5, FALSE);
00251         }
00252         cwnd->Buffer    =(U8 *)ddsd.lpSurface;
00253         cwnd->PixelPitch=ddsd.lPitch;
00254         bBackLocked             =TRUE;
00255         return TRUE;
00256 }
00257 
00258 BOOL    UnlockDDrawBackBuffer(DRV_Window *cwnd, RECT *wrect)
00259 {
00260         HRESULT                 ddrval  =DD_OK;
00261 
00262         if(!bActive)
00263                 return TRUE;
00264 
00265         while(1)
00266         {
00267                 ddrval  =lpDDSBack->lpVtbl->Unlock(lpDDSBack, NULL);
00268                 if(ddrval==DD_OK)
00269                         break;
00270 
00271                 if(ddrval==DDERR_SURFACELOST)
00272                 {
00273                         ddrval  =RestoreAll();
00274                         if(ddrval!=DD_OK )
00275                         {
00276                                 ErrorPrintf("Error During Unlock() in UnlockDDrawBackBuffer()...\n");
00277                                 ErrorPrintf("DirectDraw Surfaces were lost and could not be restored : %s\n", MyErrorToString(ddrval));
00278                                 return  FALSE;
00279                         }
00280                 }
00281                 else if(ddrval!=DDERR_WASSTILLDRAWING)
00282                 {
00283                         ErrorPrintf("Error During Unlock() in UnlockDDrawBackBuffer() : %s\n", MyErrorToString(ddrval));
00284                         return  FALSE;
00285                 }
00286                 SleepEx(5, FALSE);
00287         }
00288         bBackLocked     =FALSE;
00289         return TRUE;
00290 }
00291 
00292 BOOL    RefreshDDraw(DRV_Window *cwnd, VidModeList *cmode, RECT *src, RECT *dst)
00293 {
00294         HRESULT                 ddrval;
00295         DDSURFACEDESC2  ddsd;
00296 //      int                             i;
00297         RECT                    rDest, rSrc;
00298 
00299         if(!bActive)
00300         {
00301                 return  TRUE;
00302         }
00303 
00304         memset(&ddsd, 0, sizeof(DDSCAPS2));
00305         ddsd.dwSize     =sizeof(ddsd);
00306         ddsd.dwFlags=DDSD_HEIGHT | DDSD_WIDTH;
00307 
00308         lpDDSBack->lpVtbl->GetSurfaceDesc(lpDDSBack, &ddsd);
00309         rDest.left      =rDest.top      =0;
00310         rDest.right     =ddsd.dwWidth-1;
00311         rDest.bottom=ddsd.dwHeight-1;
00312 
00313         memset(&ddsd, 0, sizeof(DDSCAPS2));
00314         ddsd.dwSize     =sizeof(ddsd);
00315         ddsd.dwFlags=DDSD_HEIGHT | DDSD_WIDTH;
00316 
00317         lpDDSPrimary->lpVtbl->GetSurfaceDesc(lpDDSPrimary, &ddsd);
00318         rSrc.left       =rSrc.top       =0;
00319         rSrc.right      =ddsd.dwWidth-1;
00320         rSrc.bottom     =ddsd.dwHeight-1;
00321 
00322         ddrval  =DD_OK;
00323         if((cmode->current & VIDEO) && (cmode->current & FASTBLT))
00324         {
00325                 while(1)
00326                 {
00327                         ddrval  =lpDDSPrimary->lpVtbl->BltFast(lpDDSPrimary, 0, 0, lpDDSBack, NULL, 0);
00328                         if(ddrval==DD_OK)
00329                         {
00330                                 break;
00331                         }
00332 
00333                         if(ddrval==DDERR_SURFACELOST)
00334                         {
00335                                 ddrval  =RestoreAll();
00336                                 if(ddrval!=DD_OK)
00337                                 {
00338                                         ErrorPrintf("Error During BltFast() in RefreshDDraw()...\n");
00339                                         ErrorPrintf("DirectDraw Surfaces were lost and could not be restored : %s\n", MyErrorToString(ddrval));
00340                                         return  FALSE;
00341                                 }
00342                         }
00343                         else if(ddrval!=DDERR_WASSTILLDRAWING)
00344                         {
00345                                 ErrorPrintf("Error During BltFast() in RefreshDDraw() : %s\n", MyErrorToString(ddrval));
00346                                 return  FALSE;
00347                         }
00348                         SleepEx(5, FALSE);
00349                 }
00350         }
00351         else if(cmode->current & FLIP)
00352         {
00353                 while(1)
00354                 {
00355                         ddrval  =lpDDSPrimary->lpVtbl->Flip(lpDDSPrimary, lpDDSBack, DDFLIP_NOVSYNC);
00356                         if(ddrval==DD_OK)
00357                         {
00358                                 break;
00359                         }
00360 
00361                         if(ddrval==DDERR_SURFACELOST)
00362                         {
00363                                 ddrval  =RestoreAll();
00364                                 if(ddrval!=DD_OK)
00365                                 {
00366                                         ErrorPrintf("Error During Flip() in RefreshDDraw()...\n");
00367                                         ErrorPrintf("DirectDraw Surfaces were lost and could not be restored : %s\n", MyErrorToString(ddrval));
00368                                         return  FALSE;
00369                                 }
00370                         }
00371                         else if(ddrval!=DDERR_WASSTILLDRAWING)
00372                         {
00373                                 ErrorPrintf("Error During Flip() in RefreshDDraw() : %s\n", MyErrorToString(ddrval));
00374                                 return  FALSE;
00375                         }
00376                         SleepEx(5, FALSE);
00377                 }
00378         }
00379         else    //safe blt
00380         {
00381                 if(cmode->current & STRETCHMODE)
00382                 {
00383                         while(1)
00384                         {
00385                                 ddrval  =lpDDSPrimary->lpVtbl->Blt(lpDDSPrimary, NULL, lpDDSBack, NULL, 0, NULL);
00386                                 if(ddrval==DD_OK)
00387                                         break;
00388 
00389                                 if(ddrval==DDERR_SURFACELOST)
00390                                 {
00391                                         ddrval  =RestoreAll();
00392                                         if(ddrval!=DD_OK)
00393                                         {
00394                                                 ErrorPrintf("Error During StretchMode Blt() in RefreshDDraw()...\n");
00395                                                 ErrorPrintf("DirectDraw Surfaces were lost and could not be restored : %s\n", MyErrorToString(ddrval));
00396                                                 return  FALSE;
00397                                         }
00398                                 }
00399                                 else if(ddrval!=DDERR_WASSTILLDRAWING)
00400                                 {
00401                                         ErrorPrintf("Error During StretchMode Blt() in RefreshDDraw() : %s\n", MyErrorToString(ddrval));
00402                                         return  FALSE;
00403                                 }
00404                                 SleepEx(5, FALSE);
00405                         }
00406                 }
00407                 else
00408                 {
00409                         while(1)
00410                         {
00411                                 ddrval  =lpDDSPrimary->lpVtbl->Blt(lpDDSPrimary, NULL, lpDDSBack, NULL, 0, NULL);
00412                                 if(ddrval==DD_OK)
00413                                         break;
00414 
00415                                 if(ddrval==DDERR_SURFACELOST)
00416                                 {
00417                                         ddrval  =RestoreAll();
00418                                         if(ddrval!=DD_OK)
00419                                         {
00420                                                 ErrorPrintf("Error During Blt() in RefreshDDraw()...\n");
00421                                                 ErrorPrintf("DirectDraw Surfaces were lost and could not be restored : %s\n", MyErrorToString(ddrval));
00422                                                 return  FALSE;
00423                                         }
00424                                 }
00425                                 else if(ddrval!=DDERR_WASSTILLDRAWING)
00426                                 {
00427                                         ErrorPrintf("Error During Blt() in RefreshDDraw() : %s\n", MyErrorToString(ddrval));
00428                                         return  FALSE;
00429                                 }
00430                                 SleepEx(5, FALSE);
00431                         }
00432                 }
00433         }
00434 /*      for(i=0;i < NumDecalsQd;i++)
00435         {
00436                 if(DecalQ[i].srect.left == -1)
00437                 {
00438                         DDrawBlitDecalToFront(DecalQ[i].surf, NULL, DecalQ[i].x, DecalQ[i].y); 
00439                 }
00440                 else
00441                 {
00442                         DDrawBlitDecalToFront(DecalQ[i].surf, &DecalQ[i].srect, DecalQ[i].x, DecalQ[i].y); 
00443                 }
00444         }
00445         NumDecalsQd     =0;*/
00446         return TRUE;
00447 }
00448 
00449 //my best guess for best performance is fast, blt, flip
00450 //dma is off for now because it ran horribly on the machine
00451 //I tested it on.  If people get 500mhz agp bus action in a few
00452 //years it might be useful perhaps
00453 geBoolean       SetDDrawMode(U32 top, VidEnumInfo *vinfo)
00454 {
00455         HRESULT                 ddrval;
00456         DDSURFACEDESC2  ddsd;
00457         DDSCAPS2                ddscaps;
00458 
00459         if(vinfo->VidModes[top].flags & STRETCHMODE)
00460         {
00461                 if((vinfo->VidModes[top].width > 640)
00462                         ||((vinfo->VidModes[top].width == 640)
00463                         &&(vinfo->VidModes[top].height > 480)))
00464                 {
00465                         ddrval  =lpDD4->lpVtbl->SetDisplayMode(lpDD4, vinfo->VidModes[top].width, vinfo->VidModes[top].height, vinfo->VidModes[top].bpp, 0, 0);
00466                 }
00467                 else
00468                 {
00469                         ddrval  =lpDD4->lpVtbl->SetDisplayMode(lpDD4, 640, 480, vinfo->VidModes[top].bpp, 0, 0);
00470                 }
00471                 vinfo->VidModes[top].current    |=STRETCHMODE;
00472         }
00473         else
00474         {
00475                 ddrval  =lpDD4->lpVtbl->SetDisplayMode(lpDD4, vinfo->VidModes[top].width, vinfo->VidModes[top].height, vinfo->VidModes[top].bpp, 0, 0);
00476         }
00477         if(ddrval != DD_OK)
00478         {
00479                 return  GE_FALSE;
00480         }
00481         CurrentModeHeight       =vinfo->VidModes[top].height;
00482         CurrentModeWidth        =vinfo->VidModes[top].width;
00483         CurrentModeDepth        =vinfo->VidModes[top].bpp;
00484 
00485         if(!(vinfo->VidModes[top].flags & MODEXMODE))
00486         {
00487                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
00488                 ddsd.dwSize                     =sizeof(ddsd);
00489                 ddsd.dwFlags            =DDSD_CAPS;
00490                 ddsd.ddsCaps.dwCaps     =DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
00491 
00492                 ddrval  =lpDD4->lpVtbl->CreateSurface(lpDD4, &ddsd, &lpDDSPrimary, NULL);
00493                 if(ddrval==DD_OK)
00494                 {
00495                         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
00496                         ddsd.dwSize             =sizeof(ddsd);
00497                         ddsd.dwFlags    =DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
00498                         ddsd.ddsCaps.dwCaps     =DDSCAPS_SYSTEMMEMORY;
00499                         if(vinfo->VidModes[top].flags & STRETCHMODE)
00500                         {
00501                                 if((vinfo->VidModes[top].width > 640)
00502                                         ||((vinfo->VidModes[top].width == 640)
00503                                         &&(vinfo->VidModes[top].height > 480)))
00504                                 {
00505                                         ddsd.dwHeight   =640;
00506                                         ddsd.dwWidth    =480;
00507                                 }
00508                                 else
00509                                 {
00510                                         ddsd.dwHeight   =vinfo->VidModes[top].height;
00511                                         ddsd.dwWidth    =vinfo->VidModes[top].width;
00512                                 }
00513                         }
00514                         else
00515                         {
00516                                 ddsd.dwHeight   =vinfo->VidModes[top].height;
00517                                 ddsd.dwWidth    =vinfo->VidModes[top].width;
00518                         }
00519 
00520                         ddrval  =lpDD4->lpVtbl->CreateSurface(lpDD4, &ddsd, &lpDDSBack, NULL);
00521                         if(ddrval==DD_OK)
00522                         {
00523                                 //need to grab pitch here since it can change
00524                                 //depending on where the surface is created
00525                                 memset(&ddsd, 0, sizeof(DDSCAPS2));
00526                                 ddsd.dwSize     =sizeof(ddsd);
00527                                 ddsd.dwFlags=DDSD_HEIGHT | DDSD_WIDTH;
00528                                 lpDDSBack->lpVtbl->GetSurfaceDesc(lpDDSBack, &ddsd);
00529                                 vinfo->VidModes[top].pitch      =ddsd.lPitch;
00530 
00531                                 //both were created, make sure they are in vidram
00532                                 memset(&ddscaps, 0, sizeof(DDSCAPS2));
00533                                 lpDDSPrimary->lpVtbl->GetCaps(lpDDSPrimary, &ddscaps);
00534                                 if(ddscaps.dwCaps & DDSCAPS_VIDEOMEMORY)
00535                                 {
00536                                         memset(&ddscaps, 0, sizeof(DDSCAPS2));
00537                                         lpDDSBack->lpVtbl->GetCaps(lpDDSBack, &ddscaps);
00538                                         if(ddscaps.dwCaps & DDSCAPS_VIDEOMEMORY)
00539                                         {
00540                                                 //both are good to go
00541                                                 vinfo->VidModes[top].current    |=VIDEO;
00542 
00543                                                 //mark fastblt unless it's stretching
00544                                                 if(!(vinfo->VidModes[top].flags & STRETCHMODE))
00545                                                 {
00546                                                         vinfo->VidModes[top].current    |=FASTBLT;
00547                                                 }
00548                                         }
00549                                 }
00550                         }
00551                 }
00552                 else if(!(vinfo->VidModes[top].current & VIDEO)
00553                         && !(vinfo->VidModes[top].current & STRETCHMODE))
00554                 {
00555                         if(lpDDSBack)           lpDDSBack->lpVtbl->Release(lpDDSBack);
00556                         if(lpDDSPrimary)        lpDDSPrimary->lpVtbl->Release(lpDDSPrimary);
00557 
00558                         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
00559                         ddsd.dwSize                     =sizeof(ddsd);
00560                         ddsd.dwFlags            =DDSD_CAPS;
00561                         ddsd.ddsCaps.dwCaps     =DDSCAPS_PRIMARYSURFACE;
00562 
00563                         ddrval  =lpDD4->lpVtbl->CreateSurface(lpDD4, &ddsd, &lpDDSPrimary, NULL);
00564                         if(ddrval==DD_OK)
00565                         {
00566                                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
00567                                 ddsd.dwSize             =sizeof(ddsd);
00568                                 ddsd.dwFlags    =DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
00569                                 ddsd.dwHeight   =vinfo->VidModes[top].height;
00570                                 ddsd.dwWidth    =vinfo->VidModes[top].width;
00571 
00572                                 ddrval  =lpDD4->lpVtbl->CreateSurface(lpDD4, &ddsd, &lpDDSBack, NULL);
00573                                 if(ddrval==DD_OK)
00574                                 {
00575                                         //need to grab pitch here since it can change
00576                                         //depending on where the surface is created
00577                                         memset(&ddsd, 0, sizeof(DDSCAPS2));
00578                                         ddsd.dwSize     =sizeof(ddsd);
00579                                         ddsd.dwFlags=DDSD_HEIGHT | DDSD_WIDTH;
00580                                         lpDDSBack->lpVtbl->GetSurfaceDesc(lpDDSBack, &ddsd);
00581                                         vinfo->VidModes[top].pitch      =ddsd.lPitch;
00582 
00583                                         //both were created good enough
00584                                         vinfo->VidModes[top].current    |=SYSTEM|SAFEBLT;
00585                                 }
00586                         }
00587                 }
00588         }       //flip 
00589         if((vinfo->VidModes[top].flags & MODEXMODE)     || lpDDSBack==NULL)
00590         {
00591                 if(lpDDSBack)           lpDDSBack->lpVtbl->Release(lpDDSBack);
00592                 if(lpDDSPrimary)        lpDDSPrimary->lpVtbl->Release(lpDDSPrimary);
00593 
00594                 //try flip
00595                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
00596                 ddsd.dwSize                             =sizeof(ddsd);
00597                 ddsd.dwFlags                    =DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
00598                 ddsd.ddsCaps.dwCaps             =DDSCAPS_PRIMARYSURFACE |
00599                                                                         DDSCAPS_COMPLEX | DDSCAPS_FLIP;
00600                 ddsd.dwBackBufferCount  =1;
00601 
00602                 ddrval  =lpDD4->lpVtbl->CreateSurface(lpDD4, &ddsd, &lpDDSPrimary, NULL);
00603                 if(ddrval==DD_OK)
00604                 {
00605                         memset(&ddscaps, 0, sizeof(DDSCAPS2));
00606                         ddscaps.dwCaps  =DDSCAPS_BACKBUFFER;
00607                         ddrval  =lpDDSPrimary->lpVtbl->GetAttachedSurface(lpDDSPrimary, &ddscaps, &lpDDSBack);
00608                         if(ddrval==DD_OK)
00609                         {
00610                                 //need to grab pitch here since it can change
00611                                 //depending on where the surface is created
00612                                 memset(&ddsd, 0, sizeof(DDSCAPS2));
00613                                 ddsd.dwSize     =sizeof(ddsd);
00614                                 ddsd.dwFlags=DDSD_HEIGHT | DDSD_WIDTH;
00615                                 lpDDSBack->lpVtbl->GetSurfaceDesc(lpDDSBack, &ddsd);
00616                                 vinfo->VidModes[top].pitch      =ddsd.lPitch;
00617 
00618                                 vinfo->VidModes[top].current    |=SYSTEM|FLIP;
00619                         }
00620                 }
00621         }
00622 
00623         return  GE_TRUE;
00624 }
00625 
00626 //sort the passed in list of video modes, returning a sorted
00627 //reliable list of resolutions and capabilities
00628 //capabilities are tested for each mode and surface type
00629 //to make a more reliable list than getcaps() can provide
00630 void SortDDrawVideoModeList(VidEnumInfo *vinfo)
00631 {
00632         int                             top, search;
00633         VidModeList             temp;
00634         DDSURFACEDESC2  ddsd;
00635         DDSCAPS2                ddscaps;
00636         HRESULT                 ddrval;
00637 
00638         for(top=0;top < vinfo->NumVidModes;top++)
00639         {
00640                 if(vinfo->VidModes[top].flags & MODEXMODE)
00641                 {
00642                         //modex can only flip I guess
00643                         vinfo->VidModes[top].flags      |=(SYSTEM | FLIP);
00644                 }
00645                 else
00646                 {
00647                         vinfo->VidModes[top].flags      |=SAFEBLT;      //everyone has this but X
00648                         ddrval  =lpDD4->lpVtbl->SetDisplayMode(lpDD4, vinfo->VidModes[top].width, vinfo->VidModes[top].height, vinfo->VidModes[top].bpp, 0, 0);
00649 
00650                         //check fastblt, front and back
00651                         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
00652                         ddsd.dwSize                     =sizeof(ddsd);
00653                         ddsd.dwFlags            =DDSD_CAPS;
00654                         ddsd.ddsCaps.dwCaps     =DDSCAPS_PRIMARYSURFACE | DDSCAPS_VIDEOMEMORY;
00655 
00656                         ddrval  =lpDD4->lpVtbl->CreateSurface(lpDD4, &ddsd, &lpDDSPrimary, NULL);
00657                         if(ddrval==DD_OK)
00658                         {
00659                                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
00660                                 ddsd.dwSize             =sizeof(ddsd);
00661                                 ddsd.dwFlags    =DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
00662                                 ddsd.dwHeight   =vinfo->VidModes[top].height;
00663                                 ddsd.dwWidth    =vinfo->VidModes[top].width;
00664 
00665                                 ddrval  =lpDD4->lpVtbl->CreateSurface(lpDD4, &ddsd, &lpDDSBack, NULL);
00666                                 if(ddrval==DD_OK)
00667                                 {
00668                                         //both were created, make sure they are
00669                                         //in vidram
00670                                         memset(&ddscaps, 0, sizeof(DDSCAPS2));
00671                                         lpDDSPrimary->lpVtbl->GetCaps(lpDDSPrimary, &ddscaps);
00672                                         if(ddscaps.dwCaps & DDSCAPS_VIDEOMEMORY)
00673                                         {
00674                                                 memset(&ddscaps, 0, sizeof(DDSCAPS2));
00675                                                 lpDDSBack->lpVtbl->GetCaps(lpDDSBack, &ddscaps);
00676                                                 if(ddscaps.dwCaps & DDSCAPS_VIDEOMEMORY)
00677                                                 {
00678                                                         //both are good to go
00679                                                         vinfo->VidModes[top].flags      |=VIDEO;
00680                                                 }
00681                                         }
00682                                         lpDDSBack->lpVtbl->Release(lpDDSBack);
00683                                 }
00684                                 lpDDSPrimary->lpVtbl->Release(lpDDSPrimary);
00685                         }
00686 
00687                         if(bDMA)
00688                         {
00689                                 //check dma capabilities
00690                                 memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
00691                                 ddsd.dwSize                     =sizeof(ddsd);
00692                                 ddsd.dwFlags            =DDSD_CAPS;
00693                                 ddsd.ddsCaps.dwCaps     =DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY;
00694 
00695                                 ddrval  =lpDD4->lpVtbl->CreateSurface(lpDD4, &ddsd, &lpDDSPrimary, NULL);
00696                                 if(ddrval==DD_OK)
00697                                 {
00698                                         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
00699                                         ddsd.dwSize                     =sizeof(ddsd);
00700                                         ddsd.dwFlags            =DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
00701                                         ddsd.ddsCaps.dwCaps     =DDSCAPS_SYSTEMMEMORY;
00702                                         ddsd.dwHeight           =vinfo->VidModes[top].height;
00703                                         ddsd.dwWidth            =vinfo->VidModes[top].width;
00704 
00705                                         ddrval  =lpDD4->lpVtbl->CreateSurface(lpDD4, &ddsd, &lpDDSBack, NULL);
00706                                         if(ddrval==DD_OK)
00707                                         {
00708                                                 memset(&ddscaps, 0, sizeof(DDSCAPS2));
00709                                                 lpDDSPrimary->lpVtbl->GetCaps(lpDDSPrimary, &ddscaps);
00710                                                 if(ddscaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
00711                                                 {
00712                                                         memset(&ddscaps, 0, sizeof(DDSCAPS2));
00713                                                         lpDDSBack->lpVtbl->GetCaps(lpDDSBack, &ddscaps);
00714                                                         if(ddscaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
00715                                                         {
00716                                                                 //both are good to go
00717                                                                 vinfo->VidModes[top].flags      |=(SYSTEM|DMABLT);
00718                                                         }
00719                                                 }
00720                                                 lpDDSBack->lpVtbl->Release(lpDDSBack);
00721                                         }
00722                                         lpDDSPrimary->lpVtbl->Release(lpDDSPrimary);
00723                                 }
00724                         }
00725 
00726                         //check flip
00727                         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
00728                         ddsd.dwSize                             =sizeof(ddsd);
00729                         ddsd.dwFlags                    =DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
00730                         ddsd.ddsCaps.dwCaps             =DDSCAPS_PRIMARYSURFACE |
00731                                                                         DDSCAPS_COMPLEX | DDSCAPS_FLIP;
00732                         ddsd.dwBackBufferCount  =1;
00733 
00734                         ddrval  =lpDD4->lpVtbl->CreateSurface(lpDD4, &ddsd, &lpDDSPrimary, NULL);
00735                         if(ddrval==DD_OK)       //make sure the backbuffer is really there
00736                         {
00737                                 memset(&ddscaps, 0, sizeof(DDSCAPS2));
00738                                 ddscaps.dwCaps  =DDSCAPS_BACKBUFFER;
00739                                 ddrval  =lpDDSPrimary->lpVtbl->GetAttachedSurface(lpDDSPrimary, &ddscaps, &lpDDSBack);
00740                                 if(ddrval==DD_OK)
00741                                 {
00742                                         //need to grab pitch here since it can change
00743                                         //depending on where the surface is created
00744                                         memset(&ddsd, 0, sizeof(DDSCAPS2));
00745                                         ddsd.dwSize     =sizeof(ddsd);
00746                                         ddsd.dwFlags=DDSD_HEIGHT | DDSD_WIDTH;
00747                                         lpDDSBack->lpVtbl->GetSurfaceDesc(lpDDSBack, &ddsd);
00748                                         vinfo->VidModes[top].pitch      =ddsd.lPitch;
00749 
00750                                         vinfo->VidModes[top].flags      |=(SYSTEM|FLIP);
00751                                         lpDDSPrimary->lpVtbl->Release(lpDDSPrimary);
00752                                 }
00753                         }
00754 
00755                         if(bHardBlt)
00756                         {
00757                                 vinfo->VidModes[top].flags      |=HARDWARE;
00758                         }
00759                 }
00760         }
00761 
00762         //drop in extra modes for stretching onto the end
00763         //disable stretched modes for now
00764 /*
00765         search  =vinfo->NumVidModes;
00766         for(top=0;top < search;top++)
00767         {
00768                 //that's a pretty big if 
00769                 //DISABLE > 640 FOR NOW
00770                 if(((vinfo->VidModes[top].width < 640)
00771                         &&(vinfo->VidModes[top].height < 480))
00772                         && !(vinfo->VidModes[top].flags & MODEXMODE))
00773                 {
00774                         vinfo->VidModes[vinfo->NumVidModes]     =vinfo->VidModes[top];
00775                         vinfo->VidModes[vinfo->NumVidModes++].flags     |=STRETCHMODE;
00776                 }
00777         }
00778 */
00779         //sort
00780         for(top=0;top < vinfo->NumVidModes-1;top++)
00781         {
00782                 for(search=top+1;search < vinfo->NumVidModes;search++)
00783                 {
00784                         if(vinfo->VidModes[search].width < vinfo->VidModes[top].width)
00785                         {
00786                                 temp    =vinfo->VidModes[search];
00787 
00788                                 vinfo->VidModes[search]=vinfo->VidModes[top];
00789                                 vinfo->VidModes[top]    =temp;
00790                         }
00791                 }
00792         }
00793 }
00794 
00795 BOOL    DoDDrawInit(HWND hwnd, VidEnumInfo *vinfo)
00796 {
00797         LPDIRECTDRAWCREATE      lpDDCreate;
00798         HRESULT                         ddrval;
00799 
00800         bInitDone       =FALSE;
00801         ddrawinst       =LoadLibrary("ddraw.dll");
00802 
00803         if(!ddrawinst)
00804         {
00805                 return  FALSE;
00806         }
00807         SetDDrawWindow(hwnd);
00808 
00809         lpDDCreate      =(LPDIRECTDRAWCREATE)GetProcAddress(ddrawinst, "DirectDrawCreate");
00810         if(lpDDCreate)
00811         {
00812                 ddrval  =lpDDCreate(NULL, &lpDD, NULL);
00813         }
00814         else
00815         {
00816                 return  DDENUMRET_CANCEL;
00817         }
00818 
00819         if(ddrval!=DD_OK)
00820         {
00821                 ErrorPrintf("Non Fatal Error During DirectDrawCreate() in DoDDrawInit()\n%s\n", MyErrorToString(ddrval));
00822                 return  FALSE;
00823         }
00824 
00825         ddrval = lpDD->lpVtbl->QueryInterface(lpDD, &IID_IDirectDraw4, (LPVOID *)&lpDD4);
00826         if(ddrval!=DD_OK)
00827         {
00828                 ErrorPrintf("Non Fatal Error During QueryInterface() in DoDDrawInit()\n%s\n", MyErrorToString(ddrval));
00829                 return  FALSE;
00830         }
00831         
00832         lpDD->lpVtbl->Release(lpDD);
00833         lpDD    =NULL;
00834 
00835         ddrval  =lpDD4->lpVtbl->SetCooperativeLevel(lpDD4, mhWnd,
00836                         DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
00837         if(ddrval!=DD_OK)
00838         {
00839                 ErrorPrintf("Non Fatal Error During SetCooperativeLevel() in DoDDrawInit()\n%s\n", MyErrorToString(ddrval));
00840                 return  FALSE;
00841         }
00842         FreeLibrary(ddrawinst);
00843 
00844         bInitDone       =TRUE;
00845         NumDecalsQd     =0;
00846         return          TRUE;   
00847 }
00848 
00849 
00850 BOOL    DoEnumeration(VidEnumInfo *vinfo)
00851 {
00852         LPDIRECTDRAWCREATE      lpDDCreate;
00853         LPDIRECTDRAW            pDD;
00854         LPDIRECTDRAW4           pDD4    =NULL;
00855         HRESULT                         hRet;
00856         bInitDone                       =FALSE;
00857 
00858 
00859         ddrawinst       =LoadLibrary("ddraw.dll");
00860 
00861         if(!ddrawinst)
00862         {
00863                 return  FALSE;
00864         }
00865 
00866         lpDDCreate      =(LPDIRECTDRAWCREATE)GetProcAddress(ddrawinst, "DirectDrawCreate");
00867         if(lpDDCreate)
00868         {
00869                 hRet    =lpDDCreate(NULL, &pDD, NULL);
00870         }
00871         else
00872         {
00873                 return  DDENUMRET_CANCEL;
00874         }
00875         
00876         vinfo->DeviceGuid       =NULL;
00877         
00878         if(hRet != DD_OK)
00879         {
00880                 ErrorPrintf("Non Fatal Error During DirectDrawCreate() in DoEnumeration()\n%s\n", MyErrorToString(hRet));
00881                 return  DDENUMRET_CANCEL;
00882         }
00883         memset(&vinfo->DeviceInfo, 0, sizeof(vinfo->DeviceInfo));
00884         memset(&vinfo->DeviceInfoHost, 0, sizeof(vinfo->DeviceInfo));
00885 
00886         hRet    =pDD->lpVtbl->QueryInterface(pDD, &IID_IDirectDraw4, (LPVOID *)&pDD4);
00887         if(hRet != DD_OK)
00888         {
00889                 ErrorPrintf("Non Fatal Error During QueryInterface() in DoEnumeration()\n%s\n", MyErrorToString(hRet));
00890                 return  DDENUMRET_CANCEL;
00891         }
00892         
00893         hRet    =pDD4->lpVtbl->GetDeviceIdentifier(pDD4, &vinfo->DeviceInfo,0);
00894         hRet    =pDD4->lpVtbl->GetDeviceIdentifier(pDD4, &vinfo->DeviceInfoHost, DDGDI_GETHOSTIDENTIFIER);
00895         
00896         if(pDD4)
00897         {
00898                 pDD4->lpVtbl->Release(pDD4);
00899         }
00900 
00901         FreeLibrary(ddrawinst);
00902         
00903         if(NumDevices < 16)
00904         {
00905                 NumDevices++;
00906         }
00907         else
00908         {
00909                 return  DDENUMRET_CANCEL;
00910         }
00911         return  DDENUMRET_OK;
00912 
00913         return  TRUE;   
00914 }
00915 
00916 BOOL    DoModeEnumeration(VidEnumInfo *vinfo)
00917 {
00918         LPDIRECTDRAWCREATE      lpDDCreate;
00919         HRESULT                         ddrval;
00920         DDCAPS                          ddcaps;
00921 
00922         bInitDone               =FALSE;
00923 
00924         ddrawinst       =LoadLibrary("ddraw.dll");
00925 
00926         if(!ddrawinst)
00927         {
00928                 return  FALSE;
00929         }
00930 
00931         lpDDCreate      =(LPDIRECTDRAWCREATE)GetProcAddress(ddrawinst, "DirectDrawCreate");
00932         if(lpDDCreate)
00933         {
00934                 ddrval  =lpDDCreate(NULL, &lpDD, NULL);
00935         }
00936         else
00937         {
00938                 return  DDENUMRET_CANCEL;
00939         }
00940 
00941         if(ddrval != DD_OK)
00942         {
00943                 ErrorPrintf("DirectDrawCreate FAILED : DoModeEnumeration\n%s\n", MyErrorToString(ddrval));
00944                 return 0;
00945         }
00946 
00947         ddrval = lpDD->lpVtbl->QueryInterface(lpDD, &IID_IDirectDraw4, (LPVOID *)&lpDD4);
00948         if(ddrval != DD_OK)
00949         {
00950                 ErrorPrintf("QueryInterface FAILED : DoModeEnumeration\n%s\n", MyErrorToString(ddrval));
00951                 return 0;
00952         }
00953         
00954         lpDD->lpVtbl->Release(lpDD);
00955         lpDD    =NULL;
00956 
00957         //test for general dma support
00958         memset(&ddcaps, 0, sizeof(DDCAPS));
00959         ddcaps.dwSize   =sizeof(ddcaps);
00960         lpDD4->lpVtbl->GetCaps(lpDD4, &ddcaps, NULL);
00961 
00962         if(ddcaps.dwCaps & DDCAPS_CANBLTSYSMEM)
00963         {
00964                 ErrorPrintf("System to video blits supported\n");
00965                 if(ddcaps.dwVSBCaps & DDCAPS_BLTQUEUE)
00966                 {
00967                         ErrorPrintf("DMA Asynch Video to System blits supported\n");
00968                 }
00969                 if(ddcaps.dwSSBCaps & DDCAPS_BLTQUEUE)
00970                 {
00971                         ErrorPrintf("DMA Asynch System to System blits supported\n");
00972                 }
00973                 if(ddcaps.dwSVBCaps & DDCAPS_BLTQUEUE)
00974                 {
00975                         bDMA    =TRUE;
00976 
00977                         ErrorPrintf("DMA Asynch System to Video blits supported\n");
00978                         if(ddcaps.dwCaps & DDCAPS2_NOPAGELOCKREQUIRED)
00979                         {
00980                                 ErrorPrintf("DMA Asynch page lock not required\n");
00981                         }
00982                         else
00983                         {
00984                                 bDMAPageLock    =TRUE;
00985                                 ErrorPrintf("DMA Asynch page lock required\n");
00986                         }
00987                 }
00988         }
00989         if(ddcaps.dwCaps2 & DDCAPS_BLT)
00990         {
00991                 ErrorPrintf("Hardware Blt supported\n");
00992                 bHardBlt        =TRUE;
00993         }
00994 
00995         //commented code below used for heavy mode testing
00996 //      ddrval  =lpDD4->lpVtbl->SetCooperativeLevel(lpDD4, ActiveWnd,
00997 //              DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
00998 //      if(ddrval != DD_OK)
00999 //      {
01000 //              return 0;
01001 //      }
01002         lpDD4->lpVtbl->EnumDisplayModes(lpDD4, 0, NULL, (LPVOID)vinfo, ModeCallback);
01003 
01004 //      SortDDrawVideoModeList(vinfo);
01005 
01006         lpDD4->lpVtbl->Release(lpDD4);
01007         lpDD4           =NULL;
01008 
01009         FreeLibrary(ddrawinst);
01010 
01011         return          TRUE;   
01012 }
01013 
01014 void    GetDDrawPixelFormat(DRV_Window *cwnd)
01015 {
01016         DDPIXELFORMAT   ddpf;
01017         U32                             i, j;
01018 
01019         ddpf.dwSize     =sizeof(ddpf);
01020         lpDDSPrimary->lpVtbl->GetPixelFormat(lpDDSPrimary, &ddpf);
01021 
01022         if(!(ddpf.dwFlags & DDPF_RGB))
01023         {
01024                 return;
01025         }
01026         cwnd->BytesPerPixel     =ddpf.dwRGBBitCount / 8;
01027         cwnd->R_mask            =ddpf.dwRBitMask;
01028         cwnd->G_mask            =ddpf.dwGBitMask;
01029         cwnd->B_mask            =ddpf.dwBBitMask;
01030 
01031         for(j=0,i=ddpf.dwRBitMask;!(i & 1);i>>=1,j++);
01032         cwnd->R_shift   =j;
01033 
01034         for(j=0,i=ddpf.dwGBitMask;!(i & 1);i>>=1,j++);
01035         cwnd->G_shift   =j;
01036 
01037         for(j=0,i=ddpf.dwBBitMask;!(i & 1);i>>=1,j++);
01038         cwnd->B_shift   =j;
01039 
01040         for(i=(ddpf.dwRBitMask>>cwnd->R_shift),cwnd->R_width=0;i;i >>= 1, cwnd->R_width++);
01041         for(i=(ddpf.dwGBitMask>>cwnd->G_shift),cwnd->G_width=0;i;i >>= 1, cwnd->G_width++);
01042         for(i=(ddpf.dwBBitMask>>cwnd->B_shift),cwnd->B_width=0;i;i >>= 1, cwnd->B_width++);
01043 }
01044 
01045 LPDIRECTDRAWSURFACE4    DDrawLoadSurface(U32 dwWidth, U32 dwHeight, const void *pixels, const char *pal)
01046 {
01047         LPDIRECTDRAWSURFACE4    lpDDS;
01048         DDSURFACEDESC2                  ddsd;
01049         HRESULT                                 ddrval;
01050         int                                             i;
01051         
01052         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
01053         ddsd.dwSize                     =sizeof(DDSURFACEDESC2);
01054         ddsd.dwFlags            =DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_CKSRCBLT;
01055         ddsd.ddsCaps.dwCaps     =DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
01056         ddsd.dwHeight           =dwHeight;
01057         ddsd.dwWidth            =dwWidth;
01058 
01059         ddsd.ddckCKSrcBlt.dwColorSpaceLowValue  =((((U8 *)pal)[765])<<16)
01060                                                                                         |((((U8 *)pal)[766])<<8)
01061                                                                                         |(((U8 *)pal)[767]);
01062         ddsd.ddckCKSrcBlt.dwColorSpaceHighValue =((((U8 *)pal)[765])<<16)
01063                                                                                         |((((U8 *)pal)[766])<<8)
01064                                                                                         |(((U8 *)pal)[767]);
01065 
01066         
01067         ddrval  =lpDD4->lpVtbl->CreateSurface(lpDD4, &ddsd, &lpDDS, NULL);
01068 
01069         if(ddrval != DD_OK)
01070         {
01071                 return  NULL;
01072         }
01073         
01074         memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
01075         ddsd.dwSize     =sizeof(DDSURFACEDESC2);
01076         ddrval          =lpDDS->lpVtbl->Lock(lpDDS, NULL, &ddsd, DDLOCK_WAIT, NULL);
01077         
01078         if(ddrval != DD_OK)
01079         {
01080                 lpDDS->lpVtbl->Release(lpDDS);
01081                 return  NULL;
01082         }
01083 
01084         for(i=0;i < (S32)(dwHeight * dwWidth);i++)
01085         {
01086                 ((U32 *)ddsd.lpSurface)[i]      =(((U8 *)pal)[(((U8 *)pixels)[i]) * 3])<<16
01087                                                                         |((((U8 *)pal)[((((U8 *)pixels)[i]) * 3)+1])<<8)
01088                                                                         |((((U8 *)pal)[((((U8 *)pixels)[i]) * 3)+2])<<0);
01089         }
01090 
01091         lpDDS->lpVtbl->Unlock(lpDDS, NULL);
01092         
01093         return  lpDDS;
01094 }
01095 
01096 char* MyErrorToString(HRESULT error)
01097 {
01098     switch(error) {
01099         case DD_OK:
01100             /* Also includes D3D_OK and D3DRM_OK */
01101             return "No error.\0";
01102         case DDERR_ALREADYINITIALIZED:
01103             return "This object is already initialized.\0";
01104         case DDERR_BLTFASTCANTCLIP:
01105             return "Return if a clipper object is attached to the source surface passed into a BltFast call.\0";
01106         case DDERR_CANNOTATTACHSURFACE:
01107             return "This surface can not be attached to the requested surface.\0";
01108         case DDERR_CANNOTDETACHSURFACE:
01109             return "This surface can not be detached from the requested surface.\0";
01110         case DDERR_CANTCREATEDC:
01111             return "Windows can not create any more DCs.\0";
01112         case DDERR_CANTDUPLICATE:
01113             return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.\0";
01114         case DDERR_CLIPPERISUSINGHWND:
01115             return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd.\0";
01116         case DDERR_COLORKEYNOTSET:
01117             return "No src color key specified for this operation.\0";
01118         case DDERR_CURRENTLYNOTAVAIL:
01119             return "Support is currently not available.\0";
01120         case DDERR_DIRECTDRAWALREADYCREATED:
01121             return "A DirectDraw object representing this driver has already been created for this process.\0";
01122         case DDERR_EXCEPTION:
01123             return "An exception was encountered while performing the requested operation.\0";
01124         case DDERR_EXCLUSIVEMODEALREADYSET:
01125             return "An attempt was made to set the cooperative level when it was already set to exclusive.\0";
01126         case DDERR_GENERIC:
01127             return "Generic failure.\0";
01128         case DDERR_HEIGHTALIGN:
01129             return "Height of rectangle provided is not a multiple of reqd alignment.\0";
01130         case DDERR_HWNDALREADYSET:
01131             return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or palettes created.\0";
01132         case DDERR_HWNDSUBCLASSED:
01133             return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring state.\0";
01134         case DDERR_IMPLICITLYCREATED:
01135             return "This surface can not be restored because it is an implicitly created surface.\0";
01136         case DDERR_INCOMPATIBLEPRIMARY:
01137             return "Unable to match primary surface creation request with existing primary surface.\0";
01138         case DDERR_INVALIDCAPS:
01139             return "One or more of the caps bits passed to the callback are incorrect.\0";
01140         case DDERR_INVALIDCLIPLIST:
01141             return "DirectDraw does not support the provided cliplist.\0";
01142         case DDERR_INVALIDDIRECTDRAWGUID:
01143             return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.\0";
01144         case DDERR_INVALIDMODE:
01145             return "DirectDraw does not support the requested mode.\0";
01146         case DDERR_INVALIDOBJECT:
01147             return "DirectDraw received a pointer that was an invalid DIRECTDRAW object.\0";
01148         case DDERR_INVALIDPARAMS:
01149             return "One or more of the parameters passed to the function are incorrect.\0";
01150         case DDERR_INVALIDPIXELFORMAT:
01151             return "The pixel format was invalid as specified.\0";
01152         case DDERR_INVALIDPOSITION:
01153             return "Returned when the position of the overlay on the destination is no longer legal for that destination.\0";
01154         case DDERR_INVALIDRECT:
01155             return "Rectangle provided was invalid.\0";
01156         case DDERR_LOCKEDSURFACES:
01157             return "Operation could not be carried out because one or more surfaces are locked.\0";
01158         case DDERR_NO3D:
01159             return "There is no 3D present.\0";
01160         case DDERR_NOALPHAHW:
01161             return "Operation could not be carried out because there is no alpha accleration hardware present or available.\0";
01162         case DDERR_NOBLTHW:
01163             return "No blitter hardware present.\0";
01164         case DDERR_NOCLIPLIST:
01165             return "No cliplist available.\0";
01166         case DDERR_NOCLIPPERATTACHED:
01167             return "No clipper object attached to surface object.\0";
01168         case DDERR_NOCOLORCONVHW:
01169             return "Operation could not be carried out because there is no color conversion hardware present or available.\0";
01170         case DDERR_NOCOLORKEY:
01171             return "Surface doesn't currently have a color key\0";
01172         case DDERR_NOCOLORKEYHW:
01173             return "Operation could not be carried out because there is no hardware support of the destination color key.\0";
01174         case DDERR_NOCOOPERATIVELEVELSET:
01175             return "Create function called without DirectDraw object method SetCooperativeLevel being called.\0";
01176         case DDERR_NODC:
01177             return "No DC was ever created for this surface.\0";
01178         case DDERR_NODDROPSHW:
01179             return "No DirectDraw ROP hardware.\0";
01180         case DDERR_NODIRECTDRAWHW:
01181             return "A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware.\0";
01182         case DDERR_NOEMULATION:
01183             return "Software emulation not available.\0";
01184         case DDERR_NOEXCLUSIVEMODE:
01185             return "Operation requires the application to have exclusive mode but the application does not have exclusive mode.\0";
01186         case DDERR_NOFLIPHW:
01187             return "Flipping visible surfaces is not supported.\0";
01188         case DDERR_NOGDI:
01189             return "There is no GDI present.\0";
01190         case DDERR_NOHWND:
01191             return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND.\0";
01192         case DDERR_NOMIRRORHW:
01193             return "Operation could not be carried out because there is no hardware present or available.\0";
01194         case DDERR_NOOVERLAYDEST:
01195             return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on to establish a destination.\0";
01196         case DDERR_NOOVERLAYHW:
01197             return "Operation could not be carried out because there is no overlay hardware present or available.\0";
01198         case DDERR_NOPALETTEATTACHED:
01199             return "No palette object attached to this surface.\0";
01200         case DDERR_NOPALETTEHW:
01201             return "No hardware support for 16 or 256 color palettes.\0";
01202         case DDERR_NORASTEROPHW:
01203             return "Operation could not be carried out because there is no appropriate raster op hardware present or available.\0";
01204         case DDERR_NOROTATIONHW:
01205             return "Operation could not be carried out because there is no rotation hardware present or available.\0";
01206         case DDERR_NOSTRETCHHW:
01207             return "Operation could not be carried out because there is no hardware support for stretching.\0";
01208         case DDERR_NOT4BITCOLOR:
01209             return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.\0";
01210         case DDERR_NOT4BITCOLORINDEX:
01211             return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.\0";
01212         case DDERR_NOT8BITCOLOR:
01213             return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color.\0";
01214         case DDERR_NOTAOVERLAYSURFACE:
01215             return "Returned when an overlay member is called for a non-overlay surface.\0";
01216         case DDERR_NOTEXTUREHW:
01217             return "Operation could not be carried out because there is no texture mapping hardware present or available.\0";
01218         case DDERR_NOTFLIPPABLE:
01219             return "An attempt has been made to flip a surface that is not flippable.\0";
01220         case DDERR_NOTFOUND:
01221             return "Requested item was not found.\0";
01222         case DDERR_NOTLOCKED:
01223             return "Surface was not locked.  An attempt to unlock a surface that was not locked at all, or by this process, has been attempted.\0";
01224         case DDERR_NOTPALETTIZED:
01225             return "The surface being used is not a palette-based surface.\0";
01226         case DDERR_NOVSYNCHW:
01227             return "Operation could not be carried out because there is no hardware support for vertical blank synchronized operations.\0";
01228         case DDERR_NOZBUFFERHW:
01229             return "Operation could not be carried out because there is no hardware support for zbuffer blitting.\0";
01230         case DDERR_NOZOVERLAYHW:
01231             return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.\0";
01232         case DDERR_OUTOFCAPS:
01233             return "The hardware needed for the requested operation has already been allocated.\0";
01234         case DDERR_OUTOFMEMORY:
01235             return "DirectDraw does not have enough memory to perform the operation.\0";
01236         case DDERR_OUTOFVIDEOMEMORY:
01237             return "DirectDraw does not have enough memory to perform the operation.\0";
01238         case DDERR_OVERLAYCANTCLIP:
01239             return "The hardware does not support clipped overlays.\0";
01240         case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
01241             return "Can only have ony color key active at one time for overlays.\0";
01242         case DDERR_OVERLAYNOTVISIBLE:
01243             return "Returned when GetOverlayPosition is called on a hidden overlay.\0";
01244         case DDERR_PALETTEBUSY:
01245             return "Access to this palette is being refused because the palette is already locked by another thread.\0";
01246         case DDERR_PRIMARYSURFACEALREADYEXISTS:
01247             return "This process already has created a primary surface.\0";
01248         case DDERR_REGIONTOOSMALL:
01249             return "Region passed to Clipper::GetClipList is too small.\0";
01250         case DDERR_SURFACEALREADYATTACHED:
01251             return "This surface is already attached to the surface it is being attached to.\0";
01252         case DDERR_SURFACEALREADYDEPENDENT:
01253             return "This surface is already a dependency of the surface it is being made a dependency of.\0";
01254         case DDERR_SURFACEBUSY:
01255             return "Access to this surface is being refused because the surface is already locked by another thread.\0";
01256         case DDERR_SURFACEISOBSCURED:
01257             return "Access to surface refused because the surface is obscured.\0";
01258         case DDERR_SURFACELOST:
01259             return "Access to this surface is being refused because the surface memory is gone. The DirectDrawSurface object representing this surface should have Restore called on it.\0";
01260         case DDERR_SURFACENOTATTACHED:
01261             return "The requested surface is not attached.\0";
01262         case DDERR_TOOBIGHEIGHT:
01263             return "Height requested by DirectDraw is too large.\0";
01264         case DDERR_TOOBIGSIZE:
01265             return "Size requested by DirectDraw is too large, but the individual height and width are OK.\0";
01266         case DDERR_TOOBIGWIDTH:
01267             return "Width requested by DirectDraw is too large.\0";
01268         case DDERR_UNSUPPORTED:
01269             return "Action not supported.\0";
01270         case DDERR_UNSUPPORTEDFORMAT:
01271             return "FOURCC format requested is unsupported by DirectDraw.\0";
01272         case DDERR_UNSUPPORTEDMASK:
01273             return "Bitmask in the pixel format requested is unsupported by DirectDraw.\0";
01274         case DDERR_VERTICALBLANKINPROGRESS:
01275             return "Vertical blank is in progress.\0";
01276         case DDERR_WASSTILLDRAWING:
01277             return "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is incomplete.\0";
01278         case DDERR_WRONGMODE:
01279             return "This surface can not be restored because it was created in a different mode.\0";
01280         case DDERR_XALIGN:
01281             return "Rectangle provided was not horizontally aligned on required boundary.\0";
01282         default:
01283             return "Unrecognized error value.\0";
01284     }
01285 }
01286 
01287 BOOL    DDrawBlitDecal(LPDIRECTDRAWSURFACE4 lpDDSDecal, RECT *SRect, S32 x, S32 y)
01288 {
01289         HRESULT                 ddrval;
01290         DDSURFACEDESC2  ddsd;
01291         RECT                    rDest;
01292         char                    szTemp[256];
01293 
01294         //make sure the back buffer is unlocked (for stretch)
01295 /*      if(bBackLocked)
01296         {
01297                 ddrval  =lpDDSBack->lpVtbl->Unlock(lpDDSBack, NULL);
01298                 if(ddrval!=DD_OK && ddrval!=DDERR_NOTLOCKED)
01299                 {
01300                         ErrorPrintf(MyErrorToString(ddrval));
01301                         return  TRUE;
01302                 }
01303         }
01304         bBackLocked     =FALSE;
01305 */
01306 
01307         if(SRect)
01308         {
01309                 rDest.left      =x;
01310                 rDest.top       =y;
01311                 rDest.right     =x + (SRect->right - SRect->left);
01312                 rDest.bottom=y + (SRect->bottom- SRect->top);
01313         }
01314         else
01315         {
01316                 memset(&ddsd, 0, sizeof(DDSCAPS2));
01317                 ddsd.dwSize     =sizeof(ddsd);
01318                 ddsd.dwFlags=DDSD_HEIGHT | DDSD_WIDTH;
01319                 lpDDSDecal->lpVtbl->GetSurfaceDesc(lpDDSDecal, &ddsd);
01320 
01321                 rDest.left      =x;
01322                 rDest.top       =y;
01323                 rDest.right     =x + ddsd.dwWidth;
01324                 rDest.bottom=y + ddsd.dwHeight;
01325         }
01326 
01327         ddrval  =DD_OK;
01328         while(1)
01329         {
01330                 if(SRect)
01331                 {
01332                         ddrval  =lpDDSBack->lpVtbl->Blt(lpDDSBack, &rDest, lpDDSDecal, SRect, DDBLT_WAIT | DDBLT_KEYSRC, NULL);
01333                 }
01334                 else
01335                 {
01336                         ddrval  =lpDDSBack->lpVtbl->Blt(lpDDSBack, &rDest, lpDDSDecal, NULL, DDBLT_WAIT | DDBLT_KEYSRC, NULL);
01337                 }
01338                 if(ddrval==DD_OK)
01339                         break;
01340 
01341                 if(ddrval==DDERR_SURFACELOST)
01342                 {
01343                         ddrval  =RestoreAll();
01344                         if(ddrval!=DD_OK)
01345                         {
01346                                 ErrorPrintf("Error During Blt() in DDrawBltDecal()...\n");
01347                                 ErrorPrintf("DirectDraw Surfaces were lost and could not be restored : %s\n", MyErrorToString(ddrval));
01348                                 return  FALSE;
01349                         }
01350                 }
01351                 else if(ddrval!=DDERR_WASSTILLDRAWING)
01352                 {
01353                         ErrorPrintf("Error During Blt() in DDrawBltDecal() : %s\n", MyErrorToString(ddrval));
01354                         if(SRect)
01355                         {
01356                                 sprintf(szTemp, "SLeft:%d, STop:%d, SRight:%d, SBottom:%d\n", SRect->left, SRect->top, SRect->right, SRect->bottom);
01357                                 ErrorPrintf(szTemp);
01358                         }
01359                         sprintf(szTemp, "DLeft:%d, DTop:%d, DRight:%d, DBottom:%d\n%x", rDest.left, rDest.top, rDest.right, rDest.bottom, (U32)lpDDSDecal);
01360                         ErrorPrintf(szTemp);
01361                         return  FALSE;
01362                 }
01363         }
01364         return  TRUE;
01365 }
01366 
01367 BOOL    DDrawBlitDecalToFront(LPDIRECTDRAWSURFACE4 lpDDSDecal, RECT *SRect, S32 x, S32 y)
01368 {
01369         HRESULT                 ddrval;
01370         DDSURFACEDESC2  ddsd;
01371         RECT                    rDest;
01372         char                    szTemp[256];
01373 
01374         if(SRect)
01375         {
01376                 rDest.left      =x;
01377                 rDest.top       =y;
01378                 rDest.right     =x + (SRect->right - SRect->left);
01379                 rDest.bottom=y + (SRect->bottom- SRect->top);
01380         }
01381         else
01382         {
01383                 memset(&ddsd, 0, sizeof(DDSCAPS2));
01384                 ddsd.dwSize     =sizeof(ddsd);
01385                 ddsd.dwFlags=DDSD_HEIGHT | DDSD_WIDTH;
01386                 lpDDSDecal->lpVtbl->GetSurfaceDesc(lpDDSDecal, &ddsd);
01387 
01388                 rDest.left      =x;
01389                 rDest.top       =y;
01390                 rDest.right     =x + ddsd.dwWidth;
01391                 rDest.bottom=y + ddsd.dwHeight;
01392         }
01393 
01394         ddrval  =DD_OK;
01395         while(1)
01396         {
01397                 if(SRect)
01398                 {
01399                         ddrval  =lpDDSPrimary->lpVtbl->Blt(lpDDSPrimary, &rDest, lpDDSDecal, SRect, DDBLT_WAIT | DDBLT_KEYSRC, NULL);
01400                 }
01401                 else
01402                 {
01403                         ddrval  =lpDDSPrimary->lpVtbl->Blt(lpDDSPrimary, &rDest, lpDDSDecal, NULL, DDBLT_WAIT | DDBLT_KEYSRC, NULL);
01404                 }
01405                 if(ddrval==DD_OK)
01406                         break;
01407 
01408                 if(ddrval==DDERR_SURFACELOST)
01409                 {
01410                         ddrval  =RestoreAll();
01411                         if(ddrval!=DD_OK)
01412                         {
01413                                 ErrorPrintf("Error During Blt() in DDrawBltDecalToFront()...\n");
01414                                 ErrorPrintf("DirectDraw Surfaces were lost and could not be restored : %s\n", MyErrorToString(ddrval));
01415                                 return  FALSE;
01416                         }
01417                 }
01418                 else if(ddrval!=DDERR_WASSTILLDRAWING)
01419                 {
01420                         ErrorPrintf("Error During Blt() in DDrawBltDecalToFront() : %s\n", MyErrorToString(ddrval));
01421                         if(SRect)
01422                         {
01423                                 sprintf(szTemp, "SLeft:%d, STop:%d, SRight:%d, SBottom:%d\n", SRect->left, SRect->top, SRect->right, SRect->bottom);
01424                                 ErrorPrintf(szTemp);
01425                         }
01426                         sprintf(szTemp, "DLeft:%d, DTop:%d, DRight:%d, DBottom:%d\n%x", rDest.left, rDest.top, rDest.right, rDest.bottom, (U32)lpDDSDecal);
01427                         ErrorPrintf(szTemp);
01428                         return  FALSE;
01429                 }
01430         }
01431         return  TRUE;
01432 }
01433 
01434 BOOL    DDrawBlitDecalDelayed(LPDIRECTDRAWSURFACE4 lpDDSDecal, RECT *SRect, S32 x, S32 y)
01435 {
01436         DecalQ[NumDecalsQd].surf        =lpDDSDecal;
01437         if(SRect)
01438         {
01439                 DecalQ[NumDecalsQd].srect       =*SRect;
01440         }
01441         else
01442         {
01443                 DecalQ[NumDecalsQd].srect.left  =-1;
01444         }
01445         DecalQ[NumDecalsQd].x           =x;
01446         DecalQ[NumDecalsQd].y           =y;
01447 
01448         if(NumDecalsQd < 8191)
01449         {
01450                 NumDecalsQd++;
01451         }
01452         return  TRUE;
01453 }
01454 
01455 void    ClearBackBuffer(DRV_Window *cwnd)
01456 {
01457         DDBLTFX                 bfx;
01458 
01459         if(!bActive)
01460         {
01461                 return;
01462         }
01463 
01464         memset(&bfx, 0, sizeof(bfx));
01465         bfx.dwSize              =sizeof(bfx);
01466         bfx.dwFillColor =0;
01467 
01468         lpDDSBack->lpVtbl->Blt(lpDDSBack, NULL, NULL, NULL, DDBLT_COLORFILL, &bfx);
01469 }
01470 
01471 geBoolean       DRIVERCC DrvSetActive(geBoolean wParam)
01472 {
01473         bActive =wParam;
01474 
01475         if(bInitDone && bActive)
01476         {       //regaining focus
01477                 ErrorPrintf("Regaining Focus\n");
01478                 OutputDebugString("Regaining Focus\n");
01479                 if(lpDDSPrimary->lpVtbl->IsLost(lpDDSPrimary)==DDERR_SURFACELOST)
01480                 {
01481                         if(RestoreAll()==DD_OK)
01482                         {
01483                                 ErrorPrintf("Regained focus and restored all DirectDraw surfaces\n");
01484                                 OutputDebugString("Regained focus and restored all DirectDraw surfaces\n");
01485                                 ShowWindow(mhWnd, SW_SHOWNORMAL);       //dx doesn't restore it
01486                         }
01487                         else
01488                         {
01489                                 ErrorPrintf("Couldn't restore surfaces!\n");
01490                                 OutputDebugString("Couldn't restore surfaces!\n");
01491                         }
01492                 }
01493                 else
01494                 {
01495                         ErrorPrintf("Regained focus, no surfaces lost\n");
01496                         OutputDebugString("Regained focus, no surfaces lost\n");
01497                 }
01498         }
01499         else
01500         {
01501                 ErrorPrintf("Lost Focus\n");
01502                 OutputDebugString("Lost Focus\n");
01503         }
01504         return  GE_TRUE;
01505 }
01506 

Generated on Tue Sep 30 12:35:38 2003 for GTestAndEngine by doxygen 1.3.2