1 /*
2  * Copyright 2010 Christian Costa
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include "wine/test.h"
20 #include "d3dx9.h"
21 
22 #define admitted_error 0.0001f
23 
24 #define relative_error(exp, out) ((exp == 0.0f) ? fabs(exp - out) : (fabs(1.0f - out/ exp) ))
25 
26 static inline BOOL compare_matrix(const D3DXMATRIX *m1, const D3DXMATRIX *m2)
27 {
28     int i, j;
29 
30     for (i = 0; i < 4; ++i)
31     {
32         for (j = 0; j < 4; ++j)
33         {
34             if (relative_error(U(*m1).m[i][j], U(*m2).m[i][j]) > admitted_error)
35                 return FALSE;
36         }
37     }
38 
39     return TRUE;
40 }
41 
42 #define expect_mat(expectedmat, gotmat) \
43 do { \
44     const D3DXMATRIX *__m1 = (expectedmat); \
45     const D3DXMATRIX *__m2 = (gotmat); \
46     ok(compare_matrix(__m1, __m2), "Expected matrix=\n(%f,%f,%f,%f\n %f,%f,%f,%f\n %f,%f,%f,%f\n %f,%f,%f,%f\n)\n\n" \
47             "Got matrix=\n(%f,%f,%f,%f\n %f,%f,%f,%f\n %f,%f,%f,%f\n %f,%f,%f,%f)\n", \
48             U(*__m1).m[0][0], U(*__m1).m[0][1], U(*__m1).m[0][2], U(*__m1).m[0][3], \
49             U(*__m1).m[1][0], U(*__m1).m[1][1], U(*__m1).m[1][2], U(*__m1).m[1][3], \
50             U(*__m1).m[2][0], U(*__m1).m[2][1], U(*__m1).m[2][2], U(*__m1).m[2][3], \
51             U(*__m1).m[3][0], U(*__m1).m[3][1], U(*__m1).m[3][2], U(*__m1).m[3][3], \
52             U(*__m2).m[0][0], U(*__m2).m[0][1], U(*__m2).m[0][2], U(*__m2).m[0][3], \
53             U(*__m2).m[1][0], U(*__m2).m[1][1], U(*__m2).m[1][2], U(*__m2).m[1][3], \
54             U(*__m2).m[2][0], U(*__m2).m[2][1], U(*__m2).m[2][2], U(*__m2).m[2][3], \
55             U(*__m2).m[3][0], U(*__m2).m[3][1], U(*__m2).m[3][2], U(*__m2).m[3][3]); \
56 } while(0)
57 
58 static void test_create_line(IDirect3DDevice9* device)
59 {
60     HRESULT hr;
61     ID3DXLine *line = NULL;
62     struct IDirect3DDevice9 *return_device;
63     D3DXMATRIX world, identity, result;
64     FLOAT r11, r12, r13, r14;
65     ULONG ref;
66 
67     /* Arbitrary values for matrix tests. */
68     r11 = 0.1421; r12 = 0.2114; r13 = 0.8027; r14 = 0.4587;
69 
70     hr = D3DXCreateLine(NULL, &line);
71     ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3D_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
72 
73     hr = D3DXCreateLine(device, NULL);
74     ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3D_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
75 
76     hr = D3DXCreateLine(device, &line);
77     ok(hr == D3D_OK, "Got result %x, expected 0 (D3D_OK)\n", hr);
78 
79     if (FAILED(hr))
80     {
81         return;
82     }
83 
84     hr = ID3DXLine_GetDevice(line, NULL);
85     ok(hr == D3DERR_INVALIDCALL, "Got result %x, expected %x (D3D_INVALIDCALL)\n", hr, D3DERR_INVALIDCALL);
86 
87     hr = ID3DXLine_GetDevice(line, &return_device);
88     ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
89     ok(return_device == device, "Expected line device %p, got %p\n", device, return_device);
90 
91     D3DXMatrixIdentity(&world);
92     D3DXMatrixIdentity(&identity);
93     S(U(world))._11 = r11; S(U(world))._12 = r12; S(U(world))._13 = r13; S(U(world))._14 = r14;
94 
95     hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLD, &world);
96     ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
97 
98     hr = ID3DXLine_Begin(line);
99     ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
100 
101     hr = IDirect3DDevice9_GetTransform(device, D3DTS_WORLD, &result);
102     ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
103     expect_mat(&identity, &result);
104 
105     hr = ID3DXLine_End(line);
106     ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
107 
108     hr = IDirect3DDevice9_GetTransform(device, D3DTS_WORLD, &result);
109     ok(hr == D3D_OK, "Got result %x, expected %x (D3D_OK)\n", hr, D3D_OK);
110     expect_mat(&world, &result);
111 
112     IDirect3DDevice9_Release(return_device);
113 
114     ref = ID3DXLine_Release(line);
115     ok(ref == 0, "Got %x references to line %p, expected 0\n", ref, line);
116 }
117 
118 START_TEST(line)
119 {
120     HWND wnd;
121     IDirect3D9* d3d;
122     IDirect3DDevice9* device;
123     D3DPRESENT_PARAMETERS d3dpp;
124     HRESULT hr;
125 
126     if (!(wnd = CreateWindowA("static", "d3dx9_test", WS_OVERLAPPEDWINDOW, 0, 0,
127             640, 480, NULL, NULL, NULL, NULL)))
128     {
129         skip("Couldn't create application window\n");
130         return;
131     }
132     if (!(d3d = Direct3DCreate9(D3D_SDK_VERSION)))
133     {
134         skip("Couldn't create IDirect3D9 object\n");
135         DestroyWindow(wnd);
136         return;
137     }
138 
139     ZeroMemory(&d3dpp, sizeof(d3dpp));
140     d3dpp.Windowed = TRUE;
141     d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
142     hr = IDirect3D9_CreateDevice(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, wnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device);
143     if (FAILED(hr)) {
144         skip("Failed to create IDirect3DDevice9 object %#x\n", hr);
145         IDirect3D9_Release(d3d);
146         DestroyWindow(wnd);
147         return;
148     }
149 
150     test_create_line(device);
151 
152     IDirect3DDevice9_Release(device);
153     IDirect3D9_Release(d3d);
154     DestroyWindow(wnd);
155 }
156