VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.4 KB
Line 
1/* $Id: d3dhlp.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * Gallium D3D testcase. Various D3D helpers.
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 "d3dhlp.h"
29#include <math.h>
30
31/*
32 * D3D vector and matrix math helpers.
33 */
34void d3dMatrixTranspose(D3DMATRIX *pM)
35{
36 int j; /* Row. Only first 3 because diagonal elements are not swapped, i.e. no need to process [3][3]. */
37 for (j = 0; j < 3; ++j)
38 {
39 int i; /* Column, upper right elements. Skip diagonal element [j][j]. */
40 for (i = j + 1; i < 4; ++i)
41 {
42 /* Swap with corresponding bottom left element. */
43 const float tmp = pM->m[j][i];
44 pM->m[j][i] = pM->m[i][j];
45 pM->m[i][j] = tmp;
46 }
47 }
48}
49
50void d3dMatrixIdentity(D3DMATRIX *pM)
51{
52 int j; /* Row. */
53 for (j = 0; j < 4; ++j)
54 {
55 int i; /* Column. */
56 for (i = 0; i < 4; ++i)
57 {
58 pM->m[j][i] = j == i ? 1.0f : 0.0f;
59 }
60 }
61}
62
63void d3dMatrixScaleTranslation(D3DMATRIX *pM, const float s, const float dx, const float dy, const float dz)
64{
65 /*
66 * Translation matrix:
67 * | s 0 0 0 |
68 * | 0 s 0 0 |
69 * | 0 0 s 0 |
70 * | dx dy dz 1 |
71 */
72 pM->m[0][0] = s;
73 pM->m[0][1] = 0;
74 pM->m[0][2] = 0;
75 pM->m[0][3] = 0;
76
77 pM->m[1][0] = 0;
78 pM->m[1][1] = s;
79 pM->m[1][2] = 0;
80 pM->m[1][3] = 0;
81
82 pM->m[2][0] = 0;
83 pM->m[2][1] = 0;
84 pM->m[2][2] = s;
85 pM->m[2][3] = 0;
86
87 pM->m[3][0] = dx;
88 pM->m[3][1] = dy;
89 pM->m[3][2] = dz;
90 pM->m[3][3] = 1;
91}
92
93void d3dMatrixRotationAxis(D3DMATRIX *pM, const D3DVECTOR *pV, float angle)
94{
95 /*
96 * Rotation matrix:
97 * | c+x^2*(1-c) x*y*(1-c)+z*s x*z*(1-c)-y*s 0 |
98 * | x*y*(1-c)-z*s c+y^2*(1-c) y*z*(1-c)+x*s 0 |
99 * | x*z*(1-c)+y*s y*z*(1-c)-x*s c+z^2*(1-c) 0 |
100 * | 0 0 0 1 |
101 */
102 const float c = cos(angle);
103 const float s = sin(angle);
104 const float x = pV->x;
105 const float y = pV->y;
106 const float z = pV->z;
107
108 pM->m[0][0] = c + x*x*(1-c);
109 pM->m[0][1] = x*y*(1-c)+z*s;
110 pM->m[0][2] = x*z*(1-c)-y*s;
111 pM->m[0][3] = 0;
112
113 pM->m[1][0] = x*y*(1-c)-z*s;
114 pM->m[1][1] = c+y*y*(1-c);
115 pM->m[1][2] = y*z*(1-c)+x*s;
116 pM->m[1][3] = 0;
117
118 pM->m[2][0] = x*z*(1-c)+y*s;
119 pM->m[2][1] = y*z*(1-c)-x*s;
120 pM->m[2][2] = c+z*z*(1-c);
121 pM->m[2][3] = 0;
122
123 pM->m[3][0] = 0;
124 pM->m[3][1] = 0;
125 pM->m[3][2] = 0;
126 pM->m[3][3] = 1;
127}
128
129void d3dMatrixView(D3DMATRIX *pM, const D3DVECTOR *pR, const D3DVECTOR *pU, const D3DVECTOR *pL, const D3DVECTOR *pP)
130{
131 /*
132 * Camera coordinate system vectors:
133 * *pR = r = right = x
134 * *pU = u = up = y
135 * *pL = l = look = z
136 * *pP = p = position
137 *
138 * View matrix:
139 * | r.x u.x l.x 0 |
140 * | r.y u.y l.y 0 |
141 * | r.z u.z l.z 0 |
142 * | -pr -pu -pl 1 |
143 *
144 */
145
146 pM->m[0][0] = pR->x;
147 pM->m[0][1] = pU->x;
148 pM->m[0][2] = pL->x;
149 pM->m[0][3] = 0.0f;
150
151 pM->m[1][0] = pR->y;
152 pM->m[1][1] = pU->y;
153 pM->m[1][2] = pL->y;
154 pM->m[1][3] = 0.0f;
155
156 pM->m[2][0] = pR->z;
157 pM->m[2][1] = pU->z;
158 pM->m[2][2] = pL->z;
159 pM->m[2][3] = 0.0f;
160
161 pM->m[3][0] = -d3dVectorDot(pP, pR);
162 pM->m[3][1] = -d3dVectorDot(pP, pU);
163 pM->m[3][2] = -d3dVectorDot(pP, pL);
164 pM->m[3][3] = 1.0f;
165}
166
167void d3dMatrixPerspectiveProjection(D3DMATRIX *pM, float verticalFoV, float aspectRatio, float zNear, float zFar)
168{
169 /*
170 * Perspective projection matrix.
171 *
172 * a = verticalFoV = vertical field of view angle.
173 * R = aspectRatio = width / height of the view window.
174 * n = zNear = near Z plane
175 * f = zFar = far Z plane
176 *
177 * | 1/(R*tan(a/2)) 0 0 0 |
178 * | 0 1/tan(a/2) 0 0 |
179 * | 0 0 f/(f-n) 1 |
180 * | 0 0 -f*n/(f-n) 0 |
181 */
182 const float reciprocalTan2 = 1.0f / tan(verticalFoV / 2.0f);
183 const float zRange = zFar - zNear;
184
185 pM->m[0][0] = reciprocalTan2 / aspectRatio;
186 pM->m[0][1] = 0;
187 pM->m[0][2] = 0;
188 pM->m[0][3] = 0;
189
190 pM->m[1][0] = 0;
191 pM->m[1][1] = reciprocalTan2;
192 pM->m[1][2] = 0;
193 pM->m[1][3] = 0;
194
195 pM->m[2][0] = 0;
196 pM->m[2][1] = 0;
197 pM->m[2][2] = zFar / zRange;
198 pM->m[2][3] = 1;
199
200 pM->m[3][0] = 0;
201 pM->m[3][1] = 0;
202 pM->m[3][2] = - zNear * zFar / zRange;
203 pM->m[3][3] = 0;
204}
205
206void d3dMatrixMultiply(D3DMATRIX *pM, const D3DMATRIX *pM1, const D3DMATRIX *pM2)
207{
208 /* *pM = *pM1 * *pM2 */
209 int j; /* Row. */
210 for (j = 0; j < 4; ++j)
211 {
212 int i; /* Column. */
213 for (i = 0; i < 4; ++i)
214 {
215 /* Row by Column */
216 pM->m[j][i] = pM1->m[j][0] * pM2->m[0][i]
217 + pM1->m[j][1] * pM2->m[1][i]
218 + pM1->m[j][2] * pM2->m[2][i]
219 + pM1->m[j][3] * pM2->m[3][i];
220 }
221 }
222}
223
224void d3dVectorMatrixMultiply(D3DVECTOR *pR, const D3DVECTOR *pV, float w, const D3DMATRIX *pM)
225{
226 /* Vector row by matrix columns */
227 const float x = pV->x;
228 const float y = pV->y;
229 const float z = pV->z;
230 pR->x = x * pM->m[0][0] + y * pM->m[1][0] + z * pM->m[2][0] + w * pM->m[3][0];
231 pR->y = x * pM->m[0][1] + y * pM->m[1][1] + z * pM->m[2][1] + w * pM->m[3][1];
232 pR->z = x * pM->m[0][2] + y * pM->m[1][2] + z * pM->m[2][2] + w * pM->m[3][2];
233}
234
235void d3dVectorNormalize(D3DVECTOR *pV)
236{
237 const float Length = sqrt(pV->x * pV->x + pV->y * pV->y + pV->z * pV->z);
238 if (Length > 0.0f)
239 {
240 pV->x /= Length;
241 pV->y /= Length;
242 pV->z /= Length;
243 }
244}
245
246void d3dVectorCross(D3DVECTOR *pC, const D3DVECTOR *pV1, const D3DVECTOR *pV2)
247{
248 /*
249 * | i j k |
250 * | v1.x v1.y v1.z |
251 * | v2.x v2.y v2.z |
252 */
253 pC->x = pV1->y * pV2->z - pV2->y * pV1->z;
254 pC->y = -pV1->x * pV2->z + pV2->x * pV1->z;
255 pC->z = pV1->x * pV2->y - pV2->x * pV1->y;
256}
257
258
259float d3dVectorDot(const D3DVECTOR *pV1, const D3DVECTOR *pV2)
260{
261 return pV1->x * pV2->x + pV1->y * pV2->y + pV1->z * pV2->z;
262}
263
264void d3dVectorInit(D3DVECTOR *pV, float x, float y, float z)
265{
266 pV->x = x;
267 pV->y = y;
268 pV->z = z;
269}
270
271
272/*
273 * Helper to compute view and projection matrices for a camera.
274 */
275D3DCamera::D3DCamera()
276{
277 d3dMatrixIdentity(&mView);
278 d3dMatrixIdentity(&mProjection);
279 d3dMatrixIdentity(&mViewProjection);
280
281 d3dVectorInit(&mPosition, 0.0f, 0.0f, 0.0f);
282 d3dVectorInit(&mRight, 1.0f, 0.0f, 0.0f);
283 d3dVectorInit(&mUp, 0.0f, 1.0f, 0.0f);
284 d3dVectorInit(&mLook, 0.0f, 0.0f, 1.0f);
285
286 mTime = 0.0f;
287}
288
289const D3DMATRIX *D3DCamera::ViewProjection(void)
290{
291 return &mViewProjection;
292}
293
294void D3DCamera::SetupAt(const D3DVECTOR *pPos, const D3DVECTOR *pAt, const D3DVECTOR *pUp)
295{
296 mLook.x = pAt->x - pPos->x;
297 mLook.y = pAt->y - pPos->y;
298 mLook.z = pAt->z - pPos->z;
299 d3dVectorNormalize(&mLook);
300
301 d3dVectorCross(&mRight, pUp, &mLook);
302 d3dVectorNormalize(&mRight);
303
304 d3dVectorCross(&mUp, &mLook, &mRight);
305 d3dVectorNormalize(&mUp);
306
307 mPosition = *pPos;
308
309 computeView();
310 d3dMatrixMultiply(&mViewProjection, &mView, &mProjection);
311}
312
313void D3DCamera::SetProjection(float verticalFoV, float aspectRatio, float zNear, float zFar)
314{
315 d3dMatrixPerspectiveProjection(&mProjection, verticalFoV, aspectRatio, zNear, zFar);
316 d3dMatrixMultiply(&mViewProjection, &mView, &mProjection);
317}
318
319void D3DCamera::TimeAdvance(float dt)
320{
321 mTime += dt;
322
323 const float xAngleCam = 3.14f / 4.0f * sin(mTime * 3.14f / 9.0f); /* About camera X axis. */
324 const float yAngleW = mTime * 3.14f / 4.0f; /* Rotate about world Y axis. */
325
326 const D3DVECTOR xAxis = { 1.0f, 0.0f, 0.0f };
327 const D3DVECTOR yAxis = { 0.0f, 1.0f, 0.0f };
328 const D3DVECTOR zAxis = { 0.0f, 0.0f, 1.0f };
329
330 /* Start from scratch. */
331 mRight = xAxis;
332 mUp = yAxis;
333 mLook = zAxis;
334
335 D3DMATRIX R;
336
337 /* Rotate the camera up and look vectors about the right vector. */
338 d3dMatrixRotationAxis(&R, &mRight, xAngleCam);
339 d3dVectorMatrixMultiply(&mUp, &mUp, 0.0f, &R);
340 d3dVectorMatrixMultiply(&mLook, &mLook, 0.0f, &R);
341
342 /* Rotate camera axes about the world Y axis. */
343 d3dMatrixRotationAxis(&R, &yAxis, yAngleW);
344 d3dVectorMatrixMultiply(&mRight, &mRight, 0.0f, &R);
345 d3dVectorMatrixMultiply(&mUp, &mUp, 0.0f, &R);
346 d3dVectorMatrixMultiply(&mLook, &mLook, 0.0f, &R);
347
348 computeView();
349 d3dMatrixMultiply(&mViewProjection, &mView, &mProjection);
350}
351
352void D3DCamera::computeView(void)
353{
354 /* Vectors of the ñamera coordinate system must be orthonormal. */
355 d3dVectorNormalize(&mLook);
356
357 d3dVectorCross(&mUp, &mLook, &mRight);
358 d3dVectorNormalize(&mUp);
359
360 d3dVectorCross(&mRight, &mUp, &mLook);
361 d3dVectorNormalize(&mRight);
362
363 d3dMatrixView(&mView, &mRight, &mUp, &mLook, &mPosition);
364}
365
366/* Create and initialize IDirect3DCubeTexture9. */
367HRESULT d3dCreateCubeTexture(IDirect3DDevice9 *pDevice, IDirect3DCubeTexture9 **ppCubeTexture)
368{
369 HRESULT hr = S_OK;
370
371 /* Create a texture in memory. Test transfer D3DPOOL_SYSTEMMEM -> D3DPOOL_DEFAULT */
372 UINT EdgeLength = 256;
373 UINT Levels = 8; /* Greater than number of faces. */
374 DWORD Usage = 0;
375 D3DFORMAT Format = D3DFMT_A8R8G8B8;
376 D3DPOOL Pool = D3DPOOL_SYSTEMMEM;
377
378 IDirect3DCubeTexture9 *pMemTex = NULL;
379 HTEST(pDevice->CreateCubeTexture(EdgeLength, Levels, Usage, Format, Pool, &pMemTex, NULL));
380
381 /* Initialize texture content. */
382 int iFace;
383 for (iFace = 0; iFace < 6; ++iFace)
384 {
385 DWORD Color;
386 D3DCUBEMAP_FACES Face;
387 switch (iFace)
388 {
389 case 0: Face = D3DCUBEMAP_FACE_POSITIVE_X; Color = 0xfff0f0f0; break; /* Almost white */
390 case 1: Face = D3DCUBEMAP_FACE_NEGATIVE_X; Color = 0xff7f7f7f; break; /* Gray */
391 case 2: Face = D3DCUBEMAP_FACE_POSITIVE_Y; Color = 0xff0000ff; break; /* Blue */
392 case 3: Face = D3DCUBEMAP_FACE_NEGATIVE_Y; Color = 0xff00007f; break; /* Darker blue */
393 case 4: Face = D3DCUBEMAP_FACE_POSITIVE_Z; Color = 0xff00ff00; break; /* Green */
394 default:
395 case 5: Face = D3DCUBEMAP_FACE_NEGATIVE_Z; Color = 0xff007f00; break; /* Darker green */
396 }
397
398 UINT Level;
399 for (Level = 0; Level < Levels; ++Level)
400 {
401 IDirect3DSurface9 *pCubeMapSurface = NULL;
402 HTEST(pMemTex->GetCubeMapSurface(Face, Level, &pCubeMapSurface));
403
404 D3DSURFACE_DESC Desc;
405 HTEST(pCubeMapSurface->GetDesc(&Desc));
406
407 D3DLOCKED_RECT LockedRect;
408 HTEST(pCubeMapSurface->LockRect(&LockedRect, NULL, D3DLOCK_DISCARD));
409
410 UINT y;
411 BYTE *pb = (BYTE *)LockedRect.pBits;
412 for (y = 0; y < Desc.Height; ++y)
413 {
414 UINT x;
415 for (x = 0; x < Desc.Width; ++x)
416 {
417 DWORD *pdw = (DWORD *)pb;
418 pdw[x] = Color;
419 }
420 pb += LockedRect.Pitch;
421 }
422
423 HTEST(pCubeMapSurface->UnlockRect());
424
425 pCubeMapSurface->Release();
426 }
427 }
428
429 /* Create actual texture. */
430 Pool = D3DPOOL_DEFAULT;
431
432 IDirect3DCubeTexture9 *pCubeTex = NULL;
433 HTEST(pDevice->CreateCubeTexture(EdgeLength, Levels, Usage, Format, Pool, &pCubeTex, NULL));
434
435 /* Copy texture content. */
436 HTEST(pDevice->UpdateTexture(pMemTex, pCubeTex));
437
438 /* Do not need the bounce texture anymore. */
439 pMemTex->Release();
440
441 *ppCubeTexture = pCubeTex;
442 return hr;
443}
444
445/* Create IDirect3DVertexBuffer9 with vertices for a cube. */
446HRESULT d3dCreateCubeVertexBuffer(IDirect3DDevice9 *pDevice, float EdgeLength, IDirect3DVertexBuffer9 **ppVertexBuffer)
447{
448 /* Create vertices of a cube (no indexing). Layout: 3x float.
449 * Arbitrary winding order, will use D3DRS_CULLMODE = D3DCULL_NONE.
450 */
451
452 static float aVertices[6 * 6 * 3] =
453 {
454 /* POSITIVE_X */
455 /* Triangle 1 */
456 1.0f, -1.0f, -1.0f,
457 1.0f, -1.0f, 1.0f,
458 1.0f, 1.0f, 1.0f,
459 /* Triangle 2 */
460 1.0f, -1.0f, -1.0f,
461 1.0f, 1.0f, 1.0f,
462 1.0f, 1.0f, -1.0f,
463
464 /* NEGATIVE_X */
465 /* Triangle 1 */
466 -1.0f, -1.0f, -1.0f,
467 -1.0f, -1.0f, 1.0f,
468 -1.0f, 1.0f, 1.0f,
469 /* Triangle 2 */
470 -1.0f, -1.0f, -1.0f,
471 -1.0f, 1.0f, 1.0f,
472 -1.0f, 1.0f, -1.0f,
473
474 /* POSITIVE_Y */
475 /* Triangle 1 */
476 -1.0f, 1.0f, -1.0f,
477 -1.0f, 1.0f, 1.0f,
478 1.0f, 1.0f, 1.0f,
479 /* Triangle 2 */
480 -1.0f, 1.0f, -1.0f,
481 1.0f, 1.0f, 1.0f,
482 1.0f, 1.0f, -1.0f,
483
484 /* NEGATIVE_Y */
485 /* Triangle 1 */
486 -1.0f, -1.0f, -1.0f,
487 -1.0f, -1.0f, 1.0f,
488 1.0f, -1.0f, 1.0f,
489 /* Triangle 2 */
490 -1.0f, -1.0f, -1.0f,
491 1.0f, -1.0f, 1.0f,
492 1.0f, -1.0f, -1.0f,
493
494 /* POSITIVE_Z */
495 /* Triangle 1 */
496 1.0f, -1.0f, 1.0f,
497 -1.0f, -1.0f, 1.0f,
498 -1.0f, 1.0f, 1.0f,
499 /* Triangle 2 */
500 1.0f, -1.0f, 1.0f,
501 -1.0f, 1.0f, 1.0f,
502 1.0f, 1.0f, 1.0f,
503
504 /* NEGATIVE_Z */
505 /* Triangle 1 */
506 1.0f, -1.0f, -1.0f,
507 -1.0f, -1.0f, -1.0f,
508 -1.0f, 1.0f, -1.0f,
509 /* Triangle 2 */
510 1.0f, -1.0f, -1.0f,
511 -1.0f, 1.0f, -1.0f,
512 1.0f, 1.0f, -1.0f,
513 };
514
515 HRESULT hr = S_OK;
516
517 IDirect3DVertexBuffer9 *pVB = NULL;
518 HTEST(pDevice->CreateVertexBuffer(6 * 6 * 3 * sizeof(float), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &pVB, 0));
519
520 void *pv = 0;
521 HTEST(pVB->Lock(0, 0, &pv, 0));
522
523 const int cFloats = sizeof(aVertices)/sizeof(aVertices[0]);
524 float *p = (float *)pv;
525 int i;
526 for (i = 0; i < cFloats; ++i)
527 {
528 p[i] = aVertices[i] * EdgeLength / 2.0f;
529 }
530
531 HTEST(pVB->Unlock());
532
533 *ppVertexBuffer = pVB;
534 return S_OK;
535}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use