mshtml: Implement IHTMLDOMNode replaceChild.
[wine] / dlls / d3d9 / tests / shader.c
1 /*
2  * Copyright (C) 2005 Henri Verbeet
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 #define COBJMACROS
20 #include <d3d9.h>
21 #include "wine/test.h"
22
23 static HMODULE d3d9_handle = 0;
24
25 static HWND create_window(void)
26 {
27     WNDCLASS wc = {0};
28     wc.lpfnWndProc = DefWindowProc;
29     wc.lpszClassName = "d3d9_test_wc";
30     RegisterClass(&wc);
31
32     return CreateWindow("d3d9_test_wc", "d3d9_test",
33             0, 0, 0, 0, 0, 0, 0, 0, 0);
34 }
35
36 static IDirect3DDevice9 *init_d3d9(void)
37 {
38     IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion) = 0;
39     IDirect3D9 *d3d9_ptr = 0;
40     IDirect3DDevice9 *device_ptr = 0;
41     D3DPRESENT_PARAMETERS present_parameters;
42     HRESULT hres;
43
44     d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
45     ok(d3d9_create != NULL, "Failed to get address of Direct3DCreate9\n");
46     if (!d3d9_create) return NULL;
47
48     d3d9_ptr = d3d9_create(D3D_SDK_VERSION);
49     if (!d3d9_ptr)
50     {
51         skip("could not create D3D9\n");
52         return NULL;
53     }
54
55     ZeroMemory(&present_parameters, sizeof(present_parameters));
56     present_parameters.Windowed = TRUE;
57     present_parameters.hDeviceWindow = create_window();
58     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
59
60     hres = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
61
62     if(FAILED(hres))
63     {
64         skip("could not create device, IDirect3D9_CreateDevice returned %#x\n", hres);
65         return NULL;
66     }
67
68     return device_ptr;
69 }
70
71 static int get_refcount(IUnknown *object)
72 {
73     IUnknown_AddRef(object);
74     return IUnknown_Release(object);
75 }
76
77 static void test_get_set_vertex_shader(IDirect3DDevice9 *device_ptr)
78 {
79
80     static DWORD simple_vs[] = {0xFFFE0101,             /* vs_1_1               */
81         0x0000001F, 0x80000000, 0x900F0000,             /* dcl_position0 v0     */
82         0x00000009, 0xC0010000, 0x90E40000, 0xA0E40000, /* dp4 oPos.x, v0, c0   */
83         0x00000009, 0xC0020000, 0x90E40000, 0xA0E40001, /* dp4 oPos.y, v0, c1   */
84         0x00000009, 0xC0040000, 0x90E40000, 0xA0E40002, /* dp4 oPos.z, v0, c2   */
85         0x00000009, 0xC0080000, 0x90E40000, 0xA0E40003, /* dp4 oPos.w, v0, c3   */
86         0x0000FFFF};                                    /* END                  */
87
88     IDirect3DVertexShader9 *shader_ptr = 0;
89     IDirect3DVertexShader9 *current_shader_ptr = 0;
90     HRESULT hret = 0;
91     int shader_refcount = 0;
92     int i = 0;
93
94     hret = IDirect3DDevice9_CreateVertexShader(device_ptr, simple_vs, &shader_ptr);
95     ok(hret == D3D_OK && shader_ptr != NULL, "CreateVertexShader returned: hret 0x%x, shader_ptr %p. "
96         "Expected hret 0x%x, shader_ptr != %p. Aborting.\n", hret, shader_ptr, D3D_OK, NULL);
97     if (hret != D3D_OK || shader_ptr == NULL) return;
98
99     /* SetVertexShader should not touch the shader's refcount. */
100     i = get_refcount((IUnknown *)shader_ptr);
101     hret = IDirect3DDevice9_SetVertexShader(device_ptr, shader_ptr);
102     shader_refcount = get_refcount((IUnknown *)shader_ptr);
103     ok(hret == D3D_OK && shader_refcount == i, "SetVertexShader returned: hret 0x%x, refcount %d. "
104         "Expected hret 0x%x, refcount %d.\n", hret, shader_refcount, D3D_OK, i);
105
106     /* GetVertexShader should increase the shader's refcount by one. */
107     i = shader_refcount+1;
108     hret = IDirect3DDevice9_GetVertexShader(device_ptr, &current_shader_ptr);
109     shader_refcount = get_refcount((IUnknown *)shader_ptr);
110     ok(hret == D3D_OK && shader_refcount == i && current_shader_ptr == shader_ptr,
111         "GetVertexShader returned: hret 0x%x, current_shader_ptr %p refcount %d. "
112         "Expected hret 0x%x, current_shader_ptr %p, refcount %d.\n", hret, current_shader_ptr, shader_refcount, D3D_OK, shader_ptr, i);
113     IDirect3DVertexShader9_Release(current_shader_ptr);
114
115     IDirect3DVertexShader9_Release(shader_ptr);
116 }
117
118 static void test_vertex_shader_constant(IDirect3DDevice9 *device_ptr, DWORD consts)
119 {
120     float c[4] = { 0.0, 0.0, 0.0, 0.0 };
121     float d[16] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
122     HRESULT hr;
123
124     /* A simple check that the stuff works at all */
125     hr = IDirect3DDevice9_SetVertexShaderConstantF(device_ptr, 0, c, 1);
126     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned 0x%08x\n", hr);
127
128     /* Test corner cases: Write to const MAX - 1, MAX, MAX + 1, and writing 4 consts from
129      * MAX - 1
130      */
131     hr = IDirect3DDevice9_SetVertexShaderConstantF(device_ptr, consts - 1, c, 1);
132     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned 0x%08x\n", hr);
133     hr = IDirect3DDevice9_SetVertexShaderConstantF(device_ptr, consts + 0, c, 1);
134     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetVertexShaderConstantF returned 0x%08x\n", hr);
135     hr = IDirect3DDevice9_SetVertexShaderConstantF(device_ptr, consts + 1, c, 1);
136     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetVertexShaderConstantF returned 0x%08x\n", hr);
137     hr = IDirect3DDevice9_SetVertexShaderConstantF(device_ptr, consts - 1, d, 4);
138     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetVertexShaderConstantF returned 0x%08x\n", hr);
139
140     /* Constant -1 */
141     hr = IDirect3DDevice9_SetVertexShaderConstantF(device_ptr, -1, c, 1);
142     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetVertexShaderConstantF returned 0x%08x\n", hr);
143 }
144
145 static void test_get_set_pixel_shader(IDirect3DDevice9 *device_ptr)
146 {
147     static DWORD simple_ps[] = {0xFFFF0101,                                     /* ps_1_1                       */
148         0x00000051, 0xA00F0001, 0x3F800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0  */
149         0x00000042, 0xB00F0000,                                                 /* tex t0                       */
150         0x00000008, 0x800F0000, 0xA0E40001, 0xA0E40000,                         /* dp3 r0, c1, c0               */
151         0x00000005, 0x800F0000, 0x90E40000, 0x80E40000,                         /* mul r0, v0, r0               */
152         0x00000005, 0x800F0000, 0xB0E40000, 0x80E40000,                         /* mul r0, t0, r0               */
153         0x0000FFFF};                                                            /* END                          */
154
155     IDirect3DPixelShader9 *shader_ptr = 0;
156     IDirect3DPixelShader9 *current_shader_ptr = 0;
157     HRESULT hret = 0;
158     int shader_refcount = 0;
159     int i = 0;
160
161     hret = IDirect3DDevice9_CreatePixelShader(device_ptr, simple_ps, &shader_ptr);
162     ok(hret == D3D_OK && shader_ptr != NULL, "CreatePixelShader returned: hret 0x%x, shader_ptr %p. "
163         "Expected hret 0x%x, shader_ptr != %p. Aborting.\n", hret, shader_ptr, D3D_OK, NULL);
164     if (hret != D3D_OK || shader_ptr == NULL) return;
165
166     /* SetPixelsShader should not touch the shader's refcount. */
167     i = get_refcount((IUnknown *)shader_ptr);
168     hret = IDirect3DDevice9_SetPixelShader(device_ptr, shader_ptr);
169     shader_refcount = get_refcount((IUnknown *)shader_ptr);
170     ok(hret == D3D_OK && shader_refcount == i, "SetPixelShader returned: hret 0x%x, refcount %d. "
171         "Expected hret 0x%x, refcount %d.\n", hret, shader_refcount, D3D_OK, i);
172
173     /* GetPixelShader should increase the shader's refcount by one. */
174     i = shader_refcount+1;
175     hret = IDirect3DDevice9_GetPixelShader(device_ptr, &current_shader_ptr);
176     shader_refcount = get_refcount((IUnknown *)shader_ptr);
177     ok(hret == D3D_OK && shader_refcount == i && current_shader_ptr == shader_ptr,
178         "GetPixelShader returned: hret 0x%x, current_shader_ptr %p refcount %d. "
179         "Expected hret 0x%x, current_shader_ptr %p, refcount %d.\n", hret, current_shader_ptr, shader_refcount, D3D_OK, shader_ptr, i);
180     IDirect3DPixelShader9_Release(current_shader_ptr);
181
182     IDirect3DPixelShader9_Release(shader_ptr);
183 }
184
185 static void test_pixel_shader_constant(IDirect3DDevice9 *device_ptr)
186 {
187     float c[4] = { 0.0, 0.0, 0.0, 0.0 };
188     float d[16] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
189     HRESULT hr;
190     DWORD consts = 0;
191
192     /* A simple check that the stuff works at all */
193     hr = IDirect3DDevice9_SetPixelShaderConstantF(device_ptr, 0, c, 1);
194     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned 0x%08x\n", hr);
195
196     /* Is there really no max pixel shader constant value??? Test how far I can go */
197     while(SUCCEEDED(IDirect3DDevice9_SetPixelShaderConstantF(device_ptr, consts++, c, 1)));
198     consts = consts - 1;
199     trace("SetPixelShaderConstantF was able to set %d shader constants\n", consts);
200
201     /* Test corner cases: writing 4 consts from MAX - 1, everything else is pointless
202      * given the way the constant limit was found out
203      */
204     hr = IDirect3DDevice9_SetPixelShaderConstantF(device_ptr, consts - 1, d, 4);
205     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetPixelShaderConstantF returned 0x%08x\n", hr);
206
207     /* Constant -1 */
208     hr = IDirect3DDevice9_SetPixelShaderConstantF(device_ptr, -1, c, 1);
209     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetPixelShaderConstantF returned 0x%08x\n", hr);
210 }
211
212 static void test_wrong_shader(IDirect3DDevice9 *device_ptr)
213 {
214     static const DWORD simple_vs[] =
215     {
216         0xfffe0101,                                     /* vs_1_1               */
217         0x0000001f, 0x80000000, 0x900f0000,             /* dcl_position0 v0     */
218         0x00000009, 0xc0010000, 0x90e40000, 0xa0e40000, /* dp4 oPos.x, v0, c0   */
219         0x00000009, 0xc0020000, 0x90e40000, 0xa0e40001, /* dp4 oPos.y, v0, c1   */
220         0x00000009, 0xc0040000, 0x90e40000, 0xa0e40002, /* dp4 oPos.z, v0, c2   */
221         0x00000009, 0xc0080000, 0x90e40000, 0xa0e40003, /* dp4 oPos.w, v0, c3   */
222         0x0000ffff                                      /* END                  */
223     };
224
225     static const DWORD simple_ps[] =
226     {
227         0xffff0101,                                                             /* ps_1_1                       */
228         0x00000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1 = 1.0, 0.0, 0.0, 0.0  */
229         0x00000042, 0xb00f0000,                                                 /* tex t0                       */
230         0x00000008, 0x800f0000, 0xa0e40001, 0xa0e40000,                         /* dp3 r0, c1, c0               */
231         0x00000005, 0x800f0000, 0x90e40000, 0x80e40000,                         /* mul r0, v0, r0               */
232         0x00000005, 0x800f0000, 0xb0e40000, 0x80e40000,                         /* mul r0, t0, r0               */
233         0x0000ffff                                                              /* END                          */
234     };
235
236 #if 0
237 float4 main(const float4 color : COLOR) : SV_TARGET
238 {
239     float4 o;
240
241     o = color;
242
243     return o;
244 }
245 #endif
246     static const DWORD ps_4_0[] =
247     {
248         0x43425844, 0x4da9446f, 0xfbe1f259, 0x3fdb3009, 0x517521fa, 0x00000001, 0x000001ac,
249         0x00000005, 0x00000034, 0x0000008c, 0x000000bc, 0x000000f0, 0x00000130, 0x46454452,
250         0x00000050, 0x00000000, 0x00000000, 0x00000000, 0x0000001c, 0xffff0400, 0x00000100,
251         0x0000001c, 0x7263694d, 0x666f736f, 0x52282074, 0x4c482029, 0x53204c53, 0x65646168,
252         0x6f432072, 0x6c69706d, 0x39207265, 0x2e39322e, 0x2e323539, 0x31313133, 0xababab00,
253         0x4e475349, 0x00000028, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000,
254         0x00000003, 0x00000000, 0x00000f0f, 0x4f4c4f43, 0xabab0052, 0x4e47534f, 0x0000002c,
255         0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, 0x00000000,
256         0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040,
257         0x0000000e, 0x03001062, 0x001010f2, 0x00000000, 0x03000065, 0x001020f2, 0x00000000,
258         0x05000036, 0x001020f2, 0x00000000, 0x00101e46, 0x00000000, 0x0100003e, 0x54415453,
259         0x00000074, 0x00000002, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000,
260         0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
261         0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001,
262         0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
263         0x00000000, 0x00000000,
264     };
265
266     IDirect3DVertexShader9 *vs;
267     IDirect3DPixelShader9 *ps;
268     HRESULT hret;
269
270     hret = IDirect3DDevice9_CreateVertexShader(device_ptr, simple_ps, &vs);
271     ok(hret == D3DERR_INVALIDCALL, "CreateVertexShader returned: hret 0x%x, shader_ptr %p.\n", hret, vs);
272     hret = IDirect3DDevice9_CreatePixelShader(device_ptr, simple_vs, &ps);
273     ok(hret == D3DERR_INVALIDCALL, "CreatePixelShader returned: hret 0x%x, shader_ptr %p.\n", hret, ps);
274
275     hret = IDirect3DDevice9_CreatePixelShader(device_ptr, ps_4_0, &ps);
276     ok(hret == D3DERR_INVALIDCALL, "CreatePixelShader returned: hret 0x%x, shader_ptr %p.\n", hret, ps);
277 }
278
279 START_TEST(shader)
280 {
281     D3DCAPS9 caps;
282     IDirect3DDevice9 *device_ptr;
283     ULONG refcount;
284
285     d3d9_handle = LoadLibraryA("d3d9.dll");
286     if (!d3d9_handle)
287     {
288         skip("Could not load d3d9.dll\n");
289         return;
290     }
291
292     device_ptr = init_d3d9();
293     if (!device_ptr) return;
294
295     IDirect3DDevice9_GetDeviceCaps(device_ptr, &caps);
296
297     if (caps.VertexShaderVersion & 0xffff)
298     {
299         test_get_set_vertex_shader(device_ptr);
300         test_vertex_shader_constant(device_ptr, caps.MaxVertexShaderConst);
301     }
302     else skip("No vertex shader support\n");
303
304     if (caps.PixelShaderVersion & 0xffff)
305     {
306         test_get_set_pixel_shader(device_ptr);
307         /* No max pixel shader constant value??? */
308         test_pixel_shader_constant(device_ptr);
309         if (caps.VertexShaderVersion & 0xffff)
310             test_wrong_shader(device_ptr);
311     }
312     else skip("No pixel shader support\n");
313
314     refcount = IDirect3DDevice9_Release(device_ptr);
315     ok(!refcount, "Device has %u references left\n", refcount);
316 }