msvcrt: Make fputwc encoding aware.
[wine] / dlls / d3dx9_36 / tests / asm.c
1 /*
2  * Copyright (C) 2008 Stefan Dösinger
3  * Copyright (C) 2009 Matteo Bruni
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19 #define COBJMACROS
20 #define CONST_VTABLE
21 #include "wine/test.h"
22
23 #include <d3dx9.h>
24
25 #include "resources.h"
26
27 static HRESULT create_file(const char *filename, const char *data, const unsigned int size)
28 {
29     DWORD received;
30     HANDLE hfile;
31
32     hfile = CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
33     if(hfile == INVALID_HANDLE_VALUE) return HRESULT_FROM_WIN32(GetLastError());
34
35     if(WriteFile(hfile, data, size, &received, NULL))
36     {
37         CloseHandle(hfile);
38         return D3D_OK;
39     }
40
41     CloseHandle(hfile);
42     return D3DERR_INVALIDCALL;
43 }
44
45 static HRESULT WINAPI testD3DXInclude_open(ID3DXInclude *iface,
46                                            D3DXINCLUDE_TYPE include_type,
47                                            LPCSTR filename, LPCVOID parent_data,
48                                            LPCVOID *data, UINT *bytes) {
49     char *buffer;
50     const char include[] = "#define REGISTER r0\nvs.1.1\n";
51     const char include2[] = "#include \"incl3.vsh\"\n";
52     const char include3[] = "vs.1.1\n";
53
54     trace("filename = %s\n", filename);
55     trace("parent_data (%p) -> %s\n", parent_data, parent_data ? (char *)parent_data : "(null)");
56
57     if(!strcmp(filename,"incl.vsh")) {
58         buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(include));
59         CopyMemory(buffer, include, sizeof(include));
60         *bytes = sizeof(include);
61         /* Also check for the correct parent_data content */
62         ok(parent_data == NULL, "wrong parent_data value\n");
63     }
64     else if(!strcmp(filename,"incl3.vsh")) {
65         buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(include3));
66         CopyMemory(buffer, include3, sizeof(include3));
67         *bytes = sizeof(include3);
68         /* Also check for the correct parent_data content */
69         ok(parent_data != NULL && !strncmp(include2, parent_data, strlen(include2)), "wrong parent_data value\n");
70     }
71     else {
72         buffer = HeapAlloc(GetProcessHeap(), 0, sizeof(include2));
73         CopyMemory(buffer, include2, sizeof(include2));
74         *bytes = sizeof(include2);
75     }
76     *data = buffer;
77     return S_OK;
78 }
79
80 static HRESULT WINAPI testD3DXInclude_close(ID3DXInclude *iface, LPCVOID data) {
81     HeapFree(GetProcessHeap(), 0, (LPVOID)data);
82     return S_OK;
83 }
84
85 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = {
86     testD3DXInclude_open,
87     testD3DXInclude_close
88 };
89
90 struct D3DXIncludeImpl {
91     ID3DXInclude ID3DXInclude_iface;
92 };
93
94 static void assembleshader_test(void) {
95     const char test1[] = {
96         "vs.1.1\n"
97         "mov DEF2, v0\n"
98     };
99     const char testincl[] = {
100         "#define REGISTER r0\n"
101         "vs.1.1\n"
102     };
103     const char testshader[] = {
104         "#include \"incl.vsh\"\n"
105         "mov REGISTER, v0\n"
106     };
107     const char testshader2[] = {
108         "#include \"incl2.vsh\"\n"
109         "mov REGISTER, v0\n"
110     };
111     const char testshader3[] = {
112         "#include \"include/incl3.vsh\"\n"
113         "mov REGISTER, v0\n"
114     };
115     const char testincl3[] = {
116         "#include \"incl4.vsh\"\n"
117     };
118     const char testincl4_ok[] = {
119         "#define REGISTER r0\n"
120         "vs.1.1\n"
121     };
122     const char testincl4_wrong[] = {
123         "#error \"wrong include\"\n"
124     };
125     HRESULT hr;
126     ID3DXBuffer *shader, *messages;
127     D3DXMACRO defines[] = {
128         {
129             "DEF1", "10 + 15"
130         },
131         {
132             "DEF2", "r0"
133         },
134         {
135             NULL, NULL
136         }
137     };
138     struct D3DXIncludeImpl include;
139     HRESULT shader_vsh_res;
140
141     /* pDefines test */
142     shader = NULL;
143     messages = NULL;
144     hr = D3DXAssembleShader(test1, strlen(test1),
145                             defines, NULL, D3DXSHADER_SKIPVALIDATION,
146                             &shader, &messages);
147     ok(hr == D3D_OK, "pDefines test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
148     if(messages) {
149         trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
150         ID3DXBuffer_Release(messages);
151     }
152     if(shader) ID3DXBuffer_Release(shader);
153
154     /* NULL messages test */
155     shader = NULL;
156     hr = D3DXAssembleShader(test1, strlen(test1),
157                             defines, NULL, D3DXSHADER_SKIPVALIDATION,
158                             &shader, NULL);
159     ok(hr == D3D_OK, "NULL messages test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
160     if(shader) ID3DXBuffer_Release(shader);
161
162     /* NULL shader test */
163     messages = NULL;
164     hr = D3DXAssembleShader(test1, strlen(test1),
165                             defines, NULL, D3DXSHADER_SKIPVALIDATION,
166                             NULL, &messages);
167     ok(hr == D3D_OK, "NULL shader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
168     if(messages) {
169         trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
170         ID3DXBuffer_Release(messages);
171     }
172
173     /* pInclude test */
174     shader = NULL;
175     messages = NULL;
176     include.ID3DXInclude_iface.lpVtbl = &D3DXInclude_Vtbl;
177     hr = D3DXAssembleShader(testshader, strlen(testshader), NULL, &include.ID3DXInclude_iface,
178                             D3DXSHADER_SKIPVALIDATION, &shader, &messages);
179     ok(hr == D3D_OK, "pInclude test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
180     if(messages) {
181         trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
182         ID3DXBuffer_Release(messages);
183     }
184     if(shader) ID3DXBuffer_Release(shader);
185
186     /* "unexpected #include file from memory" test */
187     shader = NULL;
188     messages = NULL;
189     hr = D3DXAssembleShader(testshader, strlen(testshader),
190                             NULL, NULL, D3DXSHADER_SKIPVALIDATION,
191                             &shader, &messages);
192     ok(hr == D3DXERR_INVALIDDATA, "D3DXAssembleShader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
193     if(messages) {
194         trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
195         ID3DXBuffer_Release(messages);
196     }
197     if(shader) ID3DXBuffer_Release(shader);
198
199     /* recursive #include test */
200     shader = NULL;
201     messages = NULL;
202     hr = D3DXAssembleShader(testshader2, strlen(testshader2), NULL, &include.ID3DXInclude_iface,
203                             D3DXSHADER_SKIPVALIDATION, &shader, &messages);
204     ok(hr == D3D_OK, "D3DXAssembleShader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
205     if(messages) {
206         trace("recursive D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
207         ID3DXBuffer_Release(messages);
208     }
209     if(shader) ID3DXBuffer_Release(shader);
210
211     shader_vsh_res = create_file("shader.vsh", testshader, sizeof(testshader) - 1);
212     if(SUCCEEDED(shader_vsh_res)) {
213         create_file("incl.vsh", testincl, sizeof(testincl) - 1);
214
215         /* D3DXAssembleShaderFromFile + #include test */
216         shader = NULL;
217         messages = NULL;
218         hr = D3DXAssembleShaderFromFileA("shader.vsh",
219                                          NULL, NULL, D3DXSHADER_SKIPVALIDATION,
220                                          &shader, &messages);
221         ok(hr == D3D_OK, "D3DXAssembleShaderFromFile test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
222         if(messages) {
223             trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
224             ID3DXBuffer_Release(messages);
225         }
226         if(shader) ID3DXBuffer_Release(shader);
227
228         /* D3DXAssembleShaderFromFile + pInclude test */
229         shader = NULL;
230         messages = NULL;
231         hr = D3DXAssembleShaderFromFileA("shader.vsh", NULL, &include.ID3DXInclude_iface,
232                                          D3DXSHADER_SKIPVALIDATION, &shader, &messages);
233         ok(hr == D3D_OK, "D3DXAssembleShaderFromFile + pInclude test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
234         if(messages) {
235             trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
236             ID3DXBuffer_Release(messages);
237         }
238         if(shader) ID3DXBuffer_Release(shader);
239
240         create_file("shader3.vsh", testshader3, sizeof(testshader3) - 1);
241         create_file("incl4.vsh", testincl4_wrong, sizeof(testincl4_wrong) - 1);
242         if(CreateDirectoryA("include", NULL)) {
243             create_file("include/incl3.vsh", testincl3, sizeof(testincl3) - 1);
244             create_file("include/incl4.vsh", testincl4_ok, sizeof(testincl4_ok) - 1);
245
246             /* path search #include test */
247             shader = NULL;
248             messages = NULL;
249             hr = D3DXAssembleShaderFromFileA("shader3.vsh", NULL, NULL,
250                                              D3DXSHADER_SKIPVALIDATION,
251                                              &shader, &messages);
252             ok(hr == D3D_OK, "D3DXAssembleShaderFromFile path search test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
253             if(messages) {
254                 trace("D3DXAssembleShaderFromFile path search messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
255                 ID3DXBuffer_Release(messages);
256             }
257             if(shader) ID3DXBuffer_Release(shader);
258         } else skip("Couldn't create \"include\" directory\n");
259     } else skip("Couldn't create \"shader.vsh\"\n");
260
261     /* NULL shader tests */
262     shader = NULL;
263     messages = NULL;
264     hr = D3DXAssembleShader(NULL, 0,
265                             NULL, NULL, D3DXSHADER_SKIPVALIDATION,
266                             &shader, &messages);
267     ok(hr == D3DXERR_INVALIDDATA, "NULL shader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
268     if(messages) {
269         trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
270         ID3DXBuffer_Release(messages);
271     }
272     if(shader) ID3DXBuffer_Release(shader);
273
274     shader = NULL;
275     messages = NULL;
276     hr = D3DXAssembleShaderFromFileA("nonexistent.vsh",
277                                      NULL, NULL, D3DXSHADER_SKIPVALIDATION,
278                                      &shader, &messages);
279     ok(hr == D3DXERR_INVALIDDATA || hr == E_FAIL, /* I get this on WinXP */
280         "D3DXAssembleShaderFromFile nonexistent file test failed with error 0x%x - %d\n",
281         hr, hr & 0x0000FFFF);
282     if(messages) {
283         trace("D3DXAssembleShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
284         ID3DXBuffer_Release(messages);
285     }
286     if(shader) ID3DXBuffer_Release(shader);
287
288     /* D3DXAssembleShaderFromResource test */
289     shader = NULL;
290     messages = NULL;
291     hr = D3DXAssembleShaderFromResourceA(NULL, MAKEINTRESOURCEA(IDB_ASMSHADER),
292                                          NULL, NULL, D3DXSHADER_SKIPVALIDATION,
293                                          &shader, &messages);
294     ok(hr == D3D_OK, "D3DXAssembleShaderFromResource test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
295     if(messages) {
296         trace("D3DXAssembleShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
297         ID3DXBuffer_Release(messages);
298     }
299     if(shader) ID3DXBuffer_Release(shader);
300
301     /* D3DXAssembleShaderFromResource with missing shader resource test */
302     shader = NULL;
303     messages = NULL;
304     hr = D3DXAssembleShaderFromResourceA(NULL, "notexisting",
305                                          NULL, NULL, D3DXSHADER_SKIPVALIDATION,
306                                          &shader, &messages);
307     ok(hr == D3DXERR_INVALIDDATA, "D3DXAssembleShaderFromResource NULL shader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
308     if(messages) {
309         trace("D3DXAssembleShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
310         ID3DXBuffer_Release(messages);
311     }
312     if(shader) ID3DXBuffer_Release(shader);
313
314     /* cleanup */
315     if(SUCCEEDED(shader_vsh_res)) {
316         DeleteFileA("shader.vsh");
317         DeleteFileA("incl.vsh");
318         DeleteFileA("shader3.vsh");
319         DeleteFileA("incl4.vsh");
320         DeleteFileA("include/incl3.vsh");
321         DeleteFileA("include/incl4.vsh");
322         RemoveDirectoryA("include");
323     }
324 }
325
326 static void d3dxpreprocess_test(void) {
327     const char testincl[] = {
328         "#define REGISTER r0\n"
329         "vs.1.1\n"
330     };
331     const char testshader[] = {
332         "#include \"incl.vsh\"\n"
333         "mov REGISTER, v0\n"
334     };
335     const char testshader3[] = {
336         "#include \"include/incl3.vsh\"\n"
337         "mov REGISTER, v0\n"
338     };
339     const char testincl3[] = {
340         "#include \"incl4.vsh\"\n"
341     };
342     const char testincl4_ok[] = {
343         "#define REGISTER r0\n"
344         "vs.1.1\n"
345     };
346     const char testincl4_wrong[] = {
347         "#error \"wrong include\"\n"
348     };
349     HRESULT hr;
350     ID3DXBuffer *shader, *messages;
351     HRESULT shader_vsh_res;
352     struct D3DXIncludeImpl include = {{&D3DXInclude_Vtbl}};
353
354     shader_vsh_res = create_file("shader.vsh", testshader, sizeof(testshader) - 1);
355     if(SUCCEEDED(shader_vsh_res)) {
356         create_file("incl.vsh", testincl, sizeof(testincl) - 1);
357         create_file("shader3.vsh", testshader3, sizeof(testshader3) - 1);
358         create_file("incl4.vsh", testincl4_wrong, sizeof(testincl4_wrong) - 1);
359         if(CreateDirectoryA("include", NULL)) {
360             create_file("include/incl3.vsh", testincl3, sizeof(testincl3) - 1);
361             create_file("include/incl4.vsh", testincl4_ok, sizeof(testincl4_ok) - 1);
362
363             /* path search #include test */
364             shader = NULL;
365             messages = NULL;
366             hr = D3DXPreprocessShaderFromFileA("shader3.vsh", NULL, NULL,
367                                                &shader, &messages);
368             ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile path search test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
369             if(messages) {
370                 trace("D3DXPreprocessShaderFromFile path search messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
371                 ID3DXBuffer_Release(messages);
372             }
373             if(shader) ID3DXBuffer_Release(shader);
374         } else skip("Couldn't create \"include\" directory\n");
375
376         /* D3DXPreprocessShaderFromFile + #include test */
377         shader = NULL;
378         messages = NULL;
379         hr = D3DXPreprocessShaderFromFileA("shader.vsh",
380                                            NULL, NULL,
381                                            &shader, &messages);
382         ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
383         if(messages) {
384             trace("D3DXPreprocessShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
385             ID3DXBuffer_Release(messages);
386         }
387         if(shader) ID3DXBuffer_Release(shader);
388
389         /* D3DXPreprocessShaderFromFile + pInclude test */
390         shader = NULL;
391         messages = NULL;
392         hr = D3DXPreprocessShaderFromFileA("shader.vsh", NULL, &include.ID3DXInclude_iface,
393                                            &shader, &messages);
394         ok(hr == D3D_OK, "D3DXPreprocessShaderFromFile + pInclude test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
395         if(messages) {
396             trace("D3DXPreprocessShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
397             ID3DXBuffer_Release(messages);
398         }
399         if(shader) ID3DXBuffer_Release(shader);
400     } else skip("Couldn't create \"shader.vsh\"\n");
401
402     /* NULL shader tests */
403     shader = NULL;
404     messages = NULL;
405     hr = D3DXPreprocessShaderFromFileA("nonexistent.vsh",
406                                        NULL, NULL,
407                                        &shader, &messages);
408     ok(hr == D3DXERR_INVALIDDATA || hr == E_FAIL, /* I get this on WinXP */
409         "D3DXPreprocessShaderFromFile nonexistent file test failed with error 0x%x - %d\n",
410         hr, hr & 0x0000FFFF);
411     if(messages) {
412         trace("D3DXPreprocessShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
413         ID3DXBuffer_Release(messages);
414     }
415     if(shader) ID3DXBuffer_Release(shader);
416
417     /* D3DXPreprocessShaderFromResource test */
418     shader = NULL;
419     messages = NULL;
420     hr = D3DXPreprocessShaderFromResourceA(NULL, MAKEINTRESOURCEA(IDB_ASMSHADER),
421                                            NULL, NULL,
422                                            &shader, &messages);
423     ok(hr == D3D_OK, "D3DXPreprocessShaderFromResource test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
424     if(messages) {
425         trace("D3DXPreprocessShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
426         ID3DXBuffer_Release(messages);
427     }
428     if(shader) ID3DXBuffer_Release(shader);
429
430     /* D3DXPreprocessShaderFromResource with missing shader resource test */
431     shader = NULL;
432     messages = NULL;
433     hr = D3DXPreprocessShaderFromResourceA(NULL, "notexisting",
434                                            NULL, NULL,
435                                            &shader, &messages);
436     ok(hr == D3DXERR_INVALIDDATA, "D3DXPreprocessShaderFromResource NULL shader test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
437     if(messages) {
438         trace("D3DXPreprocessShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
439         ID3DXBuffer_Release(messages);
440     }
441     if(shader) ID3DXBuffer_Release(shader);
442
443     /* cleanup */
444     if(SUCCEEDED(shader_vsh_res)) {
445         DeleteFileA("shader.vsh");
446         DeleteFileA("incl.vsh");
447         DeleteFileA("shader3.vsh");
448         DeleteFileA("incl4.vsh");
449         DeleteFileA("include/incl3.vsh");
450         DeleteFileA("include/incl4.vsh");
451         RemoveDirectoryA("include");
452     }
453 }
454
455 START_TEST(asm)
456 {
457     assembleshader_test();
458
459     d3dxpreprocess_test();
460 }