/*========================================================================== * * Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved. * * File: d3dtest.cpp * ***************************************************************************/ #define INITGUID //#define NOTOPMOST_WINDOW #include #include #include #include #include #include #include #include #include "resource.h" #include "polytest.h" #include "pixtest.h" #include "globals.h" #include "d3dtextr.h" #include "d3dmacs.h" #include "error.h" #define OVERDRAW_IN_PIXEL_TEST 5 #define OBJECTS_IN_THROUGHPUT_TEST 8 #define RINGS_IN_THROUGHPUT_TEST 30 #define SEGS_IN_THROUGHPUT_TEST 30 #define D_IN_THROUGHPUT_TEST 1.0f #define DEPTH_IN_THROUGHPUT_TEST 0.6f #define R_IN_THROUGHPUT_TEST 0.4f #define DV_IN_THROUGHPUT_TEST 0.05f #define DR_IN_THROUGHPUT_TEST 0.3f #define OBJECTS_IN_INTERSECTION_TEST 16 #define RINGS_IN_INTERSECTION_TEST 5 #define SEGS_IN_INTERSECTION_TEST 6 #define D_IN_INTERSECTION_TEST 1.6f #define DEPTH_IN_INTERSECTION_TEST 0.2f #define R_IN_INTERSECTION_TEST 0.7f #define DV_IN_INTERSECTION_TEST 0.06f #define DR_IN_INTERSECTION_TEST 0.2f #define TEST_INTERVAL 10 #define STARTUP_INTERVAL 2 /************************************************************************* Internal Function Declarations *************************************************************************/ void CleanUpAndPostQuit(void); void InitGlobals(void); BOOL LoadTextures(void); void ReleaseTextures(void); BOOL RunPolyTest(float *lpResult); BOOL RunPixelTest(UINT order, float *lpResult); BOOL RunIntersectionTest(UINT order, float *lpResult); BOOL SetRenderState(void); long FreeVideoMemory(void); HRESULT CreateDDSurface(LPDDSURFACEDESC lpDDSurfDesc, LPDIRECTDRAWSURFACE FAR *lpDDSurface, IUnknown FAR *pUnkOuter); BOOL ReleaseD3D(void); void ReleaseExeBuffers(void); void dpf( LPSTR fmt, ... ); /************************************************************************ Globals ************************************************************************/ /* * Info structures */ DDInfo dd; D3DInfo d3d; AppInfo app; StatInfo stat; TexInfo tex; int NumTextureFormats; DDSURFACEDESC TextureFormat[10]; int dx, dy; /* * Last DD or D3D error */ HRESULT LastError; /* * What it's all about */ #define RESET_TEST 0 #define THROUGHPUT_TEST 1 #define FILL_RATE_TEST 2 #define INTERSECTION_TEST 3 time_t StartTime; float LastFillRate, PeakFillRateF2B, PeakFillRateB2F; float LastIntersectionThroughput, PeakIntersectionThroughputF2B, PeakIntersectionThroughputB2F; float LastThroughput, PeakThroughput; BOOL IsHardware = FALSE; DWORD ZDepth, ZType; BOOL CanSpecular = FALSE; BOOL CanCopy = FALSE; BOOL CanMono = FALSE; BOOL CanRGB = FALSE; BOOL NoUpdates = FALSE; /************************************************************************* Window shit *************************************************************************/ /* * WindowProc * Window message handler. */ long FAR PASCAL WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) { POINT p1, p2; switch( message ) { case WM_CREATE: break; case WM_ACTIVATEAPP: app.bAppActive = (BOOL)wParam; break; case WM_SETCURSOR: break; case WM_DESTROY: break; case WM_MOVE: if (app.bFullscreen) break; p1.x = p1.y = 0; ClientToScreen(app.hWnd, &p1); p2.x = 400; p2.y = 400; ClientToScreen(app.hWnd, &p2); SetRect(&app.rcClient, p1.x, p1.y, p2.x, p2.y); break; case WM_SIZE: if (app.bIgnoreWM_SIZE) break; return TRUE; break; case WM_ACTIVATE: if (stat.bHandleActivate && stat.bPrimaryPalettized) { dd.lpFrontBuffer->SetPalette(dd.lpPalette); } break; default: break; } return DefWindowProc(hWnd, message, wParam, lParam); } BOOL CreateHWND(UINT x, UINT y) { static int first = 1; RECT rc; POINT p1, p2; DWORD dwStyle; if (first) { WNDCLASS wc; first = 0; /* * set up and register window class */ wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WindowProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = app.hInstApp; wc.hIcon = 0; wc.hCursor = LoadCursor( NULL, IDC_ARROW ); wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszMenuName = NULL; wc.lpszClassName = "Direct3D Test"; if (!RegisterClass(&wc)) return FALSE; } /* * create a window */ app.bIgnoreWM_SIZE = TRUE; app.hWnd = CreateWindow( "Direct3D Test", "Direct3D Test", 0, 0,0,x,y, app.hDlg, /* parent window */ NULL, /* menu handle */ app.hInstApp, /* program handle */ NULL); /* create parms */ if (!app.hWnd){ Msg("CreateWindow failed"); return FALSE; } UpdateWindow(app.hWnd); /* * Convert to a normal app window if we are still a WS_POPUP window. */ dwStyle = GetWindowLong(app.hWnd, GWL_STYLE); dwStyle &= ~WS_POPUP; dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME; SetWindowLong(app.hWnd, GWL_STYLE, dwStyle); SetRect(&rc, 0, 0, 400, 400); AdjustWindowRectEx(&rc, GetWindowLong(app.hWnd, GWL_STYLE), GetMenu(app.hWnd) != NULL, GetWindowLong(app.hWnd, GWL_EXSTYLE)); SetWindowPos(app.hWnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); #ifndef NOTOPMOST_WINDOW SetWindowPos(app.hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW); #else SetWindowPos(app.hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW); #endif app.bIgnoreWM_SIZE = FALSE; p1.x = p1.y = 0; ClientToScreen(app.hWnd, &p1); p2.x = 400; p2.y = 400; ClientToScreen(app.hWnd, &p2); SetRect(&app.rcClient, p1.x, p1.y, p2.x, p2.y); return TRUE; } /*********************************************************************************** Initialization and release ***********************************************************************************/ /* * GetDDSurfaceDesc * Gets a surface description. */ BOOL GetDDSurfaceDesc(LPDDSURFACEDESC lpDDSurfDesc, LPDIRECTDRAWSURFACE lpDDSurf) { memset(lpDDSurfDesc, 0, sizeof(DDSURFACEDESC)); lpDDSurfDesc->dwSize = sizeof(DDSURFACEDESC); LastError = lpDDSurf->GetSurfaceDesc(lpDDSurfDesc); if (LastError != DD_OK) { Msg("Error getting a surface description.\n%s", MyErrorToString(LastError)); CleanUpAndPostQuit(); return FALSE; } return TRUE; } /* * InitDD * Given an HWND, creates DD surfaces */ BOOL InitDD(HWND hwnd, UINT x, UINT y) { DDSURFACEDESC ddsd; if (app.bFullscreen) { DDSCAPS ddscaps; /* * Create a complex flipping surface for fullscreen mode. */ app.bIgnoreWM_SIZE = TRUE; LastError = dd.lpDD->SetCooperativeLevel(hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); app.bIgnoreWM_SIZE = FALSE; if (LastError != DD_OK ) { app.bFullscreen = FALSE; Msg("SetCooperativeLevel failed.\n%s", MyErrorToString(LastError)); return FALSE; } app.bIgnoreWM_SIZE = TRUE; LastError = dd.lpDD->SetDisplayMode(dd.ModeList[dd.CurrentMode].w, dd.ModeList[dd.CurrentMode].h, dd.ModeList[dd.CurrentMode].bpp); app.bIgnoreWM_SIZE = FALSE; if(LastError != DD_OK ) { app.bFullscreen = FALSE; Msg("SetDisplayMode (%dx%dx%d) failed\n%s", dd.ModeList[dd.CurrentMode].w, dd.ModeList[dd.CurrentMode].h, dd.ModeList[dd.CurrentMode].bpp, MyErrorToString(LastError)); return FALSE; } dx = (int)((float)(dd.ModeList[dd.CurrentMode].w - x) / (float)2.0); dy = (int)((float)(dd.ModeList[dd.CurrentMode].h - y) / (float)2.0); SetRect(&app.rcClient, dx, dy, dx+400, dy+400); memset(&ddsd,0,sizeof(DDSURFACEDESC)); ddsd.dwSize = sizeof( ddsd ); ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_3DDEVICE | DDSCAPS_COMPLEX; ddsd.dwBackBufferCount = 1; LastError = CreateDDSurface(&ddsd, &dd.lpFrontBuffer, NULL ); if(LastError != DD_OK) { Msg("CreateSurface for front/back fullscreen buffer failed.\n%s", MyErrorToString(LastError)); return FALSE; } ddscaps.dwCaps = DDSCAPS_BACKBUFFER; LastError = dd.lpFrontBuffer->GetAttachedSurface(&ddscaps, &dd.lpBackBuffer); if(LastError != DD_OK) { Msg("GetAttachedSurface failed to get back buffer.\n%s", MyErrorToString(LastError)); return FALSE; } if (!GetDDSurfaceDesc(&ddsd, dd.lpBackBuffer)) return FALSE; if (!(ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) { RELEASE(dd.lpBackBuffer); RELEASE(dd.lpFrontBuffer); Msg("Backbuffer failed to go into video memory for fullscreen test.\n"); return FALSE; } } else { memset(&ddsd,0,sizeof(DDSURFACEDESC)); ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.dwFlags = DDSD_CAPS; ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; LastError = CreateDDSurface(&ddsd, &dd.lpFrontBuffer, NULL); if(LastError != DD_OK ) { Msg("CreateSurface for window front buffer failed.\n%s", MyErrorToString(LastError)); return FALSE; } ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS; ddsd.dwHeight = y; ddsd.dwWidth = x; ddsd.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE; if (stat.bOnlySystemMemory) ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; LastError = CreateDDSurface(&ddsd, &dd.lpBackBuffer, NULL); if (LastError != DD_OK) { RELEASE(dd.lpFrontBuffer); Msg("CreateSurface for window back buffer failed.\n%s", MyErrorToString(LastError)); return FALSE; } if (!GetDDSurfaceDesc(&ddsd, dd.lpBackBuffer)) return FALSE; if (!(ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) stat.bOnlySoftRender = TRUE; if (IsHardware && stat.bOnlySoftRender) { RELEASE(dd.lpFrontBuffer); RELEASE(dd.lpBackBuffer); Msg("There was not enough free video memory for the front and/or back buffers for this hardware D3D device.\n"); return FALSE; } /* * Create a DirectDrawClipper object. */ LastError = dd.lpDD->CreateClipper(0, &dd.lpClipper, NULL); if(LastError != DD_OK ) { RELEASE(dd.lpFrontBuffer); RELEASE(dd.lpBackBuffer); Msg("CreateClipper failed.\n%s", MyErrorToString(LastError)); return FALSE; } LastError = dd.lpClipper->SetHWnd(0, hwnd); if(LastError != DD_OK ) { RELEASE(dd.lpFrontBuffer); RELEASE(dd.lpBackBuffer); RELEASE(dd.lpClipper); Msg("Clipper SetHWnd failed.\n%s", MyErrorToString(LastError)); return FALSE; } LastError = dd.lpFrontBuffer->SetClipper(dd.lpClipper); if(LastError != DD_OK ) { RELEASE(dd.lpFrontBuffer); RELEASE(dd.lpBackBuffer); RELEASE(dd.lpClipper); Msg("SetClipper failed.\n%s", MyErrorToString(LastError)); return FALSE; } } /* * Palettize if we are not in a 16-bit mode. */ if (!GetDDSurfaceDesc(&ddsd, dd.lpBackBuffer)) return FALSE; if (ddsd.ddpfPixelFormat.dwRGBBitCount < 16) { stat.bPrimaryPalettized = TRUE; } else { stat.bPrimaryPalettized = FALSE; } if (stat.bPrimaryPalettized) { int i; HDC hdc = GetDC(NULL); GetSystemPaletteEntries(hdc, 0, (1 << 8), dd.ppe); ReleaseDC(NULL, hdc); for (i = 0; i < 10; i++) dd.ppe[i].peFlags = D3DPAL_READONLY; for (i = 10; i < 256 - 10; i++) dd.ppe[i].peFlags = PC_RESERVED; for (i = 256 - 10; i < 256; i++) dd.ppe[i].peFlags = D3DPAL_READONLY; LastError = dd.lpDD->CreatePalette(DDPCAPS_8BIT | DDPCAPS_INITIALIZE, dd.ppe, &dd.lpPalette, NULL); if (LastError != DD_OK) { RELEASE(dd.lpFrontBuffer); RELEASE(dd.lpBackBuffer); RELEASE(dd.lpClipper); Msg("CreatePalette failed.\n%s", MyErrorToString(LastError)); return FALSE; } LastError = dd.lpBackBuffer->SetPalette(dd.lpPalette); if(LastError != DD_OK ) { RELEASE(dd.lpFrontBuffer); RELEASE(dd.lpBackBuffer); RELEASE(dd.lpClipper); RELEASE(dd.lpPalette); Msg("SetPalette back failed.\n%s", MyErrorToString(LastError)); return FALSE; } LastError = dd.lpFrontBuffer->SetPalette(dd.lpPalette); if(LastError != DD_OK ) { RELEASE(dd.lpFrontBuffer); RELEASE(dd.lpBackBuffer); RELEASE(dd.lpClipper); RELEASE(dd.lpPalette); Msg("SetPalette failed.\n%s", MyErrorToString(LastError)); return FALSE; } stat.bHandleActivate = TRUE; } return TRUE; } BOOL ReleaseDD(void) { stat.bHandleActivate = FALSE; RELEASE(dd.lpPalette); RELEASE(dd.lpClipper); RELEASE(dd.lpBackBuffer); RELEASE(dd.lpFrontBuffer); if (app.bFullscreen && dd.lpDD) { dd.lpDD->SetCooperativeLevel(app.hWnd, DDSCL_NORMAL); } return TRUE; } BOOL CreateZBuffer(UINT x, UINT y, DWORD depth, DWORD memorytype) { LPDIRECTDRAWSURFACE lpZBuffer; DDSURFACEDESC ddsd; /* * Create a Z-Buffer and attach it to the back buffer. */ if (app.bFullscreen) { x = dd.ModeList[dd.CurrentMode].w; y = dd.ModeList[dd.CurrentMode].h; } memset(&ddsd,0,sizeof(DDSURFACEDESC)); ddsd.dwSize = sizeof(DDSURFACEDESC); ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_ZBUFFERBITDEPTH; ddsd.dwHeight = y; ddsd.dwWidth = x; ddsd.dwZBufferBitDepth = depth; ddsd.ddsCaps.dwCaps= DDSCAPS_ZBUFFER | memorytype; LastError = CreateDDSurface(&ddsd, &lpZBuffer, NULL); if (LastError != DD_OK) { Msg("CreateSurface for window Z-buffer failed.\n%s", MyErrorToString(LastError)); return FALSE; } if (!GetDDSurfaceDesc(&ddsd, lpZBuffer)) return FALSE; if (!(ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) stat.bOnlySoftRender = TRUE; if (IsHardware && stat.bOnlySoftRender) { RELEASE(dd.lpZBuffer); Msg("Did not have enough free video memory for Z-buffer for this hardware D3D device.\n"); return FALSE; } LastError = dd.lpBackBuffer->AddAttachedSurface(lpZBuffer); if(LastError != DD_OK) { Msg("AddAttachedBuffer failed for Z-buffer.\n%s",MyErrorToString(LastError)); return FALSE; } dd.lpZBuffer = lpZBuffer; return TRUE; } HRESULT CALLBACK EnumTextureFormatsCallback(LPDDSURFACEDESC lpDDSD, LPVOID lpContext) { if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4) return DDENUMRET_OK; memcpy(&TextureFormat[NumTextureFormats], lpDDSD, sizeof(DDSURFACEDESC)); NumTextureFormats++; return DDENUMRET_OK; } BOOL InitializeTextureLoad(LPDIRECT3DDEVICE lpD3DDevice) { HRESULT ddrval; NumTextureFormats = 0; ddrval = lpD3DDevice->EnumTextureFormats(EnumTextureFormatsCallback, NULL); if(ddrval != D3D_OK ) { return FALSE; } return TRUE; } /* * InitD3D * Initializes the D3D device and creates the viewport. */ BOOL InitD3D(LPGUID lpGuid, UINT x, UINT y) { if (stat.bZBufferOn) { if (!CreateZBuffer(x, y, ZDepth, ZType)) return FALSE; } /* * Create the device */ LastError = dd.lpBackBuffer->QueryInterface(*lpGuid, (LPVOID*)&d3d.lpD3DDevice); if (LastError != DD_OK) { Msg("Create D3D device failed.\n%s", MyErrorToString(LastError)); return FALSE; } if (!stat.bTexturesDisabled && !InitializeTextureLoad(d3d.lpD3DDevice)) return FALSE; /* * Create and setup the viewport which is scaled to the screen mode */ LastError = d3d.lpD3D->CreateViewport(&d3d.lpD3DViewport, NULL); if (LastError != D3D_OK) { Msg("Create D3D viewport failed.\n%s", MyErrorToString(LastError)); return FALSE; } LastError = d3d.lpD3DDevice->AddViewport(d3d.lpD3DViewport); if (LastError != D3D_OK) { Msg("Add D3D viewport failed.\n%s", MyErrorToString(LastError)); return FALSE; } D3DVIEWPORT viewData; memset(&viewData, 0, sizeof(D3DVIEWPORT)); viewData.dwSize = sizeof(D3DVIEWPORT); if (app.bFullscreen) { viewData.dwX = app.rcClient.left; viewData.dwY = app.rcClient.top; } else { viewData.dwX = viewData.dwY = 0; } viewData.dwWidth = x; viewData.dwHeight = y; viewData.dvScaleX = viewData.dwWidth / (float)2.0; viewData.dvScaleY = viewData.dwHeight / (float)2.0; viewData.dvMaxX = (float)D3DDivide(D3DVAL(viewData.dwWidth), D3DVAL(2 * viewData.dvScaleX)); viewData.dvMaxY = (float)D3DDivide(D3DVAL(viewData.dwHeight),D3DVAL(2 * viewData.dvScaleY)); LastError = d3d.lpD3DViewport->SetViewport(&viewData); if (LastError != D3D_OK) { Msg("SetViewport failed.\n%s", MyErrorToString(LastError)); return FALSE; } return TRUE; } BOOL ReleaseD3D(void) { RELEASE(d3d.lpD3DViewport); RELEASE(d3d.lpD3DDevice); RELEASE(dd.lpZBuffer); return TRUE; } /* * CreateD3DWindow * Creates a D3D window of the given size. * Load textures and sets the render state. */ BOOL CreateD3DWindow(LPGUID lpDeviceGUID) { stat.bOnlySoftRender = FALSE; if (!CreateHWND(400, 400)) return FALSE; /* * Initialize fullscreen DD and the D3DDevice */ if (!(InitDD(app.hWnd, 400, 400))) { SetWindowPos(app.hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE| SWP_HIDEWINDOW); DestroyWindow(app.hWnd); return FALSE; } if (!(InitD3D(lpDeviceGUID, 400, 400))) { SetWindowPos(app.hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE| SWP_HIDEWINDOW); DestroyWindow(app.hWnd); ReleaseDD(); return FALSE; } /* * Load the textures. */ if (!(LoadTextures())) { SetWindowPos(app.hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE| SWP_HIDEWINDOW); DestroyWindow(app.hWnd); ReleaseD3D(); ReleaseDD(); return FALSE; } /* * Set the render state */ if (!(SetRenderState())) { SetWindowPos(app.hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE| SWP_HIDEWINDOW); DestroyWindow(app.hWnd); ReleaseTextures(); ReleaseD3D(); ReleaseDD(); return FALSE; } return TRUE; } BOOL ReleaseD3DWindow(void) { if (app.bFullscreen && dd.lpDD) { dd.lpDD->RestoreDisplayMode(); } SetWindowPos(app.hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE| SWP_HIDEWINDOW); ReleaseTextures(); ReleasePathList(); if (!(ReleaseD3D())) return FALSE; if (!(ReleaseDD())) return FALSE; DestroyWindow(app.hWnd); return TRUE; } /********************************************************************************* Connection and disconnection *********************************************************************************/ BOOL FAR PASCAL DDEnumCallback(GUID FAR* lpGUID, LPSTR lpDriverDesc, LPSTR lpDriverName, LPVOID lpContext) { LPDIRECTDRAW lpDD; DDCAPS DriverCaps, HELCaps; lpContext; if (lpGUID) { LastError = DirectDrawCreate(lpGUID, &lpDD, NULL); if (LastError != DD_OK) { Msg("Failing while creating a DD device for testing. Continuing with execution.\n%s", MyErrorToString(LastError)); return DDENUMRET_OK; } memset(&DriverCaps, 0, sizeof(DDCAPS)); DriverCaps.dwSize = sizeof(DDCAPS); memset(&HELCaps, 0, sizeof(DDCAPS)); HELCaps.dwSize = sizeof(DDCAPS); LastError = lpDD->GetCaps(&DriverCaps, &HELCaps); if (LastError != DD_OK) { Msg("GetCaps failed in while testing a DD device. Continuing with execution.\n%s", MyErrorToString(LastError)); RELEASE(dd.lpDD); return DDENUMRET_OK; } RELEASE(dd.lpDD); if (DriverCaps.dwCaps & DDCAPS_3D) { /* * We have found a 3d hardware device */ memcpy(&dd.Driver[dd.NumDrivers].guid, lpGUID, sizeof(GUID)); memcpy(&dd.Driver[dd.NumDrivers].HWCaps, &DriverCaps, sizeof(DDCAPS)); lstrcpy(dd.Driver[dd.NumDrivers].Name, lpDriverName); dd.Driver[dd.NumDrivers].bIsPrimary = FALSE; dd.CurrentDriver = dd.NumDrivers; ++dd.NumDrivers; if (dd.NumDrivers == 5) return (D3DENUMRET_CANCEL); } } else { /* * It's the primary, fill in some fields. */ dd.Driver[dd.NumDrivers].bIsPrimary = TRUE; lstrcpy(dd.Driver[dd.NumDrivers].Name, "Primary Device"); dd.CurrentDriver = dd.NumDrivers; ++dd.NumDrivers; if (dd.NumDrivers == 5) return (D3DENUMRET_CANCEL); } return DDENUMRET_OK; } BOOL EnumDDDrivers() { dd.NumDrivers = 0; dd.CurrentDriver = 0; LastError = DirectDrawEnumerate(DDEnumCallback, NULL); if (LastError != DD_OK) { Msg("DirectDrawEnumerate failed.\n%s", MyErrorToString(LastError)); return FALSE; } return TRUE; } /* * GetDDCaps * Determines Z buffer depth. */ BOOL GetDDCaps(void) { DDCAPS DriverCaps, HELCaps; memset(&DriverCaps, 0, sizeof(DriverCaps)); DriverCaps.dwSize = sizeof(DDCAPS); memset(&HELCaps, 0, sizeof(HELCaps)); HELCaps.dwSize = sizeof(DDCAPS); LastError = dd.lpDD->GetCaps(&DriverCaps, &HELCaps); if (LastError != DD_OK) { Msg("GetCaps failed in while checking driver capabilities.\n%s", MyErrorToString(LastError)); return FALSE; } memcpy(&dd.HWddsCaps, &DriverCaps.ddsCaps, sizeof(DDSCAPS)); return TRUE; } /* * enumDeviceFunc * Enumeration function for EnumDevices */ HRESULT WINAPI enumDeviceFunc(LPGUID lpGuid, LPSTR lpDeviceDescription, LPSTR lpDeviceName, LPD3DDEVICEDESC lpHWDesc, LPD3DDEVICEDESC lpHELDesc, LPVOID lpContext) { d3d.Driver[d3d.NumDrivers].lpGuid = lpGuid; lstrcpy(d3d.Driver[d3d.NumDrivers].Desc, lpDeviceDescription); lstrcpy(d3d.Driver[d3d.NumDrivers].Name, lpDeviceName); memcpy(&d3d.Driver[d3d.NumDrivers].HWDesc, lpHWDesc, sizeof(D3DDEVICEDESC)); memcpy(&d3d.Driver[d3d.NumDrivers].HELDesc, lpHELDesc, sizeof(D3DDEVICEDESC)); d3d.NumDrivers++; if (d3d.NumDrivers == 5) return (D3DENUMRET_CANCEL); return (D3DENUMRET_OK); } /* * EnumDisplayModesCallback * Callback to save the display mode information. */ HRESULT CALLBACK EnumDisplayModesCallback(LPDDSURFACEDESC pddsd, LPVOID Context) { if (pddsd->dwWidth >= 400 && pddsd->dwHeight >= 400 && pddsd->ddpfPixelFormat.dwRGBBitCount == 16) { dd.ModeList[dd.NumModes].w = pddsd->dwWidth; dd.ModeList[dd.NumModes].h = pddsd->dwHeight; dd.ModeList[dd.NumModes].bpp = pddsd->ddpfPixelFormat.dwRGBBitCount; dd.NumModes++; } return DDENUMRET_OK; } /* * CompareModes * Compare two display modes for sorting purposes. */ int _cdecl CompareModes(const void* element1, const void* element2) { ModeListElement *lpMode1, *lpMode2; lpMode1 = (ModeListElement*)element1; lpMode2 = (ModeListElement*)element2; // XXX if (lpMode1->w < lpMode2->w) return -1; else if (lpMode2->w < lpMode1->w) return 1; else if (lpMode1->h < lpMode2->h) return -1; else if (lpMode2->h < lpMode1->h) return 1; else return 0; } BOOL EnumerateDisplayModes() { LastError = dd.lpDD->EnumDisplayModes(0, NULL, 0, EnumDisplayModesCallback); if(LastError != DD_OK ) { Msg("EnumDisplayModes failed.\n%s", MyErrorToString(LastError)); return FALSE; } qsort((void *)&dd.ModeList[0], (size_t) dd.NumModes, sizeof(ModeListElement), CompareModes); if (dd.NumModes == 0) { Msg("The available display modes are not of sufficient size or are not 16-bit\n"); return FALSE; } dd.CurrentMode = 0; return TRUE; } /* * Connect * Creates the DD and D3D objects, enumerates available devices and * gets the DD capabilites. */ BOOL Connect(void) { if (dd.Driver[dd.CurrentDriver].bIsPrimary) { app.bFullscreen = FALSE; LastError = DirectDrawCreate(NULL, &dd.lpDD, NULL); if (LastError != DD_OK) { Msg("DirectDrawCreate failed.\n%s", MyErrorToString(LastError)); return FALSE; } } else { /* * If it's not the primary device, assume we can only do fullscreen. */ app.bFullscreen = TRUE; LastError = DirectDrawCreate(&dd.Driver[dd.CurrentDriver].guid, &dd.lpDD, NULL); if (LastError != DD_OK) { Msg("DirectDrawCreate failed.\n%s", MyErrorToString(LastError)); return FALSE; } if (!EnumerateDisplayModes()) return FALSE; } app.bIgnoreWM_SIZE = TRUE; LastError = dd.lpDD->SetCooperativeLevel(app.hDlg, DDSCL_NORMAL); if(LastError != DD_OK ) { Msg("SetCooperativeLevel failed.\n%s", MyErrorToString(LastError)); return FALSE; } app.bIgnoreWM_SIZE = FALSE; LastError = dd.lpDD->QueryInterface(IID_IDirect3D, (LPVOID*)&d3d.lpD3D); if (LastError != DD_OK) { Msg("Creation of IDirect3D failed.\n%s", MyErrorToString(LastError)); return FALSE; } GetDDCaps(); d3d.NumDrivers = 0; LastError = d3d.lpD3D->EnumDevices(enumDeviceFunc, NULL); if (LastError != DD_OK) { Msg("EnumDevices failed.\n%s", MyErrorToString(LastError)); return FALSE; } return TRUE; } BOOL Disconnect(void) { RELEASE(d3d.lpD3D); RELEASE(dd.lpDD); return TRUE; } /************************************************************************* Texture map loading *************************************************************************/ /* * CreateVidTex * Create a texture in video memory (if appropriate). * If no hardware exists, this will be created in system memory, but we * can still use load to swap textures. */ BOOL CreateVidTex(LPDIRECTDRAWSURFACE lpSrcSurf, LPDIRECTDRAWSURFACE *lplpDstSurf, LPDIRECT3DTEXTURE *lplpDstTex) { DDSURFACEDESC ddsd; LPDIRECTDRAWPALETTE lpDDPal = NULL; PALETTEENTRY ppe[256]; BOOL bQuant; if (!GetDDSurfaceDesc(&ddsd, lpSrcSurf)) return FALSE; if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) bQuant = TRUE; else bQuant = FALSE; ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT; ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; if (stat.bOnlySystemMemory) ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; LastError = CreateDDSurface(&ddsd, lplpDstSurf, NULL); if (LastError != DD_OK) { Msg("Create surface in CreateVidTexture failed.\n%s", MyErrorToString(LastError)); return FALSE; } if (!GetDDSurfaceDesc(&ddsd, *lplpDstSurf)) return FALSE; if (dd.HWddsCaps.dwCaps & DDSCAPS_TEXTURE && !(ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)) stat.bOnlySoftRender = TRUE; if (IsHardware && stat.bOnlySoftRender) { Msg("Failed to put texture surface in video memory for hardware D3D device.\n"); return FALSE; } if (bQuant) { memset(ppe, 0, sizeof(PALETTEENTRY) * 256); LastError = dd.lpDD->CreatePalette(DDPCAPS_8BIT, ppe, &lpDDPal, NULL); if (LastError != DD_OK) { RELEASE((*lplpDstSurf)); Msg("CreatePalette in CreateVidTexture failed.\n%s", MyErrorToString(LastError)); return FALSE; } LastError = (*lplpDstSurf)->SetPalette(lpDDPal); if (LastError != DD_OK) { RELEASE((*lplpDstSurf)); RELEASE(lpDDPal); Msg("SetPalette in CreateVidTexture failed.\n%s", MyErrorToString(LastError)); return FALSE; } } LastError = (*lplpDstSurf)->QueryInterface(IID_IDirect3DTexture, (LPVOID*)lplpDstTex); if (LastError != D3D_OK) { RELEASE((*lplpDstSurf)); RELEASE(lpDDPal); Msg("QueryInterface in CreateVidTexture failed.\n%s", MyErrorToString(LastError)); return FALSE; } return TRUE; } /* * LoadTextures * If textures are on, load textures from image files. */ BOOL LoadTextures(void) { int i, t; HRESULT ddrval; /* * If textures are not on or are disabled, set all the handles to zero. */ if (!stat.bTexturesOn || stat.bTexturesDisabled) { for (i = 0; i < tex.NumTextures; i++) tex.TextureDstHandle[i] = 0; return TRUE; } /* * Load each image file as a "source" texture surface in system memory. * Load each source texture surface into a "destination" texture (in video * memory if appropriate). The destination texture handles are used in * rendering. This scheme demos the Load call and allows dynamic texture * swapping. */ for (i = 0, t = tex.FirstTexture; i < tex.NumTextures; i++, t++) { PALETTEENTRY ppe[256]; LPDIRECTDRAWPALETTE lpDDPalSrc, lpDDPalDst; DDSURFACEDESC ddsd; if (t >= tex.NumTextures) t = 0; if (stat.TextureBlend == D3DTBLEND_COPY) { if (!GetDDSurfaceDesc(&ddsd, dd.lpFrontBuffer)) return FALSE; if (ddsd.ddpfPixelFormat.dwRGBBitCount != 8 && ddsd.ddpfPixelFormat.dwRGBBitCount != 16) { Msg("Copy mode cannot be tested in this display depth. Change display mode and try again."); return FALSE; } ddsd.dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT; ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE; if (stat.bOnlySystemMemory) ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; if (!(tex.lpSrcTextureSurface[i] = LoadSurface(dd.lpDD, tex.ImageFile[i], &ddsd))) { return FALSE; } } else { if (!(tex.lpSrcTextureSurface[i] = LoadSurface(dd.lpDD, tex.ImageFile[i], &TextureFormat[0]))) { return FALSE; } } LastError = tex.lpSrcTextureSurface[i]->QueryInterface(IID_IDirect3DTexture, (LPVOID*)&tex.lpSrcTextureObject[i]); if (LastError != DD_OK) { Msg("Could not create texture.\n%s", MyErrorToString(LastError)); return FALSE;; } #if 0 if (tex.lpSrcTextureObject[i]->GetHandle(d3d.lpD3DDevice, &tex.TextureSrcHandle[i])) { Msg("Could not get handle."); return FALSE; } #endif if (!CreateVidTex(tex.lpSrcTextureSurface[i], &tex.lpDstTextureSurface[t], &tex.lpDstTextureObject[t])) return FALSE; LastError = tex.lpDstTextureObject[t]->GetHandle(d3d.lpD3DDevice, &tex.TextureDstHandle[t]); if (LastError != DD_OK) { Msg("Could not get handle for destination texture handle.\n%s", MyErrorToString(LastError)); return FALSE; } if (tex.lpDstTextureSurface[i]->Blt(NULL, tex.lpSrcTextureSurface[i], NULL, DDBLT_WAIT, NULL) != DD_OK) { Msg("Could not load src texture into dest."); return FALSE; } ddrval = tex.lpSrcTextureSurface[i]->GetPalette(&lpDDPalSrc); if (ddrval != DD_OK && ddrval == DDERR_NOPALETTEATTACHED) { continue; } if (ddrval != DD_OK) { Msg("Could not get source palette"); return FALSE; } ddrval = tex.lpDstTextureSurface[i]->GetPalette(&lpDDPalDst); if (ddrval != DD_OK) { Msg("Could not get dest palette"); return FALSE; } ddrval = lpDDPalSrc->GetEntries(0, 0, 256, ppe); if (ddrval != DD_OK) { Msg("Could not get source palette entries"); return FALSE; } ddrval = lpDDPalDst->SetEntries(0, 0, 256, ppe); if (ddrval != DD_OK) { Msg("Could not get source palette entries"); return FALSE; } lpDDPalDst->Release(); lpDDPalSrc->Release(); } return TRUE; } /*********************************************************************************** Miscellaneous DirectDraw functions ***********************************************************************************/ /* * FreeVideoMemory * Checks to see if there is enough free video memory */ long FreeVideoMemory(void) { DDCAPS ddcaps; memset(&ddcaps, 0, sizeof(ddcaps)); ddcaps.dwSize = sizeof( ddcaps ); LastError = dd.lpDD->GetCaps(&ddcaps, NULL ); if(LastError != DD_OK ){ Msg("GetCaps failed while checking for free memory.\n%s", MyErrorToString(LastError)); return FALSE; } return ddcaps.dwVidMemFree; } /* * CreateDDSurface * Used to create surfaces instead of calling DD directly. */ HRESULT CreateDDSurface(LPDDSURFACEDESC lpDDSurfDesc, LPDIRECTDRAWSURFACE FAR *lpDDSurface, IUnknown FAR *pUnkOuter) { HRESULT result; result = dd.lpDD->CreateSurface(lpDDSurfDesc, lpDDSurface, pUnkOuter); return result; } /************************************************************************* Tests *************************************************************************/ /* * RestoreSurfaces * Restores any lost surfaces. */ BOOL RestoreSurfaces() { int i; if (dd.lpFrontBuffer->IsLost() == DDERR_SURFACELOST) { LastError = dd.lpFrontBuffer->Restore(); if (LastError != DD_OK) { Msg("Restore of front buffer failed.\n%s", MyErrorToString(LastError)); return FALSE; } } if (dd.lpBackBuffer->IsLost() == DDERR_SURFACELOST) { LastError = dd.lpBackBuffer->Restore(); if (LastError != DD_OK) { Msg("Restore of back buffer failed.\n%s", MyErrorToString(LastError)); return FALSE; } } if (dd.lpZBuffer && dd.lpZBuffer->IsLost() == DDERR_SURFACELOST) { LastError = dd.lpZBuffer->Restore(); if (LastError != DD_OK) { Msg("Restore of Z-buffer failed.\n%s", MyErrorToString(LastError)); return FALSE; } } if (stat.bTexturesOn && !stat.bTexturesDisabled) { for (i = 0; i < tex.NumTextures; i++) { if (tex.lpSrcTextureSurface[i]->IsLost() == DDERR_SURFACELOST) { LastError = tex.lpSrcTextureSurface[i]->Restore(); if (LastError != DD_OK) { Msg("Restore of a src texture surface failed.\n%s", MyErrorToString(LastError)); return FALSE; } } if (tex.lpDstTextureSurface[i]->IsLost() == DDERR_SURFACELOST) { LastError = tex.lpDstTextureSurface[i]->Restore(); if (LastError != DD_OK) { Msg("Restore of a dst texture surface failed.\n%s", MyErrorToString(LastError)); return FALSE; } } } } return TRUE; } /* * RenderLoop * Application idle loop which renders. */ BOOL RenderLoop(UINT TestType) { static D3DRECT last, lastlast; static BOOL clearlast, clearlastlast; UINT ClearFlags; RECT src, dst; if (TestType == RESET_TEST) { /* * Clear the screen and set clear flags to false */ if (app.bFullscreen) { #if 0 DDBLTFX ddbltfx; memset(&ddbltfx, 0, sizeof(ddbltfx)); ddbltfx.dwSize = sizeof(DDBLTFX); SetRect(&dst, 0, 0, dd.ModeList[dd.CurrentMode].w, dd.ModeList[dd.CurrentMode].h); LastError = dd.lpFrontBuffer->Blt(&dst, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); if (LastError != DD_OK) { Msg("Clearing blt failed.\n%s", MyErrorToString(LastError)); return FALSE; } #endif last.x1 = dx; last.y1 = dy; last.x2 = dx + 400; last.y2 = dy + 400; lastlast.x1 = dx; lastlast.y1 = dy; lastlast.x2 = dx + 400; lastlast.y2 = dy + 400; } else { last.x1 = last.y1 = 0; last.x2 = 400; last.y2 = 400; ClearFlags = D3DCLEAR_TARGET; if (stat.bZBufferOn) ClearFlags |= D3DCLEAR_ZBUFFER; LastError = d3d.lpD3DViewport->Clear(1, &last, ClearFlags); if (LastError != D3D_OK) { Msg("Initial viewport clear failed.\n%s", MyErrorToString(LastError)); return FALSE(); } SetRect(&src, 0, 0, 400, 400); LastError = dd.lpFrontBuffer->Blt(&app.rcClient, dd.lpBackBuffer, &src, DDBLT_WAIT, NULL); if (LastError != DD_OK) { Msg("Blt of back to front buffer failed.\n%s", MyErrorToString(LastError)); return FALSE; } clearlast = FALSE; } return TRUE; } if (!RestoreSurfaces()) return FALSE; /* * Clear back buffer and Z buffer if enabled */ if (app.bFullscreen) { if (stat.bClearsOn) { LPD3DRECT lpClearRect; lpClearRect = &lastlast; if (TestType == FILL_RATE_TEST || TestType == INTERSECTION_TEST) LastError = d3d.lpD3DViewport->Clear(1, lpClearRect, D3DCLEAR_ZBUFFER); else { if (!NoUpdates) // Clearing both is fine because both must be on or off LastError = d3d.lpD3DViewport->Clear(1, lpClearRect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER); else LastError = d3d.lpD3DViewport->Clear(1, lpClearRect, D3DCLEAR_ZBUFFER); } if (LastError != D3D_OK) { Msg("Viewport clear failed.\n%s", MyErrorToString(LastError)); return FALSE; } } lastlast = last; clearlastlast = clearlast; } else { if (clearlast) { LPD3DRECT lpClearRect; lpClearRect = &last; if (!NoUpdates) // Clearing both is fine because both must be on or off LastError = d3d.lpD3DViewport->Clear(1, lpClearRect, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER); else LastError = d3d.lpD3DViewport->Clear(1, lpClearRect, D3DCLEAR_ZBUFFER); if (LastError != D3D_OK) { Msg("Viewport clear failed.\n%s", MyErrorToString(LastError)); return FALSE; } lastlast = last; } } if (TestType == THROUGHPUT_TEST || TestType == INTERSECTION_TEST) { if (!RenderScenePoly(d3d.lpD3DDevice, d3d.lpD3DViewport, &last)) { Msg("RenderScenePoly failed.\n"); return FALSE; } } else if (TestType == FILL_RATE_TEST) { if (!RenderScenePix(d3d.lpD3DDevice, d3d.lpD3DViewport, &last)) { Msg("RenderScenePix failed.\n"); return FALSE; } /* * Because extents are not correct */ if (app.bFullscreen) { last.x1 = dx; last.y1 = dy; last.x2 = dx+400; last.y2 = dy+400; } else { last.x1 = 0; last.y1 = 0; last.x2 = 400; last.y2 = 400; } } else { Msg("Bad TestStatus.\n"); return FALSE; } if (app.bFullscreen) { if (!NoUpdates) { LastError = dd.lpFrontBuffer->Flip(dd.lpBackBuffer, 1); if (LastError != DD_OK) { Msg("Flip failed.\n%s", MyErrorToString(LastError)); return FALSE; } } } else { if (clearlast) { if (lastlast.x1 < last.x1) last.x1 = lastlast.x1; if (lastlast.y1 < last.y1) last.y1 = lastlast.y1; if (lastlast.x2 > last.x2) last.x2 = lastlast.x2; if (lastlast.y2 > last.y2) last.y2 = lastlast.y2; } if (stat.bClearsOn) { clearlast = TRUE; } else clearlast = FALSE; SetRect(&src, last.x1, last.y1, last.x2, last.y2); SetRect(&dst, last.x1 + app.rcClient.left, last.y1 + app.rcClient.top, last.x2 + app.rcClient.left, last.y2 + app.rcClient.top); if (!NoUpdates) { LastError = dd.lpFrontBuffer->Blt(&dst, dd.lpBackBuffer, &src, DDBLT_WAIT, NULL); if (LastError != DD_OK) { Msg("Blt of back to front buffer failed.\n%s", MyErrorToString(LastError)); return FALSE; } } } return TRUE; } float Timer() { time_t now; now = clock(); return ((float)(now - StartTime)) / (float)CLOCKS_PER_SEC; } void ResetTimer() { StartTime = clock(); } BOOL RunPolyTest(float *lpResult) { unsigned long PolyCount; unsigned long framecount; unsigned long foo; D3DSTATS stats; float time; stats.dwSize = sizeof stats; d3d.lpD3DDevice->GetStats(&stats); foo = stats.dwTrianglesDrawn; PolyCount = InitViewPoly(dd.lpDD, d3d.lpD3D, d3d.lpD3DDevice, d3d.lpD3DViewport, tex.NumTextures, &tex.TextureDstHandle[0], OBJECTS_IN_THROUGHPUT_TEST, RINGS_IN_THROUGHPUT_TEST, SEGS_IN_THROUGHPUT_TEST, NO_SORT, R_IN_THROUGHPUT_TEST, D_IN_THROUGHPUT_TEST, DEPTH_IN_THROUGHPUT_TEST, DV_IN_THROUGHPUT_TEST, DR_IN_THROUGHPUT_TEST); if (PolyCount == 0) { Msg("Initializing the scene for the polygon throughput test failed.\n"); return FALSE; } app.bAbortTest = FALSE; SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); if (!RenderLoop(RESET_TEST)) { goto error_ended_test; } ResetTimer(); do { if (!RenderLoop(THROUGHPUT_TEST)) { goto error_ended_test; } } while (Timer() < STARTUP_INTERVAL && !app.bAbortTest); if (app.bAbortTest) { goto abort_test; } framecount = 0; ResetTimer(); do { if (!RenderLoop(THROUGHPUT_TEST)) { goto error_ended_test; } ++framecount; time = Timer(); } while (time < TEST_INTERVAL && !app.bAbortTest); if (app.bAbortTest) { goto abort_test; } SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); ReleaseViewPoly(); stats.dwSize = sizeof stats; d3d.lpD3DDevice->GetStats(&stats); foo = stats.dwTrianglesDrawn - foo; /* don't trust foo */ *lpResult = (float)(PolyCount * framecount) / time; return TRUE; abort_test: SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); ReleaseViewPoly(); *lpResult = (float)0.0; return TRUE; error_ended_test: SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); ReleaseViewPoly(); *lpResult = (float)0.0; return FALSE; } BOOL RunPixelTest(UINT order, float *lpResult) { unsigned long PixelCount, framecount; float time, result; PixelCount = InitViewPix(dd.lpDD, d3d.lpD3D, d3d.lpD3DDevice, d3d.lpD3DViewport, tex.NumTextures, &tex.TextureDstHandle[0], 400, 400, OVERDRAW_IN_PIXEL_TEST, order); if (PixelCount == 0) { Msg("InitViewPix failed.\n"); return FALSE; } app.bAbortTest = FALSE; SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); if (!RenderLoop(RESET_TEST)) { goto error_ended_test; } ResetTimer(); do { if (!RenderLoop(FILL_RATE_TEST)) { goto error_ended_test; } } while (Timer() < STARTUP_INTERVAL && !app.bAbortTest); if (app.bAbortTest) { goto abort_test; } framecount = 0; ResetTimer(); do { if (!RenderLoop(FILL_RATE_TEST)) { goto error_ended_test; } ++framecount; time = Timer(); } while (time < TEST_INTERVAL && !app.bAbortTest); if (app.bAbortTest) { goto abort_test; } SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); ReleaseViewPix(); result = (float)(PixelCount * framecount) / time; *lpResult = result; return TRUE; abort_test: SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); ReleaseViewPix(); *lpResult = (float)0.0; return TRUE; error_ended_test: SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); ReleaseViewPix(); *lpResult = (float)0.0; return FALSE; } BOOL RunIntersectionTest(UINT order, float *lpResult) { unsigned long PolyCount; unsigned long framecount; unsigned long foo; D3DSTATS stats; float time; stats.dwSize = sizeof stats; d3d.lpD3DDevice->GetStats(&stats); foo = stats.dwTrianglesDrawn; PolyCount = InitViewPoly(dd.lpDD, d3d.lpD3D, d3d.lpD3DDevice, d3d.lpD3DViewport, tex.NumTextures, &tex.TextureDstHandle[0], OBJECTS_IN_INTERSECTION_TEST, RINGS_IN_INTERSECTION_TEST, SEGS_IN_INTERSECTION_TEST, order, R_IN_INTERSECTION_TEST, D_IN_INTERSECTION_TEST, DEPTH_IN_INTERSECTION_TEST, DV_IN_INTERSECTION_TEST, DR_IN_INTERSECTION_TEST); if (PolyCount == 0) { Msg("Initializing the scene for the intersection test failed.\n"); return FALSE; } app.bAbortTest = FALSE; SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); if (!RenderLoop(RESET_TEST)) { goto error_ended_test; } ResetTimer(); do { if (!RenderLoop(INTERSECTION_TEST)) { goto error_ended_test; } } while (Timer() < STARTUP_INTERVAL && !app.bAbortTest); if (app.bAbortTest) { goto abort_test; } framecount = 0; ResetTimer(); do { if (!RenderLoop(INTERSECTION_TEST)) { goto error_ended_test; } ++framecount; time = Timer(); } while (time < TEST_INTERVAL && !app.bAbortTest); if (app.bAbortTest) { goto abort_test; } SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); ReleaseViewPoly(); stats.dwSize = sizeof stats; d3d.lpD3DDevice->GetStats(&stats); foo = stats.dwTrianglesDrawn - foo; /* don't trust foo */ *lpResult = (float)(PolyCount * framecount) / time; return TRUE; abort_test: SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); ReleaseViewPoly(); *lpResult = (float)0.0; return TRUE; error_ended_test: SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); ReleaseViewPoly(); *lpResult = (float)0.0; return FALSE; } /************************************************************************* Windows specific functions *************************************************************************/ void SetStateFromDialog(void); BOOL FillRateInfo(void) { char buf[35]; sprintf(buf, "%.2f", (float)LastThroughput / (float)1000.0); SetWindowText(GetDlgItem(app.hDlg, LAST_THROUGHPUT_TEXT), buf); sprintf(buf, "%.2f", (float)LastFillRate / (float)1000000.0); SetWindowText(GetDlgItem(app.hDlg, LAST_FILL_RATE_TEXT), buf); sprintf(buf, "%.2f", (float)PeakThroughput/ (float)1000.0); SetWindowText(GetDlgItem(app.hDlg, PEAK_THROUGHPUT_TEXT), buf); sprintf(buf, "%.2f", (float)PeakFillRateF2B / (float)1000000.0); SetWindowText(GetDlgItem(app.hDlg, PEAK_FRONT_TO_BACK_FILL_RATE_TEXT), buf); sprintf(buf, "%.2f", (float)PeakFillRateB2F / (float)1000000.0); SetWindowText(GetDlgItem(app.hDlg, PEAK_BACK_TO_FRONT_FILL_RATE_TEXT), buf); sprintf(buf, "%.2f", (float)LastIntersectionThroughput / (float)10000.0); SetWindowText(GetDlgItem(app.hDlg, LAST_INTERSECTION_TEXT), buf); sprintf(buf, "%.2f", (float)PeakIntersectionThroughputF2B / (float)10000.0); SetWindowText(GetDlgItem(app.hDlg, PEAK_FRONT_TO_BACK_INTERSECTION_TEXT), buf); sprintf(buf, "%.2f", (float)PeakIntersectionThroughputB2F / (float)10000.0); SetWindowText(GetDlgItem(app.hDlg, PEAK_BACK_TO_FRONT_INTERSECTION_TEXT), buf); return TRUE; } void RefreshButtons(void) { CheckDlgButton(app.hDlg, SYSTEM_MEMORY_CHECK, stat.bOnlySystemMemory); CheckDlgButton(app.hDlg, ZBUFFER_CHECK, stat.bZBufferOn); EnableWindow(GetDlgItem(app.hDlg, ZBUFFER_CHECK), ZDepth ? TRUE : FALSE); CheckDlgButton(app.hDlg, PERSP_CHECK, stat.bPerspCorrect); CheckDlgButton(app.hDlg, TEXTURES_CHECK, stat.bTexturesOn); CheckDlgButton(app.hDlg, SPECULAR_CHECK, stat.bSpecular); EnableWindow(GetDlgItem(app.hDlg, SPECULAR_CHECK), CanSpecular); CheckDlgButton(app.hDlg, NO_UPDATES_CHECK, NoUpdates); CheckDlgButton(app.hDlg, POINT_RADIO, (stat.TextureFilter == D3DFILTER_NEAREST) ? 1 : 0); CheckDlgButton(app.hDlg, BILINEAR_RADIO, (stat.TextureFilter == D3DFILTER_LINEAR) ? 1 : 0); CheckDlgButton(app.hDlg, GOURAUD_RADIO, (stat.ShadeMode == D3DSHADE_GOURAUD && stat.TextureBlend == D3DTBLEND_MODULATE) ? 1 : 0); CheckDlgButton(app.hDlg, FLAT_RADIO, (stat.ShadeMode == D3DSHADE_FLAT && stat.TextureBlend == D3DTBLEND_MODULATE) ? 1 : 0); CheckDlgButton(app.hDlg, COPY_RADIO, (stat.TextureBlend == D3DTBLEND_COPY) ? 1 : 0); EnableWindow(GetDlgItem(app.hDlg, COPY_RADIO), CanCopy); CheckDlgButton(app.hDlg, MONO_RADIO, stat.dcmColorModel == D3DCOLOR_MONO ? 1 : 0); EnableWindow(GetDlgItem(app.hDlg, MONO_RADIO), CanMono); CheckDlgButton(app.hDlg, RGB_RADIO, stat.dcmColorModel == D3DCOLOR_RGB ? 1 : 0); EnableWindow(GetDlgItem(app.hDlg, RGB_RADIO), CanRGB); CheckDlgButton(app.hDlg, FRONT_TO_BACK_RADIO, (stat.OverdrawOrder == FRONT_TO_BACK) ? 1 : 0); CheckDlgButton(app.hDlg, BACK_TO_FRONT_RADIO, (stat.OverdrawOrder == BACK_TO_FRONT) ? 1 : 0); EnableWindow(GetDlgItem(app.hDlg, SYSTEM_MEMORY_CHECK), !IsHardware); EnableWindow(GetDlgItem(app.hDlg, PERSP_CHECK), !stat.bTexturesDisabled); EnableWindow(GetDlgItem(app.hDlg, TEXTURES_CHECK), !stat.bTexturesDisabled); EnableWindow(GetDlgItem(app.hDlg, POINT_RADIO), !stat.bTexturesDisabled); EnableWindow(GetDlgItem(app.hDlg, BILINEAR_RADIO), !stat.bTexturesDisabled); } /* * GetCurrDevice * Gets selected device */ UINT GetCurrDevice(void) { UINT sel; sel = (UINT)SendDlgItemMessage(app.hDlg, DEVICE_LIST, CB_GETCURSEL, 0, 0L ); if (sel < 0 || sel >= d3d.NumDrivers) { Msg("Invalid driver selected in list box.\n"); // XXX just let it return } return sel; } /* * SetDeviceInfo * Sets the text and d3d.dcmColorModel for given driver */ BOOL SetDeviceInfo(int i) { SetStateFromDialog(); if (d3d.Driver[i].HWDesc.dcmColorModel) { ZDepth = d3d.Driver[i].HWDesc.dwDeviceZBufferBitDepth; ZType = DDSCAPS_VIDEOMEMORY; IsHardware = TRUE; stat.bOnlySystemMemory = FALSE; if (d3d.Driver[i].HWDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) stat.bTexturesDisabled = FALSE; else stat.bTexturesDisabled = TRUE; CanSpecular = (d3d.Driver[i].HWDesc.dpcTriCaps.dwShadeCaps & D3DPSHADECAPS_SPECULARGOURAUDMONO || d3d.Driver[i].HWDesc.dpcTriCaps.dwShadeCaps & D3DPSHADECAPS_SPECULARGOURAUDRGB) ? TRUE : FALSE; CanCopy = (d3d.Driver[i].HWDesc.dpcTriCaps.dwTextureBlendCaps & D3DPTBLENDCAPS_COPY) ? TRUE : FALSE; CanMono = (d3d.Driver[i].HWDesc.dpcTriCaps.dwShadeCaps & D3DPSHADECAPS_COLORGOURAUDMONO) ? TRUE : FALSE; CanRGB = (d3d.Driver[i].HWDesc.dpcTriCaps.dwShadeCaps & D3DPSHADECAPS_COLORGOURAUDRGB) ? TRUE : FALSE; } else { IsHardware = FALSE; ZDepth = d3d.Driver[i].HELDesc.dwDeviceZBufferBitDepth; ZType = DDSCAPS_SYSTEMMEMORY; if (d3d.Driver[i].HELDesc.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) stat.bTexturesDisabled = FALSE; else stat.bTexturesDisabled = TRUE; CanSpecular = (d3d.Driver[i].HELDesc.dpcTriCaps.dwShadeCaps & D3DPSHADECAPS_SPECULARGOURAUDMONO || d3d.Driver[i].HELDesc.dpcTriCaps.dwShadeCaps & D3DPSHADECAPS_SPECULARGOURAUDRGB) ? TRUE : FALSE; CanCopy = (d3d.Driver[i].HELDesc.dpcTriCaps.dwTextureBlendCaps & D3DPTBLENDCAPS_COPY) ? TRUE : FALSE; CanMono = (d3d.Driver[i].HELDesc.dpcTriCaps.dwShadeCaps & D3DPSHADECAPS_COLORGOURAUDMONO) ? TRUE : FALSE; CanRGB = (d3d.Driver[i].HELDesc.dpcTriCaps.dwShadeCaps & D3DPSHADECAPS_COLORGOURAUDRGB) ? TRUE : FALSE; } if (!CanSpecular) stat.bSpecular = FALSE; stat.TextureBlend = D3DTBLEND_MODULATE; stat.dcmColorModel = CanRGB ? D3DCOLOR_RGB : D3DCOLOR_MONO; if (ZDepth & DDBD_32) ZDepth = 32; else if (ZDepth & DDBD_24) ZDepth = 24; else if (ZDepth & DDBD_16) ZDepth = 16; else if (ZDepth & DDBD_8) ZDepth = 8; else { stat.bZBufferOn = FALSE; } RefreshButtons(); LastIntersectionThroughput = (float)0.0; PeakIntersectionThroughputF2B = (float)0.0; PeakIntersectionThroughputB2F = (float)0.0; PeakFillRateF2B = (float)0.0; LastFillRate = (float)0.0; PeakFillRateB2F = (float)0.0; LastThroughput = (float)0.0; PeakThroughput = (float)0.0; FillRateInfo(); stat.bOnlySoftRender = FALSE; return TRUE; } /* * FillDeviceList * Fills in the list of devices */ BOOL FillDeviceList(void) { UINT i; SendDlgItemMessage(app.hDlg, DEVICE_LIST, CB_RESETCONTENT, 0, 0); for (i = 0; i < d3d.NumDrivers; i++) SendDlgItemMessage(app.hDlg, DEVICE_LIST, CB_ADDSTRING, 0, (LONG)(LPSTR)&d3d.Driver[i].Name[0]); return TRUE; } /* * GetCurrDD * Gets selected dd driver */ UINT GetCurrDD(void) { int sel; sel = SendDlgItemMessage(app.hDlg, DD_LIST, CB_GETCURSEL, 0, 0L ); if (sel < 0 || sel >= dd.NumDrivers) { Msg("Invalid DD driver selected in list box.\n"); // XXX just let it return } return sel; } /* * SetDDInfo * Sets up the list of devices for this dd driver */ BOOL SetDDInfo(int i) { if (!FillDeviceList()) return FALSE; SendDlgItemMessage(app.hDlg, DEVICE_LIST, CB_SETCURSEL, 0, 0L ); if (!SetDeviceInfo(0)) return FALSE; return TRUE; } /* * FillDDList * Fills the list of dd drivers */ BOOL FillDDList(void) { int i; for (i = 0; i < dd.NumDrivers; i++) SendDlgItemMessage(app.hDlg, DD_LIST, CB_ADDSTRING, 0, (LONG)(LPSTR)&dd.Driver[i].Name[0]); return TRUE; } void SetStateFromDialog(void) { stat.bOnlySystemMemory = IsDlgButtonChecked(app.hDlg, SYSTEM_MEMORY_CHECK); stat.bZBufferOn = IsDlgButtonChecked(app.hDlg, ZBUFFER_CHECK); if (stat.bZBufferOn) stat.bClearsOn = TRUE; stat.bPerspCorrect = IsDlgButtonChecked(app.hDlg, PERSP_CHECK); stat.bSpecular = IsDlgButtonChecked(app.hDlg, SPECULAR_CHECK); stat.bTexturesOn = IsDlgButtonChecked(app.hDlg, TEXTURES_CHECK); NoUpdates = IsDlgButtonChecked(app.hDlg, NO_UPDATES_CHECK); stat.TextureFilter = (IsDlgButtonChecked(app.hDlg, POINT_RADIO)) ? D3DFILTER_NEAREST : D3DFILTER_LINEAR; stat.ShadeMode = (IsDlgButtonChecked(app.hDlg, GOURAUD_RADIO)) ? D3DSHADE_GOURAUD : D3DSHADE_FLAT; stat.TextureBlend = IsDlgButtonChecked(app.hDlg, COPY_RADIO) ? D3DTBLEND_COPY : D3DTBLEND_MODULATE; stat.OverdrawOrder = (IsDlgButtonChecked(app.hDlg, FRONT_TO_BACK_RADIO)) ? FRONT_TO_BACK : BACK_TO_FRONT; stat.dcmColorModel = IsDlgButtonChecked(app.hDlg, MONO_RADIO) ? D3DCOLOR_MONO : D3DCOLOR_RGB; } /* * Control panel message handler */ BOOL FAR PASCAL PanelHandler(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { int i; BOOL succ; if (app.bTestInProgress) { return TRUE; } switch (msg) { case WM_INITDIALOG: app.hDlg = hDlg; RefreshButtons(); if (!EnumDDDrivers()) { CleanUpAndPostQuit(); return FALSE; } if (!(Connect())) { CleanUpAndPostQuit(); return FALSE; } FillDDList(); SendDlgItemMessage(app.hDlg, DD_LIST, CB_SETCURSEL, dd.CurrentDriver, 0L ); SetDDInfo(dd.CurrentDriver); return TRUE; case WM_CLOSE: if (app.bQuit) break; CleanUpAndPostQuit(); EndDialog(hDlg, TRUE); break; case WM_COMMAND: if (app.bQuit) break; switch(LOWORD(wParam)) { case ALL_TESTS_BUTTON: SetStateFromDialog(); i = GetCurrDevice(); app.bTestInProgress = TRUE; if (!CreateD3DWindow(d3d.Driver[i].lpGuid)) { CleanUpAndPostQuit(); break; } succ = RunPixelTest(FRONT_TO_BACK, &LastFillRate); if (!succ) { ReleaseD3DWindow(); app.bTestInProgress = FALSE; Msg("A test has failed. Results are invalid.\n"); break; } if (app.bAbortTest) break; if (LastFillRate > PeakFillRateF2B) PeakFillRateF2B = LastFillRate; succ = RunPixelTest(BACK_TO_FRONT, &LastFillRate); if (!succ) { ReleaseD3DWindow(); app.bTestInProgress = FALSE; Msg("A test has failed. Results are invalid.\n"); break; } if (app.bAbortTest) break; if (LastFillRate > PeakFillRateB2F) PeakFillRateB2F = LastFillRate; succ = RunPolyTest(&LastThroughput); if (!succ) { ReleaseD3DWindow(); app.bTestInProgress = FALSE; Msg("A test has failed. Results are invalid.\n"); break; } if (app.bAbortTest) break; if (LastThroughput > PeakThroughput) PeakThroughput = LastThroughput; succ = RunIntersectionTest(FRONT_TO_BACK, &LastIntersectionThroughput); if (!succ) { ReleaseD3DWindow(); app.bTestInProgress = FALSE; Msg("A test has failed. Results are invalid.\n"); break; } if (app.bAbortTest) break; if (LastIntersectionThroughput > PeakIntersectionThroughputF2B) PeakIntersectionThroughputF2B = LastIntersectionThroughput; succ = RunIntersectionTest(BACK_TO_FRONT, &LastIntersectionThroughput); if (!succ) { ReleaseD3DWindow(); app.bTestInProgress = FALSE; Msg("A test has failed. Results are invalid.\n"); break; } if (app.bAbortTest) break; if (LastIntersectionThroughput > PeakIntersectionThroughputB2F) PeakIntersectionThroughputB2F = LastIntersectionThroughput; ReleaseD3DWindow(); app.bTestInProgress = FALSE; FillRateInfo(); break; case POLYGON_THROUGHPUT_BUTTON: SetStateFromDialog(); i = GetCurrDevice(); app.bTestInProgress = TRUE; if (!CreateD3DWindow(d3d.Driver[i].lpGuid)) { CleanUpAndPostQuit(); break; } succ = RunPolyTest(&LastThroughput); ReleaseD3DWindow(); app.bTestInProgress = FALSE; if (!succ) { Msg("A test has failed. Results are invalid\n"); break; } if (app.bAbortTest) break; if (LastThroughput > PeakThroughput) PeakThroughput = LastThroughput; FillRateInfo(); break; case PIXEL_FILL_RATE_BUTTON: SetStateFromDialog(); i = GetCurrDevice(); app.bTestInProgress = TRUE; if (!CreateD3DWindow(d3d.Driver[i].lpGuid)) { CleanUpAndPostQuit(); break; } succ = RunPixelTest(stat.OverdrawOrder, &LastFillRate); ReleaseD3DWindow(); app.bTestInProgress = FALSE; if (!succ) { Msg("A test has failed. Results are invalid.\n"); break; } if (app.bAbortTest) break; if (stat.OverdrawOrder == FRONT_TO_BACK && LastFillRate > PeakFillRateF2B) PeakFillRateF2B = LastFillRate; if (stat.OverdrawOrder == BACK_TO_FRONT && LastFillRate > PeakFillRateB2F) PeakFillRateB2F = LastFillRate; FillRateInfo(); break; case INTERSECTION_THROUGHPUT_BUTTON: SetStateFromDialog(); i = GetCurrDevice(); app.bTestInProgress = TRUE; if (!CreateD3DWindow(d3d.Driver[i].lpGuid)) { CleanUpAndPostQuit(); break; } succ = RunIntersectionTest(stat.OverdrawOrder, &LastIntersectionThroughput); ReleaseD3DWindow(); app.bTestInProgress = FALSE; if (!succ) { Msg("A test has failed. Results are invalid.\n"); break; } if (app.bAbortTest) break; if (stat.OverdrawOrder == FRONT_TO_BACK && LastIntersectionThroughput > PeakIntersectionThroughputF2B) PeakIntersectionThroughputF2B = LastIntersectionThroughput; if (stat.OverdrawOrder == BACK_TO_FRONT && LastIntersectionThroughput > PeakIntersectionThroughputB2F) PeakIntersectionThroughputB2F = LastIntersectionThroughput; FillRateInfo(); break; case DEVICE_LIST: if( GET_WM_COMMAND_CMD( wParam, lParam ) == CBN_SELCHANGE ) { i = GetCurrDevice(); SetDeviceInfo(i); } break; case DD_LIST: if (GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE) { if (!Disconnect()) { CleanUpAndPostQuit(); break; } i = GetCurrDD(); dd.CurrentDriver = i; if (!(Connect())) { CleanUpAndPostQuit(); break; } SetDDInfo(i); } break; case EXIT_BUTTON: CleanUpAndPostQuit(); EndDialog(hDlg, TRUE); break; } return 0L; } return FALSE; } /* * AppInit * Initialize this instance. */ static BOOL AppInit(HINSTANCE hInstance, int nCmdShow) { HDC hdc; /* Save instance handle for DialogBoxes */ app.hInstApp = hInstance; /* * Use current BPP */ hdc = GetDC(NULL); ReleaseDC(NULL, hdc); return TRUE; } /* * ProcessCommandLine * Search command line for options. Valid options include: * -systemmemory Force all surfaces to be created in system memory. */ BOOL ProcessCommandLine(LPSTR lpCmdLine) { LPSTR option; option = strtok(lpCmdLine, " -"); while(option != NULL ) { if (!lstrcmp(option, "systemmemory")) { stat.bOnlySystemMemory = TRUE; } else { Msg("Invalid command line options."); return FALSE; } option = strtok(NULL, " -"); } return TRUE; } /* * WinMain - initialization, message loop */ int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { InitGlobals(); hPrevInstance = hPrevInstance; if(!ProcessCommandLine(lpCmdLine)) return FALSE; if(!AppInit(hInstance, nCmdShow)) return FALSE; DialogBox(app.hInstApp, "ControlPanel", NULL, (DLGPROC)PanelHandler); DestroyWindow(app.hWnd); app.hWnd = NULL; return 0; } /************************************************************************* Options setting functions. *************************************************************************/ /* * Sets the render mode */ BOOL SetRenderState(void) { D3DEXECUTEBUFFERDESC debDesc; D3DEXECUTEDATA d3dExData; LPDIRECT3DEXECUTEBUFFER lpD3DExCmdBuf; LPVOID lpBuffer, lpInsStart; DDSURFACEDESC ddsd; BOOL bDithering; size_t size; memset(&ddsd, 0, sizeof(DDSURFACEDESC)); ddsd.dwSize = sizeof(DDSURFACEDESC); LastError = dd.lpDD->GetDisplayMode(&ddsd); if (LastError != DD_OK) { Msg("Getting the current display mode failed.\n%s", MyErrorToString(LastError)); return FALSE; } bDithering = ddsd.ddpfPixelFormat.dwRGBBitCount <= 8 && stat.dcmColorModel == D3DCOLOR_RGB ? TRUE : FALSE; size = 0; size += sizeof(D3DINSTRUCTION) * 2; size += sizeof(D3DSTATE) * 11; memset(&debDesc, 0, sizeof(D3DEXECUTEBUFFERDESC)); debDesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC); debDesc.dwFlags = D3DDEB_BUFSIZE; debDesc.dwBufferSize = size; LastError = d3d.lpD3DDevice->CreateExecuteBuffer(&debDesc, &lpD3DExCmdBuf, NULL); if (LastError != D3D_OK) { Msg("CreateExecuteBuffer failed in SetRenderState.\n%s", MyErrorToString(LastError)); return FALSE; } LastError = lpD3DExCmdBuf->Lock(&debDesc); if (LastError != D3D_OK) { Msg("Lock failed on execute buffer in SetRenderState.\n%s", MyErrorToString(LastError)); return FALSE; } memset(debDesc.lpData, 0, size); lpInsStart = debDesc.lpData; lpBuffer = lpInsStart; OP_STATE_RENDER(11, lpBuffer); STATE_DATA(D3DRENDERSTATE_SHADEMODE, stat.ShadeMode, lpBuffer); STATE_DATA(D3DRENDERSTATE_TEXTUREMAPBLEND, stat.TextureBlend, lpBuffer); STATE_DATA(D3DRENDERSTATE_TEXTUREPERSPECTIVE, stat.bPerspCorrect, lpBuffer); STATE_DATA(D3DRENDERSTATE_ZENABLE, stat.bZBufferOn, lpBuffer); STATE_DATA(D3DRENDERSTATE_ZWRITEENABLE, stat.bZBufferOn, lpBuffer); STATE_DATA(D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL, lpBuffer); STATE_DATA(D3DRENDERSTATE_TEXTUREMAG, stat.TextureFilter, lpBuffer); STATE_DATA(D3DRENDERSTATE_TEXTUREMIN, stat.TextureFilter, lpBuffer); STATE_DATA(D3DRENDERSTATE_SPECULARENABLE, stat.bSpecular, lpBuffer); STATE_DATA(D3DRENDERSTATE_DITHERENABLE, bDithering, lpBuffer); STATE_DATA(D3DRENDERSTATE_MONOENABLE, stat.dcmColorModel == D3DCOLOR_MONO ? TRUE : FALSE, lpBuffer); OP_EXIT(lpBuffer); LastError = lpD3DExCmdBuf->Unlock(); if (LastError != D3D_OK) { Msg("Unlock failed on execute buffer in SetRenderState.\n%s", MyErrorToString(LastError)); return FALSE; } memset(&d3dExData, 0, sizeof(D3DEXECUTEDATA)); d3dExData.dwSize = sizeof(D3DEXECUTEDATA); d3dExData.dwInstructionOffset = (ULONG) 0; d3dExData.dwInstructionLength = (ULONG) ((char*)lpBuffer - (char*)lpInsStart); lpD3DExCmdBuf->SetExecuteData(&d3dExData); LastError = d3d.lpD3DDevice->BeginScene(); if (LastError != D3D_OK) { Msg("BeginScene failed in SetRenderState.\n%s", MyErrorToString(LastError)); return FALSE; } LastError = d3d.lpD3DDevice->Execute(lpD3DExCmdBuf, d3d.lpD3DViewport, D3DEXECUTE_UNCLIPPED); if (LastError != D3D_OK) { Msg("Execute failed in SetRenderState.\n%s", MyErrorToString(LastError)); return FALSE; } LastError = d3d.lpD3DDevice->EndScene(); if (LastError != D3D_OK) { Msg("EndScene failed in SetRenderState.\n%s", MyErrorToString(LastError)); return FALSE; } lpD3DExCmdBuf->Release(); return TRUE; } /************************************************************************* Initialization functions. *************************************************************************/ /* * InitGlobals * Called once at program initialization to initialize global variables. */ void InitGlobals(void) { int i; LastFillRate = (float)0.0; PeakFillRateF2B = (float)0.0; PeakFillRateB2F = (float)0.0; LastThroughput = (float)0.0; PeakThroughput = (float)0.0; /* * DirectDraw globals */ dd.lpFrontBuffer = NULL; dd.lpBackBuffer = NULL; dd.lpZBuffer; dd.lpClipper = NULL; dd.lpPalette = NULL; dd.lpDD = NULL; /* * Direct3D globals */ d3d.lpD3D = NULL; d3d.NumDrivers = 0; for (i = 0; i < 5; i++) memset(&d3d.Driver[i], 0, sizeof(DeviceInfo)); d3d.lpD3DDevice = NULL; d3d.lpD3DViewport = NULL; /* * Windows specific and application screen mode globals */ app.hDlg = 0; app.bTestInProgress = FALSE; app.bAppActive = FALSE; app.bAppPaused = FALSE; app.bIgnoreWM_SIZE = FALSE; app.bQuit = FALSE; /* * Parameters and status flags */ stat.bStopRendering = FALSE; stat.bHandleActivate = FALSE; stat.bTexturesOn = TRUE; stat.bTexturesDisabled = FALSE; stat.bZBufferOn = TRUE; stat.bClearsOn = TRUE; stat.bPerspCorrect = TRUE; stat.bSpecular = FALSE; stat.OverdrawOrder = FRONT_TO_BACK; stat.ShadeMode = D3DSHADE_GOURAUD; stat.TextureFilter = D3DFILTER_NEAREST; stat.bOnlySystemMemory = FALSE; stat.bOnlySoftRender = FALSE; /* * Textures */ tex.NumTextures = 2; lstrcpy(tex.ImageFile[0], "checker.ppm\0"); lstrcpy(tex.ImageFile[1], "tex2.ppm\0"); tex.FirstTexture = 0; } /************************************************************************* Object release and termination functions and InitAll. *************************************************************************/ void ReleaseExeBuffers(void) { ReleaseViewPix(); ReleaseViewPoly(); } void ReleaseTextures(void) { int i; for (i = 0; i < tex.NumTextures; i++) { RELEASE(tex.lpSrcTextureObject[i]); RELEASE(tex.lpSrcTextureSurface[i]); RELEASE(tex.lpDstTextureObject[i]); RELEASE(tex.lpDstTextureSurface[i]); } } /* * CleanUpAndExit * Release everything and posts a quit message. Used for program termination. */ void CleanUpAndPostQuit(void) { app.bTestInProgress = FALSE; ReleaseD3DWindow(); Disconnect(); PostQuitMessage( 0 ); app.bQuit = TRUE; } /************************************************************************* Error reporting functions *************************************************************************/ void dpf( LPSTR fmt, ... ) { char buff[256]; lstrcpy(buff, "D3DTEST: " ); wvsprintf(&buff[lstrlen(buff)], fmt, (char *)(&fmt+1)); lstrcat(buff, "\r\n"); OutputDebugString(buff); } /* Msg * Message output for error notification. */ void __cdecl Msg( LPSTR fmt, ... ) { char buff[256]; app.bTestInProgress = FALSE; lstrcpy(buff, "D3DTEST: " ); wvsprintf(&buff[lstrlen(buff)], fmt, (char *)(&fmt+1)); lstrcat(buff, "\r\n"); OutputDebugString(buff); wvsprintf(buff, fmt, (char *)(&fmt+1)); stat.bStopRendering = TRUE; if (app.bFullscreen && dd.lpDD) { dd.lpDD->FlipToGDISurface(); } SetWindowPos(app.hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); MessageBox( NULL, buff, "D3DTest Message", MB_OK ); } /* * MyErrorToString * Returns a pointer to a string describing the given error code. */ char* MyErrorToString(HRESULT error) { switch(error) { case DD_OK: return "No error.\0"; case DDERR_ALREADYINITIALIZED: return "This object is already initialized.\0"; case DDERR_BLTFASTCANTCLIP: return "Return if a clipper object is attached to the source surface passed into a BltFast call.\0"; case DDERR_CANNOTATTACHSURFACE: return "This surface can not be attached to the requested surface.\0"; case DDERR_CANNOTDETACHSURFACE: return "This surface can not be detached from the requested surface.\0"; case DDERR_CANTCREATEDC: return "Windows can not create any more DCs.\0"; case DDERR_CANTDUPLICATE: return "Can't duplicate primary & 3D surfaces, or surfaces that are implicitly created.\0"; case DDERR_CLIPPERISUSINGHWND: return "An attempt was made to set a cliplist for a clipper object that is already monitoring an hwnd.\0"; case DDERR_COLORKEYNOTSET: return "No src color key specified for this operation.\0"; case DDERR_CURRENTLYNOTAVAIL: return "Support is currently not available.\0"; case DDERR_DIRECTDRAWALREADYCREATED: return "A DirectDraw object representing this driver has already been created for this process.\0"; case DDERR_EXCEPTION: return "An exception was encountered while performing the requested operation.\0"; case DDERR_EXCLUSIVEMODEALREADYSET: return "An attempt was made to set the cooperative level when it was already set to exclusive.\0"; case DDERR_GENERIC: return "Generic failure.\0"; case DDERR_HEIGHTALIGN: return "Height of rectangle provided is not a multiple of reqd alignment.\0"; case DDERR_HWNDALREADYSET: return "The CooperativeLevel HWND has already been set. It can not be reset while the process has surfaces or palettes created.\0"; case DDERR_HWNDSUBCLASSED: return "HWND used by DirectDraw CooperativeLevel has been subclassed, this prevents DirectDraw from restoring state.\0"; case DDERR_IMPLICITLYCREATED: return "This surface can not be restored because it is an implicitly created surface.\0"; case DDERR_INCOMPATIBLEPRIMARY: return "Unable to match primary surface creation request with existing primary surface.\0"; case DDERR_INVALIDCAPS: return "One or more of the caps bits passed to the callback are incorrect.\0"; case DDERR_INVALIDCLIPLIST: return "DirectDraw does not support the provided cliplist.\0"; case DDERR_INVALIDDIRECTDRAWGUID: return "The GUID passed to DirectDrawCreate is not a valid DirectDraw driver identifier.\0"; case DDERR_INVALIDMODE: return "DirectDraw does not support the requested mode.\0"; case DDERR_INVALIDOBJECT: return "DirectDraw received a pointer that was an invalid DIRECTDRAW object.\0"; case DDERR_INVALIDPARAMS: return "One or more of the parameters passed to the function are incorrect.\0"; case DDERR_INVALIDPIXELFORMAT: return "The pixel format was invalid as specified.\0"; case DDERR_INVALIDPOSITION: return "Returned when the position of the overlay on the destination is no longer legal for that destination.\0"; case DDERR_INVALIDRECT: return "Rectangle provided was invalid.\0"; case DDERR_LOCKEDSURFACES: return "Operation could not be carried out because one or more surfaces are locked.\0"; case DDERR_NO3D: return "There is no 3D present.\0"; case DDERR_NOALPHAHW: return "Operation could not be carried out because there is no alpha accleration hardware present or available.\0"; case DDERR_NOBLTHW: return "No blitter hardware present.\0"; case DDERR_NOCLIPLIST: return "No cliplist available.\0"; case DDERR_NOCLIPPERATTACHED: return "No clipper object attached to surface object.\0"; case DDERR_NOCOLORCONVHW: return "Operation could not be carried out because there is no color conversion hardware present or available.\0"; case DDERR_NOCOLORKEY: return "Surface doesn't currently have a color key\0"; case DDERR_NOCOLORKEYHW: return "Operation could not be carried out because there is no hardware support of the destination color key.\0"; case DDERR_NOCOOPERATIVELEVELSET: return "Create function called without DirectDraw object method SetCooperativeLevel being called.\0"; case DDERR_NODC: return "No DC was ever created for this surface.\0"; case DDERR_NODDROPSHW: return "No DirectDraw ROP hardware.\0"; case DDERR_NODIRECTDRAWHW: return "A hardware-only DirectDraw object creation was attempted but the driver did not support any hardware.\0"; case DDERR_NOEMULATION: return "Software emulation not available.\0"; case DDERR_NOEXCLUSIVEMODE: return "Operation requires the application to have exclusive mode but the application does not have exclusive mode.\0"; case DDERR_NOFLIPHW: return "Flipping visible surfaces is not supported.\0"; case DDERR_NOGDI: return "There is no GDI present.\0"; case DDERR_NOHWND: return "Clipper notification requires an HWND or no HWND has previously been set as the CooperativeLevel HWND.\0"; case DDERR_NOMIRRORHW: return "Operation could not be carried out because there is no hardware present or available.\0"; case DDERR_NOOVERLAYDEST: return "Returned when GetOverlayPosition is called on an overlay that UpdateOverlay has never been called on to establish a destination.\0"; case DDERR_NOOVERLAYHW: return "Operation could not be carried out because there is no overlay hardware present or available.\0"; case DDERR_NOPALETTEATTACHED: return "No palette object attached to this surface.\0"; case DDERR_NOPALETTEHW: return "No hardware support for 16 or 256 color palettes.\0"; case DDERR_NORASTEROPHW: return "Operation could not be carried out because there is no appropriate raster op hardware present or available.\0"; case DDERR_NOROTATIONHW: return "Operation could not be carried out because there is no rotation hardware present or available.\0"; case DDERR_NOSTRETCHHW: return "Operation could not be carried out because there is no hardware support for stretching.\0"; case DDERR_NOT4BITCOLOR: return "DirectDrawSurface is not in 4 bit color palette and the requested operation requires 4 bit color palette.\0"; case DDERR_NOT4BITCOLORINDEX: return "DirectDrawSurface is not in 4 bit color index palette and the requested operation requires 4 bit color index palette.\0"; case DDERR_NOT8BITCOLOR: return "DirectDrawSurface is not in 8 bit color mode and the requested operation requires 8 bit color.\0"; case DDERR_NOTAOVERLAYSURFACE: return "Returned when an overlay member is called for a non-overlay surface.\0"; case DDERR_NOTEXTUREHW: return "Operation could not be carried out because there is no texture mapping hardware present or available.\0"; case DDERR_NOTFLIPPABLE: return "An attempt has been made to flip a surface that is not flippable.\0"; case DDERR_NOTFOUND: return "Requested item was not found.\0"; case DDERR_NOTLOCKED: 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"; case DDERR_NOTPALETTIZED: return "The surface being used is not a palette-based surface.\0"; case DDERR_NOVSYNCHW: return "Operation could not be carried out because there is no hardware support for vertical blank synchronized operations.\0"; case DDERR_NOZBUFFERHW: return "Operation could not be carried out because there is no hardware support for zbuffer blitting.\0"; case DDERR_NOZOVERLAYHW: return "Overlay surfaces could not be z layered based on their BltOrder because the hardware does not support z layering of overlays.\0"; case DDERR_OUTOFCAPS: return "The hardware needed for the requested operation has already been allocated.\0"; case DDERR_OUTOFMEMORY: return "DirectDraw does not have enough memory to perform the operation.\0"; case DDERR_OUTOFVIDEOMEMORY: return "DirectDraw does not have enough memory to perform the operation.\0"; case DDERR_OVERLAYCANTCLIP: return "The hardware does not support clipped overlays.\0"; case DDERR_OVERLAYCOLORKEYONLYONEACTIVE: return "Can only have ony color key active at one time for overlays.\0"; case DDERR_OVERLAYNOTVISIBLE: return "Returned when GetOverlayPosition is called on a hidden overlay.\0"; case DDERR_PALETTEBUSY: return "Access to this palette is being refused because the palette is already locked by another thread.\0"; case DDERR_PRIMARYSURFACEALREADYEXISTS: return "This process already has created a primary surface.\0"; case DDERR_REGIONTOOSMALL: return "Region passed to Clipper::GetClipList is too small.\0"; case DDERR_SURFACEALREADYATTACHED: return "This surface is already attached to the surface it is being attached to.\0"; case DDERR_SURFACEALREADYDEPENDENT: return "This surface is already a dependency of the surface it is being made a dependency of.\0"; case DDERR_SURFACEBUSY: return "Access to this surface is being refused because the surface is already locked by another thread.\0"; case DDERR_SURFACEISOBSCURED: return "Access to surface refused because the surface is obscured.\0"; case DDERR_SURFACELOST: 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"; case DDERR_SURFACENOTATTACHED: return "The requested surface is not attached.\0"; case DDERR_TOOBIGHEIGHT: return "Height requested by DirectDraw is too large.\0"; case DDERR_TOOBIGSIZE: return "Size requested by DirectDraw is too large, but the individual height and width are OK.\0"; case DDERR_TOOBIGWIDTH: return "Width requested by DirectDraw is too large.\0"; case DDERR_UNSUPPORTED: return "Action not supported.\0"; case DDERR_UNSUPPORTEDFORMAT: return "FOURCC format requested is unsupported by DirectDraw.\0"; case DDERR_UNSUPPORTEDMASK: return "Bitmask in the pixel format requested is unsupported by DirectDraw.\0"; case DDERR_VERTICALBLANKINPROGRESS: return "Vertical blank is in progress.\0"; case DDERR_WASSTILLDRAWING: return "Informs DirectDraw that the previous Blt which is transfering information to or from this Surface is incomplete.\0"; case DDERR_WRONGMODE: return "This surface can not be restored because it was created in a different mode.\0"; case DDERR_XALIGN: return "Rectangle provided was not horizontally aligned on required boundary.\0"; case D3DERR_BADMAJORVERSION: return "D3DERR_BADMAJORVERSION\0"; case D3DERR_BADMINORVERSION: return "D3DERR_BADMINORVERSION\0"; case D3DERR_EXECUTE_LOCKED: return "D3DERR_EXECUTE_LOCKED\0"; case D3DERR_EXECUTE_NOT_LOCKED: return "D3DERR_EXECUTE_NOT_LOCKED\0"; case D3DERR_EXECUTE_CREATE_FAILED: return "D3DERR_EXECUTE_CREATE_FAILED\0"; case D3DERR_EXECUTE_DESTROY_FAILED: return "D3DERR_EXECUTE_DESTROY_FAILED\0"; case D3DERR_EXECUTE_LOCK_FAILED: return "D3DERR_EXECUTE_LOCK_FAILED\0"; case D3DERR_EXECUTE_UNLOCK_FAILED: return "D3DERR_EXECUTE_UNLOCK_FAILED\0"; case D3DERR_EXECUTE_FAILED: return "D3DERR_EXECUTE_FAILED\0"; case D3DERR_EXECUTE_CLIPPED_FAILED: return "D3DERR_EXECUTE_CLIPPED_FAILED\0"; case D3DERR_TEXTURE_NO_SUPPORT: return "D3DERR_TEXTURE_NO_SUPPORT\0"; case D3DERR_TEXTURE_NOT_LOCKED: return "D3DERR_TEXTURE_NOT_LOCKED\0"; case D3DERR_TEXTURE_LOCKED: return "D3DERR_TEXTURELOCKED\0"; case D3DERR_TEXTURE_CREATE_FAILED: return "D3DERR_TEXTURE_CREATE_FAILED\0"; case D3DERR_TEXTURE_DESTROY_FAILED: return "D3DERR_TEXTURE_DESTROY_FAILED\0"; case D3DERR_TEXTURE_LOCK_FAILED: return "D3DERR_TEXTURE_LOCK_FAILED\0"; case D3DERR_TEXTURE_UNLOCK_FAILED: return "D3DERR_TEXTURE_UNLOCK_FAILED\0"; case D3DERR_TEXTURE_LOAD_FAILED: return "D3DERR_TEXTURE_LOAD_FAILED\0"; case D3DERR_MATRIX_CREATE_FAILED: return "D3DERR_MATRIX_CREATE_FAILED\0"; case D3DERR_MATRIX_DESTROY_FAILED: return "D3DERR_MATRIX_DESTROY_FAILED\0"; case D3DERR_MATRIX_SETDATA_FAILED: return "D3DERR_MATRIX_SETDATA_FAILED\0"; case D3DERR_SETVIEWPORTDATA_FAILED: return "D3DERR_SETVIEWPORTDATA_FAILED\0"; case D3DERR_MATERIAL_CREATE_FAILED: return "D3DERR_MATERIAL_CREATE_FAILED\0"; case D3DERR_MATERIAL_DESTROY_FAILED: return "D3DERR_MATERIAL_DESTROY_FAILED\0"; case D3DERR_MATERIAL_SETDATA_FAILED: return "D3DERR_MATERIAL_SETDATA_FAILED\0"; case D3DERR_LIGHT_SET_FAILED: return "D3DERR_LIGHT_SET_FAILED\0"; default: return "Unrecognized error value.\0"; } }