/* ** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY ** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT ** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX ** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE ** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com). ** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER ** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A ** FULL TEXT OF THE NON-WARRANTY PROVISIONS. ** ** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO ** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN ** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013, ** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR ** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF ** THE UNITED STATES. ** ** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED ** ** $Log: ** 3 3dfx 1.0.1.0.1.0 10/11/00 Brent Forced check in to enforce ** branching. ** 2 3dfx 1.0.1.0 06/20/00 Joseph Kain Changes to support the ** Napalm Glide open source release. Changes include cleaned up offensive ** comments and new legal headers. ** 1 3dfx 1.0 09/11/99 StarTeam VTS Administrator ** $ ** ** 43 6/24/98 11:05a Dow ** better error message ** ** 42 6/11/98 7:45p Jdt ** Win98/NT5 Multimon 1st Pass ** ** 41 6/04/98 6:52p Dow ** Resolutions to 1600x1200 ** ** 40 5/27/98 3:10p Dow ** DOS happiness ** ** 39 4/14/98 11:55a Dow ** The Lord helps those who help themselves. ** ** 38 4/05/98 2:19p Dow ** DOS/WIN32 stepping on each others' dicks ** ** 37 4/03/98 2:03p Dow ** DOS Glide modes ** ** 36 3/11/98 8:27p Dow ** WinGlide * * 33 11/06/97 9:51a Jdt * Fixes window resize events to not crash/hang * * 32 10/01/97 3:21p Atai * fix 819, DOS tests flicker on glide * * 31 9/08/97 12:05p Atai * fixed resize problem in dxControl() * * 30 8/28/97 10:24a Odo * moved debugging varaible * * 29 8/27/97 10:32a Dow * added more debugging info * * 28 8/21/97 4:24p Dow * Fixed @#$%! C++ Comments, Added Debugging info ** ** $Revision: 1.2.2.3 $ ** $Date: 2000/11/18 16:00:35 $ ** */ /* 3Dfx Headers */ #include <3dfx.h> #include #include #include #define FX_DLL_DEFINIION #include #include #ifdef __DOS32__ #include #endif /* Local Headers */ #include "minihwc.h" #define H3_BUF_MAGIC 0x666 FxBool tripleBuffering = 0; #ifdef GDBG_INFO_ON static char *bufTypeNames[] = { "HWC_BUFFER_FRONTBUFFER", "HWC_BUFFER_BACKBUFFER", "HWC_BUFFER_AUXBUFFER", "HWC_BUFFER_DEPTHBUFFER", "HWC_BUFFER_ALPHABUFFER", "HWC_BUFFER_TRIPLEBUFFER", "HWC_BUFFER_FIFOBUFFER", "HWC_BUFFER_SCREENBUFFER", "HWC_BUFFER_TEXTUREBUFFER" }; #endif #if defined( __WIN32__) && defined(HWC_ACCESS_DDRAW) #define WIN32_LEAN_AND_MEAN #include #include #define NUM_BUFS 6 static HWND hWndApp = 0; static FxU32 FifoOffset = 0; static FxU32 Width = 0; static FxU32 Height = 0; static FxBool IsFullScreen = 0; static hwcBufferDesc BufDesc[NUM_BUFS] = {0}; /* Direct Draw stuff */ static LPDIRECTDRAWCLIPPER lpClipper = NULL; static LPDIRECTDRAWSURFACE lpFront = NULL; static LPDIRECTDRAWSURFACE lpBack = NULL; static LPDIRECTDRAWSURFACE lpAux = NULL; static LPDIRECTDRAWSURFACE lpTriple = NULL; static LPDIRECTDRAW2 lpDD = NULL; static LPDIRECTDRAW lpDD1 = NULL; FxBool ErrorMessage(HWND hWnd, char *err) { GDBG_INFO(0, "Error %s \n", err); // MessageBox( hWnd, err, "ERROR", MB_OK ); return FALSE; } /* ErrorMessage */ /* * Takes a DirectDraw Surface object (LPDIRECTDRAWSURFACE), looks up its * description (DDSURFACEDESC), and returns a pointer to the surface and its * stride value in pDesc. */ FxBool _dxSurfaceToBufDesc(LPDIRECTDRAWSURFACE lpSurf, hwcBufferDesc *pDesc) { DDSURFACEDESC ddsd; ddsd.dwSize = sizeof(ddsd); if (IDirectDrawSurface2_Lock(lpSurf, NULL, &ddsd, DDLOCK_WAIT, NULL) !=DD_OK) { return ErrorMessage(hWndApp, "_dxSurfaceToBufDesc: DdrawSurface Lock failed\n"); } /* pDesc->bufType should be filled in by caller */ pDesc->bufOffset = (FxU32) (ddsd.lpSurface); /* virtual address. */ pDesc->bufStride = (FxI32) (ddsd.lPitch); /* in bytes */ pDesc->bufBPP = (FxI32) 16; IDirectDrawSurface2_Unlock(lpSurf, NULL); return FXTRUE; } /* _dxSurfaceToBufDesc */ /* * Convert front, back and aux surfaces from DDraw to Glide bufDescriptors. */ FxBool _dxDDrawToGlideDesc(hwcBufferDesc *pDesc) { hwcBufferDesc *dFront = &pDesc[0]; hwcBufferDesc *dBack = &pDesc[1]; hwcBufferDesc *dAux = &pDesc[2]; hwcBufferDesc *dFifo = &pDesc[3]; hwcBufferDesc *dScreen = &pDesc[4]; hwcBufferDesc *dTriple = &pDesc[5]; GDBG_INFO(80, "_dxDDrawToGlide entry\n"); /* Initialize all descriptors. */ dScreen->bufMagic = H3_BUF_MAGIC; dScreen->bufType = HWC_BUFFER_SCREENBUFFER; dScreen->bufOffset = 0; dScreen->bufStride = 0; dScreen->bufBPP = 0; /* Get info about screen (primary display) */ dScreen->bufType = HWC_BUFFER_SCREENBUFFER; if (!_dxSurfaceToBufDesc( lpFront, dScreen)) return ErrorMessage(hWndApp, "Couldn't get Screen Info"); *dFront = *dBack = *dAux = *dFifo = *dTriple = *dScreen; dFront->bufType = HWC_BUFFER_FRONTBUFFER; /* Get info about back buffer */ dBack->bufType = HWC_BUFFER_BACKBUFFER; if (!_dxSurfaceToBufDesc( lpBack, dBack)) return ErrorMessage(hWndApp, "Couldn't get Backbuffer Info"); /* Get info about aux buffer */ dAux->bufType = HWC_BUFFER_AUXBUFFER; if (!_dxSurfaceToBufDesc( lpAux, dAux)) return ErrorMessage(hWndApp, "Couldn't get AuxBuffer Info"); /* Get info about triple buffer */ if (tripleBuffering) { dTriple->bufType = HWC_BUFFER_TRIPLEBUFFER; if (!_dxSurfaceToBufDesc( lpTriple, dTriple)) return ErrorMessage(hWndApp, "Couldn't get triple buffer Info"); } /* Get info about cmdFifo */ dFifo->bufType = HWC_BUFFER_FIFOBUFFER; dFifo->bufOffset = FifoOffset; dFifo->bufStride = 65536 << 1; /* Fixme!!! what's this? */ /* Now convert buf addresses for draw buffers into video memory offsets */ dFront->bufOffset -= dScreen->bufOffset; dBack ->bufOffset -= dScreen->bufOffset; dAux ->bufOffset -= dScreen->bufOffset; if (tripleBuffering) dTriple->bufOffset -= dScreen->bufOffset; GDBG_INFO(80, "_dxDDrawToGlideDesc: dFront->bufOffset = 0x%x\n", dFront->bufOffset); GDBG_INFO(80, "_dxDDrawToGlideDesc: dBack->bufOffset = 0x%x\n", dBack->bufOffset); GDBG_INFO(80, "_dxDDrawToGlideDesc: dAux->bufOffset = 0x%x\n", dAux->bufOffset); GDBG_INFO(80, "_dxDDrawToGlideDesc: dFifo->bufOffset = 0x%x\n", dFifo->bufOffset); if (tripleBuffering) GDBG_INFO(80, "_dxDDrawToGlideDesc: dTriple->bufOffset = 0x%x\n", dTriple->bufOffset); GDBG_INFO(80, "F:%.06x %5d B:%.06x %5d B2:%.06x %5d A:%.06x %5d, C:%.06x %5d\n", dFront->bufOffset, dFront->bufStride, dBack ->bufOffset, dBack ->bufStride, dTriple->bufOffset, dTriple->bufStride, dAux ->bufOffset, dAux ->bufStride, dFifo ->bufOffset, dFifo ->bufStride); return TRUE; } /* _dxDDrawToGlideDesc */ /* XXXTACOHACK -- The required header file isn't shipping yet - decls will be removed at some future time */ typedef void *HMONITOR; typedef BOOL (FAR PASCAL * LPDDENUMCALLBACKEXA)(GUID FAR *, LPSTR, LPSTR, LPVOID, HMONITOR); extern HRESULT WINAPI DirectDrawEnumerateExA( LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags); typedef HRESULT (WINAPI * LPDIRECTDRAWENUMERATEEXA)( LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags); #define DDENUM_ATTACHEDSECONDARYDEVICES 0x00000001L /* XXXTACOHACK -- The required header file isn't shipping yet - decls will be removed at some future time */ static GUID fooGuid; BOOL FAR PASCAL ddEnumCbEx( GUID FAR *guid, LPSTR desc, LPSTR name, LPVOID ctx, HMONITOR hmon ) { DWORD *data = (DWORD*)ctx; HMONITOR target = (HMONITOR)data[0]; BOOL rv = DDENUMRET_OK; if ( target == hmon ) { fooGuid = *guid; data[1] = (DWORD)&fooGuid; rv = DDENUMRET_CANCEL; } return rv; } /* * Allocate (or re-allocate for WM_SIZE) buffers from DDraw. */ FxBool _dxAllocSurfaces(int xRes, int yRes, int vRefresh, hwcBufferDesc *pDesc, void *hmon ) { DDSURFACEDESC ddsd; LPGUID ddGuid; GDBG_INFO(80, "_dxAS: hWnd = %x, fs=%d, xRes=%d, yRes=%d, vRefresh=%d\n", hWndApp, IsFullScreen, xRes, yRes, vRefresh); ddGuid = NULL; { HMODULE ddraw = GetModuleHandle( "ddraw.dll" ); if ( ddraw ) { LPDIRECTDRAWENUMERATEEXA ddEnumEx; ddEnumEx = (void*)GetProcAddress( ddraw, "DirectDrawEnumerateExA" ); if ( ddEnumEx ) { DWORD data[2]; data[0] = (DWORD)hmon; data[1] = 0; ddEnumEx( ddEnumCbEx, data, DDENUM_ATTACHEDSECONDARYDEVICES ); if ( data[1] ) { ddGuid = (LPGUID)data[1]; } } } } if (lpDD1 == NULL) { if (DirectDrawCreate( ddGuid, &lpDD1, NULL ) != DD_OK) { return ErrorMessage(hWndApp, "DirectDrawCreate Failed!"); } else { GDBG_INFO(80, "_dxAS: DDraw Obj created!\n"); } } else { GDBG_INFO(80, "_dxAS: DDraw Obj already existed!\n"); } lpDD = 0L; if (IDirectDraw_QueryInterface( lpDD1, &IID_IDirectDraw2, (LPVOID*)&lpDD) !=DD_OK) { IDirectDraw_Release( lpDD1 ); lpDD1 = NULL; lpDD = NULL; return ErrorMessage(hWndApp, "DDraw2 interface object failed!"); } else { GDBG_INFO(80, "_dxAS: DDraw2 Obj created!\n"); } /* * Make sure this is done after creating direct draw object!!! * First time, only one time, get ourselves a command fifo. * Fix me - XXX */ if (FifoOffset == 0) { /* CHD HACK!!! */ FifoOffset = 0x200000U - 65536*3; /* fixme!!! why 3? */ } /* * If there are any previously allocated surfaces, free them now * before asking for more. */ if( lpClipper) IDirectDrawSurface2_Release( lpClipper); if( lpAux ) IDirectDrawSurface2_Release( lpAux ); if( lpBack ) IDirectDrawSurface2_Release( lpBack ); if( lpTriple ) IDirectDrawSurface2_Release( lpTriple ); if( lpFront ) IDirectDrawSurface2_Release( lpFront ); lpClipper = NULL; lpFront = NULL; lpBack = NULL; lpTriple = NULL; lpAux = NULL; if ( !IsFullScreen ) { /* In a window */ GDBG_INFO(80, "_dxAS: Allocating buffers for a windowed mode\n"); /* Verify screen pixel format is 16bpp, and set cooperative level */ ddsd.dwSize = sizeof( ddsd ); if (IDirectDraw2_GetDisplayMode( lpDD, &ddsd ) != DD_OK) return ErrorMessage(hWndApp, "Couldn't get display mode!"); if (ddsd.ddpfPixelFormat.dwRGBBitCount / 8 != 2) return ErrorMessage(hWndApp, "Display is not in 16bpp format!"); if (IDirectDraw2_SetCooperativeLevel(lpDD,hWndApp, DDSCL_NORMAL ) != DD_OK) return ErrorMessage(hWndApp, "Couldn't set cooperative level!"); /* Allocate Front Buffer Surface */ ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE; if (IDirectDraw2_CreateSurface( lpDD, &ddsd, &lpFront, 0 ) != DD_OK) return ErrorMessage(hWndApp, "Couldn't allocate primary surface!"); GDBG_INFO(80, "_dxAS: Screen: xRes = %d, yRes = %d, stride = %d\n", xRes, yRes, ddsd.lPitch); /* From jdt */ if (IDirectDraw2_CreateClipper( lpDD, 0, &lpClipper, 0 ) != DD_OK) return ErrorMessage(hWndApp, "Create Clipper failed!\n"); if (IDirectDrawClipper_SetHWnd( lpClipper, 0, hWndApp ) != DD_OK) return ErrorMessage(hWndApp, "Clipper SethWnd failed!\n"); if (IDirectDrawSurface2_SetClipper( lpFront, lpClipper ) != DD_OK) return ErrorMessage(hWndApp, "Set Clipper failed!\n"); /* Always allocate back buffer. */ ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.dwWidth = xRes; ddsd.dwHeight = yRes; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE; if (IDirectDraw2_CreateSurface( lpDD, &ddsd, &lpBack, 0 ) != DD_OK) return ErrorMessage(hWndApp, "Couldn't allocate secondary surface!" ); GDBG_INFO(80, "_dxAS: Back buffer allocated!\n"); /* * Always allocate Aux Buffer Surface * XXX - (use nAuxBuffers, and deal with 8bpp for alpha) */ ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.dwWidth = xRes; ddsd.dwHeight = yRes; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE; if (IDirectDraw2_CreateSurface( lpDD, &ddsd, &lpAux, 0 ) != DD_OK) return ErrorMessage(hWndApp, "Couldn't allocate aux surface" ); GDBG_INFO(80, "_dxAS: Aux Buffer allocated!\n"); } else { /* Full screen - Set Exclusive Mode, change resolution, */ GDBG_INFO(80, "_dxAS: Setting Full screen exclusive mode!\n"); if (IDirectDraw2_SetCooperativeLevel(lpDD, hWndApp, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN ) != DD_OK) return ErrorMessage(hWndApp, "Couldn't set cooperative level!"); if (IDirectDraw2_SetDisplayMode( lpDD, xRes, yRes, 16, 0,0) != DD_OK) return ErrorMessage(hWndApp, "Couldn't set display mode!"); #if WE_WERE_HELPLESS /* Allocate Front/Back Buffer Surfaces, skip triple buffer XXX */ ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.dwBackBufferCount = 1; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE; if (IDirectDraw2_CreateSurface( lpDD, &ddsd, &lpFront, 0 ) != DD_OK) return ErrorMessage(hWndApp, "Couldn't allocate primary surface!"); /* Get back buffer information */ ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; if (IDirectDrawSurface2_GetAttachedSurface( lpFront, &ddsd.ddsCaps, &lpBack) != DD_OK) return ErrorMessage(hWndApp, "Couldn't get back buffer info!\n"); GDBG_INFO(80, "_dxAS: Full Screen: front/back buffer allocated!\n"); /* Allocate Aux Buffer Surface - XXX */ ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.dwWidth = xRes; ddsd.dwHeight = yRes; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE; if (IDirectDraw2_CreateSurface( lpDD, &ddsd, &lpAux, 0 ) != DD_OK) return ErrorMessage(hWndApp, "Couldn't allocate aux surface" ); GDBG_INFO(80, "_dxAS: Full Screen: aux buffer allocated!\n"); /* * Triple buffer hack: full-screen only for now. Allocate as Aux DD surf, * after everything else N.B. Allocation order may be important!!! * god knows how DD would implement dwBackBufferCount == 2 */ if (tripleBuffering) { if (IDirectDraw2_CreateSurface( lpDD, &ddsd, &lpTriple, 0 ) != DD_OK) return ErrorMessage(hWndApp, "Couldn't allocate triple buffer" ); GDBG_INFO(80, "_dxAS: Triple buffer allocated!\n"); } #endif } #if WE_WERE_HELPLESS /* Convert direct draw surfaces to Glide's idea of buffer descriptors */ return _dxDDrawToGlideDesc(pDesc); #else /* We help ourselves */ return FXTRUE; #endif } /* _dxAllocSurfaces */ FxBool _dxReallocSurfaces(int xRes, int yRes, int vRefresh, hwcBufferDesc *pDesc) { DDSURFACEDESC ddsd; const char *errorMessage = "no error"; /* for now this is a baseball bat it can be trimmed down */ if ( !IsFullScreen ) { /* this *REALLY* should be called for fullscreen */ if( lpClipper) IDirectDrawClipper_Release( lpClipper); if( lpAux ) IDirectDrawSurface2_Release( lpAux ); if( lpBack ) IDirectDrawSurface2_Release( lpBack ); if( lpTriple ) IDirectDrawSurface2_Release( lpTriple ); if( lpFront ) IDirectDrawSurface2_Release( lpFront ); lpClipper = NULL; lpFront = NULL; lpBack = NULL; lpTriple = NULL; lpAux = NULL; /* Verify screen pixel format is 16bpp, and set cooperative level */ ddsd.dwSize = sizeof( ddsd ); /* Allocate Front Buffer Surface */ ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE; if (IDirectDraw2_CreateSurface( lpDD, &ddsd, &lpFront, 0 ) != DD_OK) { errorMessage = "Couldn't allocate primary surface!"; goto FUBAR; } /* From jdt */ if (IDirectDraw2_CreateClipper( lpDD, 0, &lpClipper, 0 ) != DD_OK) { errorMessage = "Create Clipper failed!\n"; goto FUBAR; } if (IDirectDrawClipper_SetHWnd( lpClipper, 0, hWndApp ) != DD_OK) { errorMessage = "Clipper SethWnd failed!\n"; goto FUBAR; } if (IDirectDrawSurface2_SetClipper( lpFront, lpClipper ) != DD_OK) { errorMessage = "Set Clipper failed!\n"; goto FUBAR; } /* Always allocate back buffer. */ ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.dwWidth = xRes; ddsd.dwHeight = yRes; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE; if (IDirectDraw2_CreateSurface( lpDD, &ddsd, &lpBack, 0 ) != DD_OK) { errorMessage = "Couldn't allocate secondary surface!"; goto FUBAR; } /* * Always allocate Aux Buffer Surface * XXX - (use nAuxBuffers, and deal with 8bpp for alpha) */ ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH; ddsd.dwWidth = xRes; ddsd.dwHeight = yRes; ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE; if (IDirectDraw2_CreateSurface( lpDD, &ddsd, &lpAux, 0 ) != DD_OK) { errorMessage = "Couldn't allocate aux surface"; goto FUBAR; } } return _dxDDrawToGlideDesc(pDesc); FUBAR: /* if you don't free these you can't make another attempt */ if( lpClipper) IDirectDrawClipper_Release( lpClipper); if( lpAux ) IDirectDrawSurface2_Release( lpAux ); if( lpBack ) IDirectDrawSurface2_Release( lpBack ); if( lpTriple ) IDirectDrawSurface2_Release( lpTriple ); if( lpFront ) IDirectDrawSurface2_Release( lpFront ); lpClipper = NULL; lpFront = NULL; lpBack = NULL; lpTriple = NULL; lpAux = NULL; return ErrorMessage( hWndApp, (char*)errorMessage ); } /* _dxReallocSurfaces */ /* * Restore lost surfaces, or move the window. * Note: Resizing is done by deleting and re-allocation, and is done in * _dxAllocSurfaces(); */ static FxBool _dxRestoreSurfaces(hwcBufferDesc *pDesc) { if (lpDD == NULL) return TRUE; if (IDirectDrawSurface2_IsLost(lpFront) == DDERR_SURFACELOST) { if (IDirectDrawSurface2_Restore(lpFront) != DD_OK) return ErrorMessage(hWndApp, "Front Buffer restore failure\n"); } if (!IsFullScreen) { if (IDirectDrawSurface2_IsLost(lpBack) == DDERR_SURFACELOST) { if (IDirectDrawSurface2_Restore(lpBack) != DD_OK) return ErrorMessage(hWndApp, "Back Buffer restore failure\n"); } } if (IDirectDrawSurface2_IsLost(lpAux) == DDERR_SURFACELOST) { if (IDirectDrawSurface2_Restore(lpAux) != DD_OK) return ErrorMessage(hWndApp, "Aux Buffer restore failure\n"); } if (!IsFullScreen) { if (IDirectDrawSurface2_IsLost(lpTriple) == DDERR_SURFACELOST) { if (IDirectDrawSurface2_Restore(lpTriple) != DD_OK) return ErrorMessage(hWndApp, "Back Buffer restore failure\n"); } } GDBG_INFO(80, "_dxRS: restore surfaces OK\n"); return _dxDDrawToGlideDesc(pDesc); } /* _dxRestoreSurfaces */ FxBool dxOpen( FxU32 hWindow, GrScreenResolution_t sRes, GrScreenRefresh_t vRefresh, hwcColorFormat cFormat, hwcOriginLocation yOrigin, int nColBuffers, int nAuxBuffers, hwcBufferDesc *pBufDesc, /* return values */ int *width, int *height, hwcSwapType *swapType, void *hmon ) { int i; GDBG_INFO(80, "dxOpen: hWnd = %x, sRes=%d, yOrg=%d, ncb=%d, nab=%d\n", hWindow, sRes, yOrigin, nColBuffers, nAuxBuffers); /* * Get ourselves a valid window handle */ hWndApp = (hWindow == 0) ? GetActiveWindow() : (HWND) hWindow; if (hWndApp == NULL) { return MessageBox(NULL, "grSstWinOpen was passed a NULL window handle!\n\ Contact the application Vendor\n", "Programmer Error", MB_OK); } if (sRes == GR_RESOLUTION_NONE ) { /* In a window */ RECT rect; /* Find out how big the window is */ GetClientRect(hWndApp, &rect); IsFullScreen = FXFALSE; Width = rect.right; Height = rect.bottom; } else { /* Full screen mode - convert resolution to Width, Height */ static int _w[] = {320,320,400,512,640,640,640,640,800,960,856,512,1024,1280,1600,400}; static int _h[] = {200,240,256,384,200,350,400,480,600,720,480,256,768,1024,1200,300}; if ((sRes < GR_RESOLUTION_320x200) || (sRes > GR_RESOLUTION_1600x1200)) return ErrorMessage(hWndApp, "Bad Fullscreen resolution"); tripleBuffering = (nColBuffers == 3); IsFullScreen = FXTRUE; Width = _w[sRes]; Height = _h[sRes]; } GDBG_INFO(80, "dxOpen: W=%d, H=%d, FullScr=%d, vRefresh=%d\n", Width, Height, IsFullScreen, vRefresh); if (!_dxAllocSurfaces(Width, Height, vRefresh, BufDesc, hmon)) return ErrorMessage(hWndApp, "failed dxOpen"); GDBG_INFO(80, "_dxAllocSurfaces OK!!!\n"); for (i=0; i< NUM_BUFS; i++) { pBufDesc[i] = BufDesc[i]; GDBG_INFO(80, "dxOpen: pBufDesc[%d]: \n", i); GDBG_INFO(80, "\tbufMagic = 0x%x\n", pBufDesc[i].bufMagic); GDBG_INFO(80, "\tbufType = 0x%x\n", pBufDesc[i].bufType); GDBG_INFO(80, "\tbufOffset = 0x%x\n", pBufDesc[i].bufOffset); GDBG_INFO(80, "\tbufStride = 0x%x\n", pBufDesc[i].bufStride); GDBG_INFO(80, "\tbufBPP = 0x%x\n", pBufDesc[i].bufBPP); } *width = Width; *height = Height; *swapType = (IsFullScreen) ? HWC_SWAP_FLIP : HWC_SWAP_BLT; GDBG_INFO(80, "dxOpen: Returning TRUE\n"); return FXTRUE; } /* dxOpen */ FxBool dxControl(FxU32 code, hwcBufferDesc *pBufDesc, int *width, int *height) { RECT rect; int i; GDBG_INFO(80, "dxControl: code = %d\n", code); /* dx is not initizized */ if ( lpDD== NULL ) { return TRUE; } /* Why was I called? */ switch(code) { case HWC_CONTROL_RESIZE: /* recreate surfaces */ GetClientRect(hWndApp, &rect); if ((Width != (FxU32) rect.right) || (Height != (FxU32) rect.bottom)) { Width = rect.right; Height = rect.bottom; GDBG_INFO(120, "W and H changed to %d %d\n", Width, Height); if (!_dxReallocSurfaces(Width, Height, 0, BufDesc)) { /* Let's find some other way to do this! ErrorMessage(hWndApp, "dxControl: Resize failed\n"); */ return FXFALSE; } } break; case HWC_CONTROL_MOVE: break; case HWC_CONTROL_ACTIVATE: GDBG_INFO(120, "dxControl: Activate\n"); break; case HWC_CONTROL_DEACTIVATE: GDBG_INFO(120, "dxControl: DeActivate\n"); break; default: GDBG_INFO(120, "dxControl: Strange control %d\n", code); return FXFALSE; break; } for (i=0; i<5; i++) pBufDesc[i] = BufDesc[i]; *width = Width; *height = Height; GDBG_INFO(80, "dxControl: code = %d, w = %d, h = %d\n", code, Width, Height); return FXTRUE; } /* dxControl */ FxBool dxClose() { GDBG_INFO(80, "dxClose:\n"); /* * fixme! nulling out this code fixes bug 541... why is unclear??? XXX * A little more information... the problem is releasing lpDD1, and * only in fullscreen mode. Temporary refined hack is to not release * lpDD1 in fullscreen mode. Also rearrange code in dxAllocSurfaces * to only create lpDD1 once per application execution. /PGJ */ #if 1 // Release any allocated buffers if( lpClipper) IDirectDrawSurface2_Release( lpClipper); if( lpFront ) IDirectDrawSurface2_Release( lpFront ); if(!IsFullScreen) { if( lpBack ) IDirectDrawSurface2_Release( lpBack ); } if( lpAux ) IDirectDrawSurface2_Release( lpAux ); if( lpDD ) IDirectDraw2_Release( lpDD ); if (1 /* !IsFullScreen */) { if( lpDD1 ) IDirectDraw_Release( lpDD1 ); lpDD1 = NULL; } lpClipper = NULL; lpFront = NULL; lpBack = NULL; lpTriple = NULL; lpAux = NULL; lpDD = NULL; #endif /* 0 */ GDBG_INFO(80, "dxClose: Returning TRUE\n"); return FXTRUE; } /* dxClose */ void dxSwap(FxU32 code) { static RECT dest, src; static POINT point; static HRESULT hr; GDBG_INFO(80, "dxSwap:\n"); if ( !IsFullScreen ) { GDBG_INFO(120, "Swap: using BLTs\n"); src.left = 0; src.right = Width-1; src.top = 0; src.bottom = Height-1; dest = src; point.x = 0; point.y = 0; ClientToScreen( hWndApp, &point ); dest.left += point.x; dest.right += point.x; dest.top += point.y; dest.bottom += point.y; hr = IDirectDrawSurface_Blt( lpFront, &dest, lpBack, &src, DDBLT_WAIT, NULL ); while( IDirectDrawSurface_GetBltStatus( lpFront, DDGBS_ISBLTDONE ) != DD_OK ); if ( hr != DD_OK ) { ErrorMessage(hWndApp, "Couldn't blit!\n"); } } return; } /* dxSwap */ #else /* it's either DOS or the Hoopti Lab Setup */ static FxU16 oldVidMode; FxBool dxOpen( FxU32 hWindow, GrScreenResolution_t sRes, GrScreenRefresh_t vRefresh, hwcColorFormat cFormat, hwcOriginLocation yOrigin, int nColBuffers, int nAuxBuffers, hwcBufferDesc *pBufDesc, // return values int *width, int *height, hwcSwapType *swapType ) { #define FN_NAME "dxOpen" FxU32 mode; hwcBufferDesc *dFront = &pBufDesc[0]; hwcBufferDesc *dBack = &pBufDesc[1]; hwcBufferDesc *dAux = &pBufDesc[2]; hwcBufferDesc *dFifo = &pBufDesc[3]; hwcBufferDesc *dScreen = &pBufDesc[4]; hwcBufferDesc *dTriple = &pBufDesc[5]; FxBool rv = FXTRUE; FxU32 endAddr; union REGS r, rOut; r.w.ax = 0x4f03; int386(0x10, &r, &rOut); oldVidMode = rOut.w.bx; GDBG_INFO(80, "%s: Saving Current video mode (0x%x).\n", FN_NAME, oldVidMode); GDBG_INFO(80, "%s: Resolution == 0x%x\n", FN_NAME, sRes); switch (sRes) { case GR_RESOLUTION_640x480: *width = 640; *height = 480; mode = 0x111; break; case GR_RESOLUTION_800x600: case GR_RESOLUTION_320x200: case GR_RESOLUTION_320x240: case GR_RESOLUTION_512x384: case GR_RESOLUTION_400x256: case GR_RESOLUTION_640x200: case GR_RESOLUTION_640x350: case GR_RESOLUTION_640x400: case GR_RESOLUTION_960x720: case GR_RESOLUTION_856x480: case GR_RESOLUTION_512x256: case GR_RESOLUTION_NONE: default: GDBG_INFO(80, "%s: Unimplemented resolution\n", FN_NAME); return FXFALSE; break; } r.w.ax = 0x4f02; r.w.bx = mode; GDBG_INFO(80, "%s: Setting mode 0x%x, 0x%x\n", FN_NAME, r.w.ax, r.w.bx); /* Do VGA Magic */ int386(0x10, &r, &rOut); /* AT3D buffers need to be 4K (Intel) page-aligned */ #define BUMP(x, y) (((x) + ((y)-1)) & ~((y)-1)) #define BUMP_PAGE(x) (BUMP(x, 1<<12)) /* Initialize all descriptors. */ dFront->bufMagic = H3_BUF_MAGIC; dFront->bufType = HWC_BUFFER_FRONTBUFFER; dFront->bufOffset = 0; dFront->bufStride = (*width)*2; dFront->bufBPP = 16; endAddr = BUMP_PAGE((*width)*(*height)*2); dBack->bufMagic = H3_BUF_MAGIC; dBack->bufType = HWC_BUFFER_BACKBUFFER; dBack->bufOffset = endAddr; dBack->bufStride = (*width)*2; dBack->bufBPP = 16; endAddr = BUMP_PAGE(endAddr + (*width)*(*height)*2); tripleBuffering = (nColBuffers == 3); if (tripleBuffering) { dTriple->bufMagic = H3_BUF_MAGIC; dTriple->bufType = HWC_BUFFER_TRIPLEBUFFER; dTriple->bufOffset = endAddr; dTriple->bufStride = (*width)*2; dTriple->bufBPP = 16; endAddr = BUMP_PAGE(endAddr + (*width)*(*height)*2); } dAux->bufMagic = H3_BUF_MAGIC; dAux->bufType = HWC_BUFFER_AUXBUFFER; dAux->bufOffset = endAddr; dAux->bufStride = (*width)*2; dAux->bufBPP = 16; endAddr = BUMP_PAGE(endAddr + (*width)*(*height)*2); dFifo->bufMagic = H3_BUF_MAGIC; dFifo->bufType = HWC_BUFFER_FIFOBUFFER; dFifo->bufOffset = endAddr; dFifo->bufStride = 65536; dFifo->bufBPP = 16; dScreen->bufMagic = H3_BUF_MAGIC; dScreen->bufType = HWC_BUFFER_SCREENBUFFER; dScreen->bufOffset = 0; dScreen->bufStride = 0; dScreen->bufBPP = 0; GDBG_INFO(80, "%s: dFront = 0x%x, dBack = 0x%x, dAux = 0x%x\n", FN_NAME, dFront, dBack, dAux, dFifo); GDBG_INFO(80, "dxOpen: F:%.06x %5d B:%.06x %5d A:%.06x %5d, C:%.06x %5d\n", dFront->bufOffset, dFront->bufStride, dBack ->bufOffset, dBack ->bufStride, dAux ->bufOffset, dAux ->bufStride, dFifo ->bufOffset, dFifo ->bufStride); #ifdef GDBG_INFO_ON { int i; for (i = 0; i < 5; i++) { GDBG_INFO(80, "%s: pBufDesc[%d] = 0x%x:\n", FN_NAME, i, &pBufDesc[i]); GDBG_INFO(80, "%s: pBufDesc.bufType = %s\n", FN_NAME, bufTypeNames[pBufDesc[i].bufType]); GDBG_INFO(80, "%s: pBufDesc.bufOffset = 0x%x\n", FN_NAME, pBufDesc[i].bufOffset ); GDBG_INFO(80, "%s: pBufDesc.bufStride = 0x%x\n", FN_NAME, pBufDesc[i].bufStride); GDBG_INFO(80, "%s: pBufDesc.bufBPP = 0x%x\n", FN_NAME, pBufDesc[i].bufBPP); } } #endif *swapType = HWC_SWAP_FLIP; BAIL: return rv; #undef FN_NAME } /* dxOpen */ FxBool dxControl(FxU32 code, hwcBufferDesc *pBufDesc, int *width, int *height) { return FXTRUE; } /* dxControl */ FxBool dxClose() { #define FN_NAME "dxClose" GDBG_INFO(80, "%s: Setting up VESA mode 640*480*\n", FN_NAME); { union REGS r; memset(&r, 0, sizeof(r)); r.w.ax = 0x4f02; r.w.bx = oldVidMode; GDBG_INFO(80, "%s: Setting mode 0x%x, 0x%x\n", FN_NAME, r.w.ax, r.w.bx); int386( 0x10, &r, &r ); } return FXTRUE; #undef FN_NAME } /* dxClose */ void dxSwap(FxU32 code) { } /* dxSwap */ #endif /* __DOS32__ || (defined(__WIN32__) && !defined(HWC_ACCESS_DDRAW) */