2490 lines
84 KiB
C++
2490 lines
84 KiB
C++
/*==========================================================================
|
|
*
|
|
* Copyright (C) 1995, 1996 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: d3dtest.cpp
|
|
*
|
|
***************************************************************************/
|
|
|
|
#define INITGUID
|
|
|
|
//#define NOTOPMOST_WINDOW
|
|
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <ddraw.h>
|
|
#include <d3d.h>
|
|
#include <assert.h>
|
|
#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";
|
|
}
|
|
}
|