VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/disp/wddm/gallium/test/d3d9main.cpp

Last change on this file was 98909, checked in by vboxsync, 14 months ago

WDDM: testcase update

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.0 KB
Line 
1/* $Id: d3d9main.cpp 98909 2023-03-10 16:49:13Z vboxsync $ */
2/** @file
3 * Gallium D3D testcase. Win32 application to run Gallium D3D9 tests.
4 */
5
6/*
7 * Copyright (C) 2017-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28#include "d3d9render.h"
29
30#include <iprt/string.h>
31
32#define D3D9TEST_MAX_DEVICES 2
33
34class D3D9Test : public D3D9DeviceProvider
35{
36public:
37 D3D9Test();
38 ~D3D9Test();
39
40 HRESULT Init(HINSTANCE hInstance, int argc, char **argv, int nCmdShow);
41 int Run();
42
43 virtual int DeviceCount();
44 virtual IDirect3DDevice9 *Device(int index);
45
46private:
47 HRESULT initWindow(HINSTANCE hInstance, int nCmdShow);
48 HRESULT initDirect3D9(int cDevices);
49 void parseCmdLine(int argc, char **argv);
50 static LRESULT CALLBACK wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
51
52 int miRenderId;
53 enum
54 {
55 RenderModeStep = 0,
56 RenderModeContinuous = 1,
57 RenderModeFPS = 2
58 } miRenderMode;
59 HWND mHwnd;
60 IDirect3D9Ex *mpD3D9;
61 int mcDevices;
62 IDirect3DDevice9 *mpaDevices[D3D9TEST_MAX_DEVICES];
63 D3D9Render *mpRender;
64
65 D3DPRESENT_PARAMETERS mPP;
66};
67
68D3D9Test::D3D9Test()
69 :
70 miRenderId(3),
71 miRenderMode(RenderModeStep),
72 mHwnd(0),
73 mpD3D9(0),
74 mcDevices(1),
75 mpRender(0)
76{
77 memset(&mpaDevices, 0, sizeof(mpaDevices));
78 memset(&mPP, 0, sizeof(mPP));
79}
80
81D3D9Test::~D3D9Test()
82{
83 if (mpRender)
84 {
85 delete mpRender;
86 mpRender = 0;
87 }
88 for (int i = 0; i < mcDevices; ++i)
89 {
90 if (mpaDevices[i])
91 {
92 mpaDevices[i]->Release();
93 mpaDevices[i] = 0;
94 }
95 }
96
97 if (mpD3D9)
98 {
99 mpD3D9->Release();
100 mpD3D9 = 0;
101 }
102}
103
104LRESULT CALLBACK D3D9Test::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
105{
106 switch (msg)
107 {
108 case WM_CLOSE:
109 DestroyWindow(hwnd);
110 return 0;
111
112 case WM_DESTROY:
113 PostQuitMessage(0);
114 return 0;
115
116 default:
117 return DefWindowProcA(hwnd, msg, wParam, lParam);
118 }
119}
120
121HRESULT D3D9Test::initWindow(HINSTANCE hInstance,
122 int nCmdShow)
123{
124 HRESULT hr = S_OK;
125
126 WNDCLASSA wc = { 0 };
127 wc.style = CS_HREDRAW | CS_VREDRAW;
128 wc.lpfnWndProc = wndProc;
129 wc.cbClsExtra = 0;
130 wc.cbWndExtra = 0;
131 wc.hInstance = hInstance;
132 wc.hIcon = LoadIcon(0, IDI_APPLICATION);
133 wc.hCursor = LoadCursor(0, IDC_ARROW);
134 wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
135 wc.lpszMenuName = 0;
136 wc.lpszClassName = "D3D9TestWndClassName";
137
138 if (RegisterClassA(&wc))
139 {
140 RECT r = {0, 0, 800, 600};
141 AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, false);
142
143 mHwnd = CreateWindowA("D3D9TestWndClassName",
144 "D3D9 Test",
145 WS_OVERLAPPEDWINDOW,
146 100, 100, r.right, r.bottom,
147 0, 0, hInstance, 0);
148 if (mHwnd)
149 {
150 ShowWindow(mHwnd, nCmdShow);
151 UpdateWindow(mHwnd);
152 }
153 else
154 {
155 D3DTestShowError(hr, "CreateWindow");
156 hr = E_FAIL;
157 }
158 }
159 else
160 {
161 D3DTestShowError(hr, "RegisterClass");
162 hr = E_FAIL;
163 }
164
165 return hr;
166}
167
168HRESULT D3D9Test::initDirect3D9(int cDevices)
169{
170 mcDevices = cDevices;
171
172 HRESULT hr = Direct3DCreate9Ex(D3D_SDK_VERSION, &mpD3D9);
173 if (FAILED(hr))
174 {
175 D3DTestShowError(hr, "Direct3DCreate9Ex");
176 return hr;
177 }
178
179 /* Verify hardware support for current screen mode. */
180 D3DDISPLAYMODE mode;
181 hr = mpD3D9->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode);
182 if (FAILED(hr))
183 {
184 D3DTestShowError(hr, "GetAdapterDisplayMode");
185 return hr;
186 }
187
188 hr = mpD3D9->CheckDeviceType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, mode.Format, mode.Format, true);
189 if (FAILED(hr))
190 {
191 D3DTestShowError(hr, "CheckDeviceType");
192 return hr;
193 }
194
195 /* Create identical devices. */
196 for (int i = 0; i < mcDevices; ++i)
197 {
198#if 0
199 mPP.BackBufferWidth = 0;
200 mPP.BackBufferHeight = 0;
201 mPP.BackBufferFormat = D3DFMT_UNKNOWN;
202#else
203 RECT clientRect;
204 GetClientRect(mHwnd, &clientRect);
205 mPP.BackBufferWidth = clientRect.right;
206 mPP.BackBufferHeight = clientRect.bottom;
207 mPP.BackBufferFormat = D3DFMT_X8R8G8B8;
208#endif
209 mPP.BackBufferCount = 1;
210 mPP.MultiSampleType = D3DMULTISAMPLE_NONE;
211 mPP.MultiSampleQuality = 0;
212 mPP.SwapEffect = D3DSWAPEFFECT_DISCARD;
213 mPP.hDeviceWindow = mHwnd;
214 mPP.Windowed = true;
215 mPP.EnableAutoDepthStencil = true;
216 mPP.AutoDepthStencilFormat = D3DFMT_D24S8;
217 mPP.Flags = 0;
218 mPP.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
219 mPP.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
220
221 hr = mpD3D9->CreateDevice(D3DADAPTER_DEFAULT,
222 D3DDEVTYPE_HAL,
223 mHwnd,
224 D3DCREATE_HARDWARE_VERTEXPROCESSING,
225 &mPP,
226 &mpaDevices[i]);
227 if (FAILED(hr))
228 {
229 D3DTestShowError(hr, "CreateDevice");
230 }
231 }
232
233 return hr;
234}
235
236void D3D9Test::parseCmdLine(int argc, char **argv)
237{
238 /* Very simple: test number followed by step flag.
239 * Default is test 0, step mode: 0 1
240 */
241
242 /* First number is the render id. */
243 if (argc >= 2)
244 miRenderId = RTStrToInt32(argv[1]);
245
246 /* Second number is the render/step mode. */
247 if (argc >= 3)
248 {
249 int i = RTStrToInt32(argv[2]);
250 switch (i)
251 {
252 default:
253 case 0: miRenderMode = RenderModeStep; break;
254 case 1: miRenderMode = RenderModeContinuous; break;
255 case 2: miRenderMode = RenderModeFPS; break;
256 }
257 }
258}
259
260HRESULT D3D9Test::Init(HINSTANCE hInstance, int argc, char **argv, int nCmdShow)
261{
262 parseCmdLine(argc, argv);
263
264 HRESULT hr = initWindow(hInstance, nCmdShow);
265 if (SUCCEEDED(hr))
266 {
267 mpRender = CreateRender(miRenderId);
268 if (mpRender)
269 {
270 const int cDevices = mpRender->RequiredDeviceCount();
271 hr = initDirect3D9(cDevices);
272 if (SUCCEEDED(hr))
273 {
274 hr = mpRender->InitRender(this);
275 if (FAILED(hr))
276 {
277 D3DTestShowError(hr, "InitRender");
278 }
279 }
280 }
281 else
282 {
283 hr = E_FAIL;
284 }
285 }
286
287 return hr;
288}
289
290int D3D9Test::Run()
291{
292 bool fFirst = true;
293 MSG msg;
294
295 LARGE_INTEGER PerfFreq;
296 QueryPerformanceFrequency(&PerfFreq);
297 float const PerfPeriod = 1.0f / (float)PerfFreq.QuadPart; /* Period in seconds. */
298
299 LARGE_INTEGER PrevTS;
300 QueryPerformanceCounter(&PrevTS);
301
302 int cFrames = 0;
303 float elapsed = 0;
304
305 do
306 {
307 BOOL fGotMessage;
308 if (miRenderMode == RenderModeStep)
309 {
310 fGotMessage = GetMessageA(&msg, 0, 0, 0);
311 }
312 else
313 {
314 fGotMessage = PeekMessageA(&msg, 0, 0, 0, PM_REMOVE);
315 }
316
317 if (fGotMessage)
318 {
319 TranslateMessage(&msg);
320 DispatchMessageA(&msg);
321 }
322
323 BOOL fDoRender = FALSE;
324 if (miRenderMode == RenderModeStep)
325 {
326 if (msg.message == WM_CHAR)
327 {
328 if (msg.wParam == ' ')
329 {
330 fDoRender = TRUE;
331 }
332 }
333 }
334 else
335 {
336 fDoRender = TRUE;
337 }
338
339 if (fDoRender)
340 {
341 LARGE_INTEGER CurrTS;
342 QueryPerformanceCounter(&CurrTS);
343
344 /* Time in seconds since the previous render step. */
345 float dt = fFirst ? 0.0f : (float)(CurrTS.QuadPart - PrevTS.QuadPart) * PerfPeriod;
346 if (dt > 0.1f)
347 dt = 0.1f;
348 if (mpRender)
349 {
350 mpRender->TimeAdvance(dt);
351 mpRender->DoRender(this);
352 fFirst = false;
353 }
354
355 if (miRenderMode == RenderModeFPS)
356 {
357 ++cFrames;
358 elapsed += dt;
359 if (elapsed > 1.0f)
360 {
361 float msPerFrame = elapsed * 1000.0f / (float)cFrames;
362 char sz[256];
363 RTStrPrintf(sz, sizeof(sz), "D3D9 Test FPS %d Frame Time %u.%03ums",
364 cFrames, (unsigned)msPerFrame, (unsigned)(msPerFrame * 1000) % 1000);
365 SetWindowTextA(mHwnd, sz);
366
367 cFrames = 0;
368 elapsed = 0.0f;
369 }
370 }
371
372 PrevTS = CurrTS;
373 }
374 } while (msg.message != WM_QUIT);
375
376 return msg.wParam;
377}
378
379int D3D9Test::DeviceCount()
380{
381 return mcDevices;
382}
383
384IDirect3DDevice9 *D3D9Test::Device(int index)
385{
386 if (index < mcDevices)
387 return mpaDevices[index];
388 return NULL;
389}
390
391int main(int argc, char **argv)
392{
393 int rcExit = RTEXITCODE_FAILURE;
394
395 D3D9Test test;
396 HRESULT hr = test.Init(GetModuleHandleW(NULL), argc, argv, SW_SHOWDEFAULT);
397 if (SUCCEEDED(hr))
398 rcExit = test.Run();
399
400 return rcExit;
401}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use