summaryrefslogtreecommitdiff
path: root/src/avp/win95/dx_proj.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/avp/win95/dx_proj.cpp')
-rw-r--r--src/avp/win95/dx_proj.cpp710
1 files changed, 710 insertions, 0 deletions
diff --git a/src/avp/win95/dx_proj.cpp b/src/avp/win95/dx_proj.cpp
new file mode 100644
index 0000000..b01db10
--- /dev/null
+++ b/src/avp/win95/dx_proj.cpp
@@ -0,0 +1,710 @@
+// Project specific parts of the Win95 DirectX system,
+// largely concerned with the rules for selecting a driver,
+// draw mode, memory mode etc during system initialisation, which
+// cannot readily be decided at a project independent level.
+
+// Must link to C code in main engine system
+
+// Note that TestInitD3DObject is called during InitialiseSystem, immediately
+// after initialisation of the basic DirectDraw object. It is normally used
+// to detect the hardware acceleration capabilities of a system, by creating a Direct3D
+// object which is then collapsed again, so that the information can be passed to e.g.
+// menu software to provide recommended options. The video mode can potentially
+// be rewritten here, so that a 320x200x8 request mode is interpreted as e.g. 640x480x15
+// if hardware acceleration is detected and it is decided that it will be used.
+
+// Note that the ProcessorType global should be valid at this stage.
+
+
+// TestMemoryAccess is run immediately after TestInitD3DObject in InitialiseSystem,
+// and is used to determine whether the back buffer should be in system or video memory.
+// Note that if you intend to use MMX scan draws the back buffer should be in system memory,
+// if you are running with hardware accelerated draws it MUST be in video memory, and otherwise
+// I would recommend video memory except in extreme circumstances (i.e. very old video cards
+// with very slow VRAM access). Note that whether or not we will boot on hardware should have been
+// decided by this stage.
+
+// NOTE THAT THE REQUESTSYSTEMMEMORYALWAYS OPTION IS A DEBUGGING FEATURE, SINCE THE WATCOM
+// DEBUGGER CAN ONLY BE USED ON FUNCTIOSN WITHIN DRAWITEMLISTCONTENTS ETC IF THE RENDERING
+// TARGET IS IN SYSTEM MEMORY AND THE SYSTEM DOES NOT HAVE TO TAKE A WIN16 LOCK TO
+// REACH THE SURFACE. THIS REQUEST MODE OPTION REPLACES FORCEBUFFERSINTOSYSTEMMEMORY, WHICH
+// WAS AT THE TOP OF DD_FUNC.CPP
+
+// SelectD3DDriverAndDrawMode is the final selection function for hardware acceleration, z buffering
+// etc, run during SetVideoMode from InitialiseDirect3DImmediateMode. Note that your target video
+// mode must have been selected before you enter this routine. This routine is separate so that a call
+// to ChangeDisplayModes (in io.c) can be used to change the video mode, driver etc.
+
+// NOTE: USE OF CHANGEDISPLAYMODES MUST BE INTEGRATED WITH USE OF THE CHUNK SYSTEM, SINCE IT WILL
+// REQUIRE A TEXTURE RELOAD AND PROBABLY A SHAPE RELOAD.
+
+// NOTE: IF YOU INTEND TO LET THE USER OVERRIDE VIDEO MODE, DRIVER ETC SETTINGS FROM MENUS RUN
+// (UNAVOIDABLY, I SUSPECT) AFTER INITIALISESYSTEM, YOU MUST CALL SETVIDEOMODE BEFORE THE MENUS
+// IF YOU WANT THEM TO BE DISPLAYED USING ENGINE (DIRECTX) FUNCTIONS AND THEN CALL CHANGEDISPLAYMODES
+// TO CHANGE THE MODES TO THE FINAL ONES. DO NOT CALL SETVIDEOMODE TWICE DURING A SINGLE PROGRAM RUN.
+// CHANGEDISPLAYMODES WILL CALL YOUR VERSION OF SELECTD3DDRIVERANDDRAWMODE FOR YOU, BUT TESTMEMORYACCESS
+// AND TESTINITD3DOBJECT WILL NOT BE CALLED AGAIN. IF YOU WANT TO RESELECT THE MEMORY MODE OR RETEST
+// HARDWARE ACCELERATION CAPABILITIES, YOU MUST DO IT YOURSELF IN THE MENUS SYSTEM.
+
+// NOTE: TO CHANGE PALETTE IN A PALETTISED MODE, CALL CHANGEPALETTE IN IO.C, NOT CHANGEDISPLAYMODES.
+
+extern "C" {
+
+#include "system.h"
+#include "equates.h"
+#include "platform.h"
+#include "shape.h"
+#include "prototyp.h"
+#include "inline.h"
+
+#include "d3_func.h"
+#include "d3dmacs.h"
+
+extern "C++"
+{
+#include "pcmenus.h"
+};
+
+#include "dxlog.h"
+
+// Tell system to prefer palettised formats
+// for textures. The alternative is to prefer
+// non-palettised modes.
+// Note that non-palettised modes certainly seem
+// to look better on the software RGB driver, anyway,
+// leading me to suspect that my runtime ppm quantiser
+// is, ahem, less than totally perfect...
+#define PreferPalettisedTextures Yes
+
+// Test hack to force driver zero (mono
+// rather than RGB), plus others. Should
+// all be No in theory. Turn on only one
+// at a time!!!
+#define ForceRampDriver No
+#define ForceRGBDriver No
+#define ForceHardwareDriver No
+#define ForceDirectDraw No
+
+// Externs
+
+extern int VideoMode;
+extern int VideoModeColourDepth;
+extern int WindowMode;
+extern int DrawMode;
+extern int ScanDrawMode;
+extern int ZBufferMode;
+extern int DXMemoryMode;
+extern int DXMemoryRequestMode;
+extern int ZBufferRequestMode;
+extern int RasterisationRequestMode;
+extern int SoftwareScanDrawRequestMode;
+extern int D3DDriverMode;
+extern BOOL D3DHardwareAvailable;
+extern D3DINFO d3d;
+extern int StartDriver;
+extern int StartFormat;
+extern HRESULT LastError;
+extern BOOL MMXAvailable;
+extern LPDIRECTDRAW lpDD;
+
+// Globals
+// Test only!!!
+int TestHw = No;
+
+
+// Callback function to enumerate texture
+// formats available on the current D3D
+// driver. Obviously this should be run
+// AFTER the driver callback, and after
+// a driver has been selected.
+// A palette will be picked as the default
+// (with preference given to palettized
+// formats) and returned via the lpContext.
+
+HRESULT CALLBACK TextureFormatsEnumerator
+ (LPDDSURFACEDESC lpDDSD, LPVOID lpContext)
+{
+ unsigned long m;
+ int r, g, b;
+ int *lpStartFormat = (int*) lpContext;
+
+ /*
+ Record the DDSURFACEDESC of this texture format
+ */
+
+ memset(&d3d.TextureFormat[d3d.NumTextureFormats], 0,
+ sizeof(D3DTEXTUREFORMAT));
+ memcpy(&d3d.TextureFormat[d3d.NumTextureFormats].ddsd,
+ lpDDSD, sizeof(DDSURFACEDESC));
+
+ /*
+ Is this format palettized? How many bits? Otherwise, how many RGB
+ bits?
+ */
+
+ if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
+ {
+ d3d.TextureFormat[d3d.NumTextureFormats].Palette = Yes;
+ d3d.TextureFormat[d3d.NumTextureFormats].IndexBPP = 8;
+ }
+ else if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4)
+ {
+ d3d.TextureFormat[d3d.NumTextureFormats].Palette = Yes;
+ d3d.TextureFormat[d3d.NumTextureFormats].IndexBPP = 4;
+ }
+ else if (lpDDSD->ddpfPixelFormat.dwFlags & (DDPF_ALPHA|DDPF_ALPHAPIXELS|DDPF_FOURCC))
+ {
+ return DDENUMRET_OK;
+ }
+ else if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_RGB)
+ {
+ // This bit is all fiendishly cunning, Dr Tringham,
+ // but one has to wonder if it actually, as such,
+ // works...
+ d3d.TextureFormat[d3d.NumTextureFormats].Palette = No;
+ d3d.TextureFormat[d3d.NumTextureFormats].IndexBPP = 0;
+ for (r = 0, m = lpDDSD->ddpfPixelFormat.dwRBitMask;
+ !(m & 1); r++, m >>= 1);
+ for (r = 0; m & 1; r++, m >>= 1);
+ for (g = 0, m = lpDDSD->ddpfPixelFormat.dwGBitMask;
+ !(m & 1); g++, m >>= 1);
+ for (g = 0; m & 1; g++, m >>= 1);
+ for (b = 0, m = lpDDSD->ddpfPixelFormat.dwBBitMask;
+ !(m & 1); b++, m >>= 1);
+ for (b = 0; m & 1; b++, m >>= 1);
+ d3d.TextureFormat[d3d.NumTextureFormats].RedBPP = r;
+ d3d.TextureFormat[d3d.NumTextureFormats].GreenBPP = g;
+ d3d.TextureFormat[d3d.NumTextureFormats].BlueBPP = b;
+ }
+ else
+ {
+ return DDENUMRET_OK;
+ }
+
+ /*
+ If lpStartFormat is -1, this is the first format.
+ Select it.
+ */
+
+ if (*lpStartFormat == -1)
+ *lpStartFormat = d3d.NumTextureFormats;
+ else
+ {
+ if (PreferTextureFormat(&d3d.TextureFormat[*lpStartFormat],&d3d.TextureFormat[d3d.NumTextureFormats]))
+ *lpStartFormat = d3d.NumTextureFormats;
+ }
+
+ d3d.NumTextureFormats++;
+ return DDENUMRET_OK;
+}
+
+
+// Code to pick a driver and scan draw mode
+// based on what hardware is present on the
+// system and the current request modes
+// (specified by default in the InitialVideoMode
+// call).
+// The basic rules are that a hardware driver will
+// always be picked if one is available unless
+// software only rasterisation has been requested,
+// in which case we will get a software driver anyway,
+// and that hardware rgb scan draws will be picked if
+// we are running on hardware, but otherwise the ramp
+// software scan draw mode will be picked unless DirectDraw
+// scan draws have been specifically requested.
+
+// Note that since rewrites to the VideoMode really ought
+// to be done BEFORE SetVideoMode is run, this function's
+// effects must be combined with those of
+// InitialiseDirectDrawObject and TestInitD3DObject!!!!
+
+void SelectD3DDriverAndDrawMode(void)
+
+{
+// Note that if we have requested default rasterisation and hw is
+// available, we may want to pick the software RGB driver if MMXAvailable
+// is Yes!!! Fix later!!!
+ if ((D3DHardwareAvailable)
+ && (RasterisationRequestMode != RequestSoftwareRasterisation))
+ {
+ int i=0;
+ BOOL EarlyExit = No;
+
+ do
+ {
+ if (d3d.Driver[i].Hardware)
+ {
+ d3d.CurrentDriver = i;
+ EarlyExit = Yes;
+ }
+ }
+ while ((++i < d3d.NumDrivers) && !EarlyExit);
+
+ D3DDriverMode = D3DHardwareRGBDriver;
+ ScanDrawMode = ScanDrawD3DHardwareRGB;
+ }
+// Note that we may want to select the software RGB driver if default scan
+// draws have been requested, should MMXAvailable be Yes...
+ else if (SoftwareScanDrawRequestMode == RequestScanDrawSoftwareRGB)
+ {
+ int i=0;
+ BOOL EarlyExit = No;
+
+ do
+ {
+ if ((!d3d.Driver[i].Hardware) &&
+ (d3d.Driver[i].Desc.dcmColorModel == D3DCOLOR_RGB))
+ {
+ d3d.CurrentDriver = i;
+ EarlyExit = Yes;
+ }
+ }
+ while ((++i < d3d.NumDrivers) && !EarlyExit);
+
+ D3DDriverMode = D3DSoftwareRGBDriver;
+ ScanDrawMode = ScanDrawD3DSoftwareRGB;
+ }
+// Note that once everything, like, works, and Microsoft's code
+// is dead fast and doesn't crash or anything, the default software
+// scan draw mode should be changed from DirectDraw to Ramp.
+// Probably.
+ else if (SoftwareScanDrawRequestMode == RequestScanDrawRamp)
+ {
+ int i=0;
+ BOOL EarlyExit = No;
+
+ do
+ {
+ if ((!d3d.Driver[i].Hardware) &&
+ (d3d.Driver[i].Desc.dcmColorModel == D3DCOLOR_MONO))
+ {
+ d3d.CurrentDriver = i;
+ EarlyExit = Yes;
+ }
+ }
+ while ((++i < d3d.NumDrivers) && !EarlyExit);
+
+ D3DDriverMode = D3DSoftwareRampDriver;
+ ScanDrawMode = ScanDrawD3DRamp;
+ }
+ else if ((SoftwareScanDrawRequestMode == RequestScanDrawDirectDraw)
+ || (SoftwareScanDrawRequestMode == RequestScanDrawDefault))
+ {
+ int i=0;
+ BOOL EarlyExit = No;
+
+ // Set ramp driver anyway for convenience
+ do
+ {
+ if ((!d3d.Driver[i].Hardware) &&
+ (d3d.Driver[i].Desc.dcmColorModel == D3DCOLOR_MONO))
+ {
+ d3d.CurrentDriver = i;
+ EarlyExit = Yes;
+ }
+ }
+ while ((++i < d3d.NumDrivers) && !EarlyExit);
+
+ D3DDriverMode = D3DSoftwareRampDriver;
+ ScanDrawMode = ScanDrawDirectDraw;
+ }
+ else // bollocks
+ {
+ ReleaseDirect3D();
+ exit(0xdeaf);
+ }
+
+ #if SupportZBuffering
+ if (ZBufferRequestMode == RequestZBufferAlways)
+ {
+ if (d3d.Driver[d3d.CurrentDriver].ZBuffer)
+ ZBufferMode = ZBufferOn;
+ else
+ ZBufferMode = ZBufferOff;
+ }
+ else if (ZBufferRequestMode == RequestZBufferDefault)
+ {
+ if ((d3d.Driver[d3d.CurrentDriver].ZBuffer)
+ && (d3d.Driver[d3d.CurrentDriver].Hardware))
+ ZBufferMode = ZBufferOn;
+ else
+ ZBufferMode = ZBufferOff;
+ }
+ else
+ ZBufferMode = ZBufferOff;
+ #endif
+
+
+ // Overrides for test purposes only
+
+ #if ForceRampDriver
+ d3d.CurrentDriver = 0;
+ D3DDriverMode = D3DSoftwareRampDriver;
+ ScanDrawMode = ScanDrawD3DRamp;
+ #endif
+
+ #if ForceRGBDriver
+ d3d.CurrentDriver = 1;
+ D3DDriverMode = D3DSoftwareRGBDriver;
+ ScanDrawMode = ScanDrawD3DSoftwareRGB;
+ #endif
+
+ #if ForceHardwareDriver
+ d3d.CurrentDriver = 2;
+ D3DDriverMode = D3DHardwareRGBDriver;
+ ScanDrawMode = ScanDrawD3DHardwareRGB;
+ #endif
+
+ #if ForceDirectDraw
+ d3d.CurrentDriver = 0;
+ D3DDriverMode = D3DSoftwareRampDriver;
+ ScanDrawMode = ScanDrawDirectDraw;
+ #endif
+
+}
+
+#if SUPPORT_MMX
+int use_mmx_math;
+void SelectMMXOptions(void)
+{
+ if (MMXAvailable)
+ use_mmx_math = 1;
+ else
+ use_mmx_math = 0;
+}
+#endif
+
+// Initialise temporary D3D object and then destroy
+// it again, SOLELY for the purpose of determining
+// whether hardware acceleration is available
+
+// NOTE THIS -->MUST<-- BE RUN -->AFTER<--
+// InitialiseDirectDrawObject!!!
+
+BOOL TestInitD3DObject(void)
+{
+ // Zero hardware available global
+ D3DHardwareAvailable = No;
+
+// Zero d3d structure
+ memset(&d3d, 0, sizeof(D3DINFO));
+
+// Set up Direct3D interface object
+ LastError = lpDD->QueryInterface(IID_IDirect3D, (LPVOID*) &d3d.lpD3D);
+
+ if (LastError != DD_OK)
+ return FALSE;
+
+// Use callback function to enumerate available devices on system
+// and acquire device GUIDs etc
+
+ LastError = d3d.lpD3D->EnumDevices(DeviceEnumerator, (LPVOID)&StartDriver);
+
+ if (LastError != D3D_OK)
+ return FALSE;
+
+ // select the usual driver - get its description
+ int old_rrm = RasterisationRequestMode;
+ RasterisationRequestMode = RequestDefaultRasterisation;
+ SelectD3DDriverAndDrawMode();
+ d3d.ThisDriver = d3d.Driver[d3d.CurrentDriver].Desc;
+ RasterisationRequestMode = old_rrm;
+
+// THE TEXTURE FORMATS ENUMERATOR COULD ALSO BE CALLED HERE TO DETERMINE
+// WHETHER PALETTISED FORMATS ETC ARE AVAILABLE.
+
+// NOTE THAT GETAVAILABLEVIDEOMEMORY (IN DD_FUNC.CPP) CAN BE USED TO REPORT
+// THE FREE VIDEO MEMORY AT ANY TIME.
+
+
+// Eliminate Direct3D object again
+ RELEASE(d3d.lpD3D);
+
+// Code to reset video mode depending on
+// presence of hardware acceleration should
+// go here. NOTE THAT AT A LATER DATE THIS CODE
+// MUST ALSO TAKE ACCOUNT OF THE SETTING OF
+// MMXAVAILABLE AND SUCH INFORMATION IN THE D3DINFO
+// STRUCTURE AS DOES THE DRIVER DO TEXTURES
+// OR Z-BUFFERING. FIXME!!!
+
+ #if 0
+ if ((D3DHardwareAvailable) &&
+ (RasterisationRequestMode == RequestDefaultRasterisation))
+ {
+ if ((VideoMode == VideoMode_DX_320x200x8) ||
+ (VideoMode == VideoMode_DX_320x240x8))
+ {
+ if (CheckForVideoModes(VideoMode_DX_320x200x15))
+ {
+ VideoMode = VideoMode_DX_320x200x15;
+ return TRUE;
+ }
+ else if (CheckForVideoModes(VideoMode_DX_640x480x15))
+ {
+ VideoMode = VideoMode_DX_640x480x15;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ else if (VideoMode == VideoMode_DX_640x480x8)
+ {
+ if (CheckForVideoModes(VideoMode_DX_640x480x15))
+ {
+ VideoMode = VideoMode_DX_640x480x15;
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ }
+ #else
+ // test only!!!
+ {
+ if (D3DHardwareAvailable)
+ TestHw = Yes;
+ else
+ TestHw = No;
+ }
+ #endif
+
+ return TRUE;
+}
+
+// Function to test access speed of VRAM
+// against system memory using the DD blt
+// members, and set DXMemoryMode using this
+// result and the DXMemoryRequestMode as a basis.
+// Note that we must allow for bank flipping
+// speed.
+// Potentially we should also test processor
+// copy against video card blitter if the blitter
+// is in hardware, since some blitters can be slower
+// than the system processor.
+
+// THIS FUNCTION HAS NOT YET BEEN DONE, SEEING AS IT
+// DOESN'T ACTUALLY MAKE MUCH DIFFERENCE TO THE SPEED
+// IN PRACTICE.
+
+// NOTE ALSO that DXMemoryMode has itself
+// not yet been fully implemented, since with
+// all buffers forced into system memory DD
+// doesn't seem to work properly anyway...
+
+// NOTE, HOWEVER, THAT THIS FUNCTION MUST READ
+// MMXAvailable and D3DHardwareAvailable,
+// since if MMX driver is picked we want the
+// back buffer in SYSTEM memory, not video
+// (as of 26 / 7 / 96).
+
+// MUST PUT BACK BUFFER IN VIDEO MEMORY ON
+// AN ACCELERATOR!!!
+
+BOOL TestMemoryAccess(void)
+
+{
+ // We take this request AT IT'S WORD, i.e. to mean
+ // that we will always do our best to provide a system
+ // memory target. Note that this means that if we then
+ // go on to boot up on hardware nothing will actually appear
+ // on the screen, though the debugger should work (in SubWindow
+ // mode, obviously). A more subtle test might be appropriate here,
+ // though it IS a debugging thing...
+ if (DXMemoryRequestMode == RequestSystemMemoryAlways)
+ DXMemoryMode = SystemMemoryPreferred;
+ else // assume default
+ {
+ // Note that at this stage we have a DirectDraw object on which
+ // to run GetCaps, we have detected the processor type and we have run
+ // TestInitD3DObject, so we have determined whether or not hardware
+ // acceleration is available.
+
+ // Rendering target must be in VRAM if we are to run accelerated.
+ // Note that we really want to know whether we are going to run
+ // accelerated, not whether we can do, but this requires integration
+ // with the project's rules for deciding on its running mode.
+ // This function should probably be moved to d3_proj.cpp along
+ // with SelectD3DDriverAndMode and TestInitD3DObject...
+ if (D3DHardwareAvailable)
+ DXMemoryMode = VideoMemoryPreferred;
+ // For MMX we are currently assuming a high scan draw throughput,
+ // as VideoModeType_15 is likely to be the optimal solution, which
+ // is liable to result in a system gated by VRAM speed for a video
+ // memory rendering target. For this system we therfore want a system
+ // memory target.
+ else if (MMXAvailable)
+ DXMemoryMode = SystemMemoryPreferred;
+ // We are now assuming a DirectDraw software solution with our
+ // scan draws, on a standard(ish) video card. At this point we need
+ // to make an intelligent decision, remembering that in practice
+ // system memory targets are rarely faster than video memory ones
+ // for this situation.
+ else
+ {
+ // On the basis of experiment, these are the important
+ // video card capabilities for 3dc.
+ BOOL Flip;
+ BOOL BlitSysMem;
+ BOOL BlitVidMem;
+ BOOL BlitFloodFill;
+ BOOL BlitAsyncQueue;
+ BOOL BankSwitched;
+ // Timing factors
+ int TimeForVramWrite;
+ int TimeForSysMemWrite;
+ unsigned char* SurfacePtr;
+ // DirectX intfc
+ DDCAPS ddcaps;
+ HRESULT ddrval;
+ LPDIRECTDRAWSURFACE lpTestSurf;
+ DDSURFACEDESC ddsd;
+ // etc
+ int i;
+ int TestSurfHeight = 480;
+ int TestSurfWidth = 640;
+
+ // Get caps on the DirectDraw object
+ memset(&ddcaps, 0, sizeof(ddcaps));
+ ddcaps.dwSize = sizeof(ddcaps);
+ ddrval = lpDD->GetCaps(&ddcaps, NULL);
+ LOGDXERR(ddrval);
+
+ if (ddrval != DD_OK)
+ #if debug
+ {
+ ReleaseDirect3D();
+ exit(ddrval);
+ }
+ #else
+ {
+ return FALSE;
+ }
+ #endif
+
+ if (ddcaps.dwCaps & DDCAPS_BLT)
+ BlitVidMem = TRUE;
+ else
+ BlitVidMem = FALSE;
+
+ if (ddcaps.dwCaps & DDCAPS_BANKSWITCHED)
+ BankSwitched = TRUE;
+ else
+ BankSwitched = FALSE;
+
+ if (ddcaps.dwCaps & DDCAPS_BLTCOLORFILL)
+ BlitFloodFill = TRUE;
+ else
+ BlitFloodFill = FALSE;
+
+ if (ddcaps.dwCaps & DDCAPS_BLTQUEUE)
+ BlitAsyncQueue = TRUE;
+ else
+ BlitAsyncQueue = FALSE;
+
+ if (ddcaps.dwCaps & DDCAPS_CANBLTSYSMEM)
+ BlitSysMem = TRUE;
+ else
+ BlitSysMem = FALSE;
+
+ if (ddcaps.ddsCaps.dwCaps & DDSCAPS_FLIP)
+ Flip = TRUE;
+ else
+ Flip = FALSE;
+
+ // Creating surfaces like this before setting exclusive mode
+ // und so weiter seems to REALLY UPSET IT. So for now, we
+ // shall say sod it and decide purely on the basis of the caps.
+ #if 0
+ // Create a DD surface in Vram
+ memset(&ddsd,0,sizeof(DDSURFACEDESC));
+ ddsd.dwSize = sizeof(DDSURFACEDESC);
+ ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
+ // 640 x 480 would be a typical screen
+ ddsd.dwHeight = TestSurfHeight;
+ ddsd.dwWidth = TestSurfWidth;
+ ddsd.ddsCaps.dwCaps= (DDSCAPS_OFFSCREENPLAIN);
+
+ ddrval = lpDD->CreateSurface(&ddsd, &lpTestSurf, NULL);
+ LOGDXERR(ddrval);
+ if (ddrval != DD_OK)
+ #if debug
+ {
+ ReleaseDirect3D();
+ exit(ddrval);
+ }
+ #else
+ return FALSE;
+ #endif
+
+ SurfacePtr = (unsigned char*) ddsd.lpSurface;
+
+ // Time write
+ TimeForVramWrite = timeGetTime();
+ for (i=0; i<TestSurfHeight; i++)
+ {
+ memset(SurfacePtr, 0, TestSurfWidth);
+ SurfacePtr += ddsd.lPitch;
+ }
+ TimeForVramWrite = (timeGetTime() - TimeForVramWrite);
+
+ // Kill the surface
+ ReleaseDDSurface((void*) lpTestSurf);
+
+ // Create a DD surface in System Memory
+ memset(&ddsd,0,sizeof(DDSURFACEDESC));
+ ddsd.dwSize = sizeof(DDSURFACEDESC);
+ ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
+ // 640 x 480 would be a typical screen
+ ddsd.dwHeight = TestSurfHeight;
+ ddsd.dwWidth = TestSurfWidth;
+ ddsd.ddsCaps.dwCaps= (DDSCAPS_OFFSCREENPLAIN
+ | DDSCAPS_SYSTEMMEMORY);
+
+ ddrval = lpDD->CreateSurface(&ddsd, &lpTestSurf, NULL);
+ LOGDXERR(ddrval);
+ if (ddrval != DD_OK)
+ #if debug
+ {
+ ReleaseDirect3D();
+ exit(ddrval);
+ }
+ #else
+ return FALSE;
+ #endif
+
+ SurfacePtr = (unsigned char*) ddsd.lpSurface;
+
+ // Time write
+ TimeForSysMemWrite = timeGetTime();
+ for (i=0; i<TestSurfHeight; i++)
+ {
+ memset(SurfacePtr, 0, TestSurfWidth);
+ SurfacePtr += ddsd.lPitch;
+ }
+ TimeForSysMemWrite = (timeGetTime() - TimeForSysMemWrite);
+
+ ReleaseDDSurface((void*) lpTestSurf);
+ #endif
+
+ // Now decide!!!!
+ // Benchmarking memory speed at this point in the initialisation
+ // sequence seems tricky, so for now we shall simply try deciding on
+ // the basis of the caps, seeing as video memory always seems faster
+ // even on dubious 1992 cards anyway. This should probably be fixed,
+ // though.
+ if (Flip || BlitSysMem || BlitFloodFill || BlitAsyncQueue)
+ DXMemoryMode = VideoMemoryPreferred;
+ else
+ DXMemoryMode = SystemMemoryPreferred;
+ }
+ }
+
+ return TRUE;
+}
+
+
+// For extern "C"
+
+};
+