2 * Copyright (C) 2008 Stefan Dösinger
3 * Copyright (C) 2009 Matteo Bruni
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.
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.
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
21 #include "wine/test.h"
25 #include "resources.h"
27 static char temp_path
[MAX_PATH
];
29 static BOOL
create_file(const char *filename
, const char *data
, const unsigned int size
, char *out_path
)
36 GetTempPathA(sizeof(temp_path
), temp_path
);
38 strcpy(path
, temp_path
);
39 strcat(path
, filename
);
40 hfile
= CreateFileA(path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, 0);
41 if (hfile
== INVALID_HANDLE_VALUE
)
44 if (WriteFile(hfile
, data
, size
, &written
, NULL
))
49 strcpy(out_path
, path
);
57 static void delete_file(const char *filename
)
61 strcpy(path
, temp_path
);
62 strcat(path
, filename
);
66 static BOOL
create_directory(const char *name
)
70 strcpy(path
, temp_path
);
72 return CreateDirectoryA(path
, NULL
);
75 static void delete_directory(const char *name
)
79 strcpy(path
, temp_path
);
81 RemoveDirectoryA(path
);
84 static HRESULT WINAPI
testD3DXInclude_open(ID3DXInclude
*iface
, D3DXINCLUDE_TYPE include_type
,
85 const char *filename
, const void *parent_data
, const void **data
, UINT
*bytes
)
88 static const char shader
[] =
89 "#include \"incl.vsh\"\n"
91 static const char include
[] = "#define REGISTER r0\nvs.1.1\n";
92 static const char include2
[] = "#include \"incl3.vsh\"\n";
93 static const char include3
[] = "vs.1.1\n";
95 trace("filename %s.\n", filename
);
96 trace("parent_data %p: %s.\n", parent_data
, parent_data
? (char *)parent_data
: "(null)");
98 if (!strcmp(filename
, "shader.vsh"))
100 buffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(shader
));
101 memcpy(buffer
, shader
, sizeof(shader
));
102 *bytes
= sizeof(shader
);
104 else if (!strcmp(filename
, "incl.vsh"))
106 buffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(include
));
107 memcpy(buffer
, include
, sizeof(include
));
108 *bytes
= sizeof(include
);
109 /* This is included from the first D3DXAssembleShader with non-null ID3DXInclude test
110 * (parent_data == NULL) and from shader.vsh / shader[] (with matching parent_data).
111 * Allow both cases. */
112 ok(parent_data
== NULL
|| !strncmp(shader
, parent_data
, strlen(shader
)), "wrong parent_data value\n");
114 else if (!strcmp(filename
, "incl2.vsh"))
116 buffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(include2
));
117 memcpy(buffer
, include2
, sizeof(include2
));
118 *bytes
= sizeof(include2
);
120 else if (!strcmp(filename
, "incl3.vsh"))
122 buffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(include3
));
123 memcpy(buffer
, include3
, sizeof(include3
));
124 *bytes
= sizeof(include3
);
125 /* Also check for the correct parent_data content */
126 ok(parent_data
!= NULL
&& !strncmp(include2
, parent_data
, strlen(include2
)), "wrong parent_data value\n");
128 else if (!strcmp(filename
, "include/incl3.vsh"))
130 buffer
= HeapAlloc(GetProcessHeap(), 0, sizeof(include
));
131 memcpy(buffer
, include
, sizeof(include
));
132 *bytes
= sizeof(include
);
133 ok(!parent_data
, "wrong parent_data value\n");
137 ok(0, "Unexpected #include for file %s.\n", filename
);
138 return D3DERR_INVALIDCALL
;
144 static HRESULT WINAPI
testD3DXInclude_close(ID3DXInclude
*iface
, const void *data
)
146 HeapFree(GetProcessHeap(), 0, (void *)data
);
150 static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl
= {
151 testD3DXInclude_open
,
152 testD3DXInclude_close
155 struct D3DXIncludeImpl
{
156 ID3DXInclude ID3DXInclude_iface
;
159 static void assembleshader_test(void)
161 static const char test1
[] =
164 static const char testincl
[] =
165 "#define REGISTER r0\n"
167 static const char testshader
[] =
168 "#include \"incl.vsh\"\n"
169 "mov REGISTER, v0\n";
170 static const char testshader2
[] =
171 "#include \"incl2.vsh\"\n"
172 "mov REGISTER, v0\n";
173 static const char testshader3
[] =
174 "#include \"include/incl3.vsh\"\n"
175 "mov REGISTER, v0\n";
176 static const char testincl3
[] =
177 "#include \"incl4.vsh\"\n";
178 static const char testincl4_ok
[] =
179 "#define REGISTER r0\n"
181 static const char testincl4_wrong
[] =
182 "#error \"wrong include\"\n";
184 ID3DXBuffer
*shader
, *messages
;
185 static const D3DXMACRO defines
[] = {
196 struct D3DXIncludeImpl include
;
197 char shader_vsh_path
[MAX_PATH
], shader3_vsh_path
[MAX_PATH
];
198 static const WCHAR shader_filename_w
[] = {'s','h','a','d','e','r','.','v','s','h',0};
203 hr
= D3DXAssembleShader(test1
, strlen(test1
),
204 defines
, NULL
, D3DXSHADER_SKIPVALIDATION
,
206 ok(hr
== D3D_OK
, "pDefines test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
208 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
209 ID3DXBuffer_Release(messages
);
211 if(shader
) ID3DXBuffer_Release(shader
);
213 /* NULL messages test */
215 hr
= D3DXAssembleShader(test1
, strlen(test1
),
216 defines
, NULL
, D3DXSHADER_SKIPVALIDATION
,
218 ok(hr
== D3D_OK
, "NULL messages test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
219 if(shader
) ID3DXBuffer_Release(shader
);
221 /* NULL shader test */
223 hr
= D3DXAssembleShader(test1
, strlen(test1
),
224 defines
, NULL
, D3DXSHADER_SKIPVALIDATION
,
226 ok(hr
== D3D_OK
, "NULL shader test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
228 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
229 ID3DXBuffer_Release(messages
);
235 include
.ID3DXInclude_iface
.lpVtbl
= &D3DXInclude_Vtbl
;
236 hr
= D3DXAssembleShader(testshader
, strlen(testshader
), NULL
, &include
.ID3DXInclude_iface
,
237 D3DXSHADER_SKIPVALIDATION
, &shader
, &messages
);
238 ok(hr
== D3D_OK
, "pInclude test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
240 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
241 ID3DXBuffer_Release(messages
);
243 if(shader
) ID3DXBuffer_Release(shader
);
245 /* "unexpected #include file from memory" test */
248 hr
= D3DXAssembleShader(testshader
, strlen(testshader
),
249 NULL
, NULL
, D3DXSHADER_SKIPVALIDATION
,
251 ok(hr
== D3DXERR_INVALIDDATA
, "D3DXAssembleShader test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
253 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
254 ID3DXBuffer_Release(messages
);
256 if(shader
) ID3DXBuffer_Release(shader
);
258 /* recursive #include test */
261 hr
= D3DXAssembleShader(testshader2
, strlen(testshader2
), NULL
, &include
.ID3DXInclude_iface
,
262 D3DXSHADER_SKIPVALIDATION
, &shader
, &messages
);
263 ok(hr
== D3D_OK
, "D3DXAssembleShader test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
265 trace("recursive D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
266 ID3DXBuffer_Release(messages
);
268 if(shader
) ID3DXBuffer_Release(shader
);
270 /* #include with a path. */
273 hr
= D3DXAssembleShader(testshader3
, strlen(testshader3
), NULL
, &include
.ID3DXInclude_iface
,
274 D3DXSHADER_SKIPVALIDATION
, &shader
, &messages
);
275 ok(hr
== D3D_OK
, "D3DXAssembleShader test failed with error 0x%x - %d\n", hr
, hr
& 0x0000ffff);
278 trace("Path search D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
279 ID3DXBuffer_Release(messages
);
282 ID3DXBuffer_Release(shader
);
284 if (create_file("shader.vsh", testshader
, sizeof(testshader
) - 1, shader_vsh_path
))
286 create_file("incl.vsh", testincl
, sizeof(testincl
) - 1, NULL
);
288 /* D3DXAssembleShaderFromFile + #include test */
291 hr
= D3DXAssembleShaderFromFileA(shader_vsh_path
,
292 NULL
, NULL
, D3DXSHADER_SKIPVALIDATION
,
294 ok(hr
== D3D_OK
, "D3DXAssembleShaderFromFile test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
296 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
297 ID3DXBuffer_Release(messages
);
299 if(shader
) ID3DXBuffer_Release(shader
);
301 /* D3DXAssembleShaderFromFile + pInclude test */
304 hr
= D3DXAssembleShaderFromFileA("shader.vsh", NULL
, &include
.ID3DXInclude_iface
,
305 D3DXSHADER_SKIPVALIDATION
, &shader
, &messages
);
306 ok(hr
== D3D_OK
, "D3DXAssembleShaderFromFile + pInclude test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
308 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
309 ID3DXBuffer_Release(messages
);
311 if(shader
) ID3DXBuffer_Release(shader
);
313 create_file("shader3.vsh", testshader3
, sizeof(testshader3
) - 1, shader3_vsh_path
);
314 create_file("incl4.vsh", testincl4_wrong
, sizeof(testincl4_wrong
) - 1, NULL
);
315 if (create_directory("include"))
317 create_file("include\\incl3.vsh", testincl3
, sizeof(testincl3
) - 1, NULL
);
318 create_file("include\\incl4.vsh", testincl4_ok
, sizeof(testincl4_ok
) - 1, NULL
);
320 /* path search #include test */
323 hr
= D3DXAssembleShaderFromFileA(shader3_vsh_path
, NULL
, NULL
,
324 D3DXSHADER_SKIPVALIDATION
,
326 ok(hr
== D3D_OK
, "D3DXAssembleShaderFromFile path search test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
328 trace("D3DXAssembleShaderFromFile path search messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
329 ID3DXBuffer_Release(messages
);
331 if(shader
) ID3DXBuffer_Release(shader
);
332 } else skip("Couldn't create \"include\" directory\n");
334 delete_file("shader.vsh");
335 delete_file("incl.vsh");
336 delete_file("shader3.vsh");
337 delete_file("incl4.vsh");
338 delete_file("include\\incl3.vsh");
339 delete_file("include\\incl4.vsh");
340 delete_directory("include");
342 /* The main shader is also to be loaded through the ID3DXInclude object. */
345 hr
= D3DXAssembleShaderFromFileA("shader.vsh", NULL
, &include
.ID3DXInclude_iface
,
346 D3DXSHADER_SKIPVALIDATION
, &shader
, &messages
);
347 ok(hr
== D3D_OK
, "D3DXAssembleShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n",
348 hr
, hr
& 0x0000ffff);
351 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
352 ID3DXBuffer_Release(messages
);
355 ID3DXBuffer_Release(shader
);
359 hr
= D3DXAssembleShaderFromFileW(shader_filename_w
, NULL
, &include
.ID3DXInclude_iface
,
360 D3DXSHADER_SKIPVALIDATION
, &shader
, &messages
);
361 ok(hr
== D3D_OK
, "D3DXAssembleShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n",
362 hr
, hr
& 0x0000ffff);
365 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
366 ID3DXBuffer_Release(messages
);
369 ID3DXBuffer_Release(shader
);
370 } else skip("Couldn't create \"shader.vsh\"\n");
372 /* NULL shader tests */
375 hr
= D3DXAssembleShader(NULL
, 0,
376 NULL
, NULL
, D3DXSHADER_SKIPVALIDATION
,
378 ok(hr
== D3DXERR_INVALIDDATA
, "NULL shader test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
380 trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
381 ID3DXBuffer_Release(messages
);
383 if(shader
) ID3DXBuffer_Release(shader
);
387 hr
= D3DXAssembleShaderFromFileA("nonexistent.vsh",
388 NULL
, NULL
, D3DXSHADER_SKIPVALIDATION
,
390 ok(hr
== D3DXERR_INVALIDDATA
|| hr
== E_FAIL
, /* I get this on WinXP */
391 "D3DXAssembleShaderFromFile nonexistent file test failed with error 0x%x - %d\n",
392 hr
, hr
& 0x0000FFFF);
394 trace("D3DXAssembleShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
395 ID3DXBuffer_Release(messages
);
397 if(shader
) ID3DXBuffer_Release(shader
);
399 /* D3DXAssembleShaderFromResource test */
402 hr
= D3DXAssembleShaderFromResourceA(NULL
, MAKEINTRESOURCEA(IDB_ASMSHADER
),
403 NULL
, NULL
, D3DXSHADER_SKIPVALIDATION
,
405 ok(hr
== D3D_OK
, "D3DXAssembleShaderFromResource test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
407 trace("D3DXAssembleShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
408 ID3DXBuffer_Release(messages
);
410 if(shader
) ID3DXBuffer_Release(shader
);
412 /* D3DXAssembleShaderFromResource with missing shader resource test */
415 hr
= D3DXAssembleShaderFromResourceA(NULL
, "notexisting",
416 NULL
, NULL
, D3DXSHADER_SKIPVALIDATION
,
418 ok(hr
== D3DXERR_INVALIDDATA
, "D3DXAssembleShaderFromResource NULL shader test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
420 trace("D3DXAssembleShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
421 ID3DXBuffer_Release(messages
);
423 if(shader
) ID3DXBuffer_Release(shader
);
426 static void d3dxpreprocess_test(void)
428 static const char testincl
[] =
429 "#define REGISTER r0\n"
431 static const char testshader
[] =
432 "#include \"incl.vsh\"\n"
433 "mov REGISTER, v0\n";
434 static const char testshader3
[] =
435 "#include \"include/incl3.vsh\"\n"
436 "mov REGISTER, v0\n";
437 static const char testincl3
[] =
438 "#include \"incl4.vsh\"\n";
439 static const char testincl4_ok
[] =
440 "#define REGISTER r0\n"
442 static const char testincl4_wrong
[] =
443 "#error \"wrong include\"\n";
445 ID3DXBuffer
*shader
, *messages
;
446 char shader_vsh_path
[MAX_PATH
], shader3_vsh_path
[MAX_PATH
];
447 static struct D3DXIncludeImpl include
= {{&D3DXInclude_Vtbl
}};
448 static const WCHAR shader_filename_w
[] = {'s','h','a','d','e','r','.','v','s','h',0};
450 if (create_file("shader.vsh", testshader
, sizeof(testshader
) - 1, shader_vsh_path
))
452 create_file("incl.vsh", testincl
, sizeof(testincl
) - 1, NULL
);
453 create_file("shader3.vsh", testshader3
, sizeof(testshader3
) - 1, shader3_vsh_path
);
454 create_file("incl4.vsh", testincl4_wrong
, sizeof(testincl4_wrong
) - 1, NULL
);
455 if (create_directory("include"))
457 create_file("include\\incl3.vsh", testincl3
, sizeof(testincl3
) - 1, NULL
);
458 create_file("include\\incl4.vsh", testincl4_ok
, sizeof(testincl4_ok
) - 1, NULL
);
460 /* path search #include test */
463 hr
= D3DXPreprocessShaderFromFileA(shader3_vsh_path
, NULL
, NULL
,
465 ok(hr
== D3D_OK
, "D3DXPreprocessShaderFromFile path search test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
467 trace("D3DXPreprocessShaderFromFile path search messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
468 ID3DXBuffer_Release(messages
);
470 if(shader
) ID3DXBuffer_Release(shader
);
471 } else skip("Couldn't create \"include\" directory\n");
473 /* D3DXPreprocessShaderFromFile + #include test */
476 hr
= D3DXPreprocessShaderFromFileA(shader_vsh_path
,
479 ok(hr
== D3D_OK
, "D3DXPreprocessShaderFromFile test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
481 trace("D3DXPreprocessShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
482 ID3DXBuffer_Release(messages
);
484 if(shader
) ID3DXBuffer_Release(shader
);
486 /* D3DXPreprocessShaderFromFile + pInclude test */
489 hr
= D3DXPreprocessShaderFromFileA("shader.vsh", NULL
, &include
.ID3DXInclude_iface
,
491 ok(hr
== D3D_OK
, "D3DXPreprocessShaderFromFile + pInclude test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
493 trace("D3DXPreprocessShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
494 ID3DXBuffer_Release(messages
);
496 if(shader
) ID3DXBuffer_Release(shader
);
498 delete_file("shader.vsh");
499 delete_file("incl.vsh");
500 delete_file("shader3.vsh");
501 delete_file("incl4.vsh");
502 delete_file("include\\incl3.vsh");
503 delete_file("include\\incl4.vsh");
504 delete_directory("include");
506 /* The main shader is also to be loaded through the ID3DXInclude object. */
509 hr
= D3DXPreprocessShaderFromFileA("shader.vsh", NULL
, &include
.ID3DXInclude_iface
,
511 ok(hr
== D3D_OK
, "D3DXPreprocessShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n",
512 hr
, hr
& 0x0000ffff);
515 trace("D3DXPreprocessShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
516 ID3DXBuffer_Release(messages
);
519 ID3DXBuffer_Release(shader
);
523 hr
= D3DXPreprocessShaderFromFileW(shader_filename_w
, NULL
, &include
.ID3DXInclude_iface
,
525 ok(hr
== D3D_OK
, "D3DXPreprocessShaderFromFile + pInclude main shader test failed with error 0x%x - %d\n",
526 hr
, hr
& 0x0000ffff);
529 trace("D3DXPreprocessShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
530 ID3DXBuffer_Release(messages
);
533 ID3DXBuffer_Release(shader
);
534 } else skip("Couldn't create \"shader.vsh\"\n");
536 /* NULL shader tests */
539 hr
= D3DXPreprocessShaderFromFileA("nonexistent.vsh",
542 ok(hr
== D3DXERR_INVALIDDATA
|| hr
== E_FAIL
, /* I get this on WinXP */
543 "D3DXPreprocessShaderFromFile nonexistent file test failed with error 0x%x - %d\n",
544 hr
, hr
& 0x0000FFFF);
546 trace("D3DXPreprocessShaderFromFile messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
547 ID3DXBuffer_Release(messages
);
549 if(shader
) ID3DXBuffer_Release(shader
);
551 /* D3DXPreprocessShaderFromResource test */
554 hr
= D3DXPreprocessShaderFromResourceA(NULL
, MAKEINTRESOURCEA(IDB_ASMSHADER
),
557 ok(hr
== D3D_OK
, "D3DXPreprocessShaderFromResource test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
559 trace("D3DXPreprocessShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
560 ID3DXBuffer_Release(messages
);
562 if(shader
) ID3DXBuffer_Release(shader
);
564 /* D3DXPreprocessShaderFromResource with missing shader resource test */
567 hr
= D3DXPreprocessShaderFromResourceA(NULL
, "notexisting",
570 ok(hr
== D3DXERR_INVALIDDATA
, "D3DXPreprocessShaderFromResource NULL shader test failed with error 0x%x - %d\n", hr
, hr
& 0x0000FFFF);
572 trace("D3DXPreprocessShaderFromResource messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages
));
573 ID3DXBuffer_Release(messages
);
575 if(shader
) ID3DXBuffer_Release(shader
);
580 assembleshader_test();
582 d3dxpreprocess_test();