wldap32: Fix French translation.
[wine] / dlls / d3d8 / tests / stateblock.c
1 /*
2  * Copyright 2006 Ivan Gyurdiev
3  * Copyright 2005, 2008 Henri Verbeet
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
20 #define COBJMACROS
21 #include <d3d8.h>
22 #include "wine/test.h"
23
24 static DWORD texture_stages;
25
26 static HWND create_window(void)
27 {
28     WNDCLASS wc = {0};
29     wc.lpfnWndProc = DefWindowProc;
30     wc.lpszClassName = "d3d8_test_wc";
31     RegisterClass(&wc);
32
33     return CreateWindow("d3d8_test_wc", "d3d8_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
34 }
35
36 static HRESULT init_d3d8(HMODULE d3d8_module, IDirect3DDevice8 **device, D3DPRESENT_PARAMETERS *device_pparams)
37 {
38     IDirect3D8 * (WINAPI *d3d8_create)(UINT SDKVersion) = 0;
39     D3DDISPLAYMODE d3ddm;
40     IDirect3D8 *d3d8 = 0;
41     HWND window;
42     HRESULT hr;
43
44     d3d8_create = (void *)GetProcAddress(d3d8_module, "Direct3DCreate8");
45     if (!d3d8_create) return E_FAIL;
46
47     d3d8 = d3d8_create(D3D_SDK_VERSION);
48     if (!d3d8)
49     {
50         skip("Failed to create D3D8 object.\n");
51         return E_FAIL;
52     }
53
54     window = create_window();
55
56     IDirect3D8_GetAdapterDisplayMode(d3d8, D3DADAPTER_DEFAULT, &d3ddm);
57     memset(device_pparams, 0, sizeof(*device_pparams));
58     device_pparams->Windowed = TRUE;
59     device_pparams->SwapEffect = D3DSWAPEFFECT_DISCARD;
60     device_pparams->BackBufferFormat = d3ddm.Format;
61
62     hr = IDirect3D8_CreateDevice(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, window,
63             D3DCREATE_SOFTWARE_VERTEXPROCESSING, device_pparams, device);
64     ok(SUCCEEDED(hr) || hr == D3DERR_NOTAVAILABLE || broken(hr == D3DERR_INVALIDCALL),
65             "IDirect3D8_CreateDevice failed, hr %#x.\n", hr);
66
67     return hr;
68 }
69
70 static void test_begin_end_state_block(IDirect3DDevice8 *device)
71 {
72     DWORD state_block;
73     HRESULT hr;
74
75     /* Should succeed */
76     hr = IDirect3DDevice8_BeginStateBlock(device);
77     ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#x.\n", hr);
78     if (FAILED(hr)) return;
79
80     /* Calling BeginStateBlock while recording should return D3DERR_INVALIDCALL */
81     hr = IDirect3DDevice8_BeginStateBlock(device);
82     ok(hr == D3DERR_INVALIDCALL, "BeginStateBlock returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
83     if (hr != D3DERR_INVALIDCALL) return;
84
85     /* Should succeed */
86     state_block = 0xdeadbeef;
87     hr = IDirect3DDevice8_EndStateBlock(device, &state_block);
88     ok(SUCCEEDED(hr) && state_block && state_block != 0xdeadbeef,
89             "EndStateBlock returned: hr %#x, state_block %#x. "
90             "Expected hr %#x, state_block != 0, state_block != 0xdeadbeef.\n", hr, state_block, D3D_OK);
91     IDirect3DDevice8_DeleteStateBlock(device, state_block);
92
93     /* Calling EndStateBlock while not recording should return D3DERR_INVALIDCALL.
94      * state_block should not be touched. */
95     state_block = 0xdeadbeef;
96     hr = IDirect3DDevice8_EndStateBlock(device, &state_block);
97     ok(hr == D3DERR_INVALIDCALL && state_block == 0xdeadbeef,
98             "EndStateBlock returned: hr %#x, state_block %#x. "
99             "Expected hr %#x, state_block 0xdeadbeef.\n", hr, state_block, D3DERR_INVALIDCALL);
100 }
101
102 /* ============================ State Testing Framework ========================== */
103
104 struct state_test
105 {
106     const char *test_name;
107
108     /* The initial data is usually the same
109      * as the default data, but a write can have side effects.
110      * The initial data is tested first, before any writes take place
111      * The default data can be tested after a write */
112     const void *initial_data;
113
114     /* The default data is the standard state to compare
115      * against, and restore to */
116     const void *default_data;
117
118     /* The test data is the experiment data to try
119      * in - what we want to write
120      * out - what windows will actually write (not necessarily the same)  */
121     const void *test_data_in;
122     const void *test_data_out;
123
124     /* The poison data is the data to preinitialize the return buffer to */
125     const void *poison_data;
126
127     /* Return buffer */
128     void *return_data;
129
130     /* Size of the data samples above */
131     unsigned int data_size;
132
133     /* Test resource management handlers */
134     HRESULT (*setup_handler)(struct state_test *test);
135     void (*teardown_handler)(struct state_test *test);
136
137     /* Test data handlers */
138     void (*set_handler)(IDirect3DDevice8 *device, const struct state_test *test, const void *data_in);
139     void (*get_handler)(IDirect3DDevice8 *device, const struct state_test *test, void *data_out);
140     void (*print_handler)(const struct state_test *test, const void *data);
141
142     /* Test arguments */
143     const void *test_arg;
144
145     /* Test-specific context data */
146     void *test_context;
147 };
148
149 /* See below for explanation of the flags */
150 #define EVENT_OK             0x00
151 #define EVENT_CHECK_DEFAULT  0x01
152 #define EVENT_CHECK_INITIAL  0x02
153 #define EVENT_CHECK_TEST     0x04
154 #define EVENT_ERROR          0x08
155 #define EVENT_APPLY_DATA     0x10
156
157 struct event
158 {
159    int (*event_fn)(IDirect3DDevice8 *device, void *arg);
160    int status;
161 };
162
163 /* This is an event-machine, which tests things.
164  * It tests get and set operations for a batch of states, based on
165  * results from the event function, which directs what's to be done */
166 static void execute_test_chain(IDirect3DDevice8 *device, struct state_test *test,
167         unsigned int ntests, struct event *event, unsigned int nevents, void *event_arg)
168 {
169     unsigned int i = 0, j;
170     int outcome;
171
172     /* For each queued event */
173     for (j = 0; j < nevents; ++j)
174     {
175         /* Execute the next event handler (if available) or just set the supplied status */
176         outcome = event[j].status;
177         if (event[j].event_fn) outcome |= event[j].event_fn(device, event_arg);
178
179         /* Now verify correct outcome depending on what was signaled by the handler.
180          * An EVENT_CHECK_TEST signal means check the returned data against the test_data (out).
181          * An EVENT_CHECK_DEFAULT signal means check the returned data against the default_data.
182          * An EVENT_CHECK_INITIAL signal means check the returned data against the initial_data.
183          * An EVENT_ERROR signal means the test isn't going to work, exit the event loop.
184          * An EVENT_APPLY_DATA signal means load the test data (after checks) */
185
186         if (outcome & EVENT_ERROR)
187         {
188             trace("Test %s, Stage %u in error state, aborting\n", test[i].test_name, j);
189             break;
190         }
191         else if (outcome & EVENT_CHECK_TEST || outcome & EVENT_CHECK_DEFAULT || outcome & EVENT_CHECK_INITIAL)
192         {
193             for (i = 0; i < ntests; ++i)
194             {
195                 memcpy(test[i].return_data, test[i].poison_data, test[i].data_size);
196                 test[i].get_handler(device, &test[i], test[i].return_data);
197
198                 if (outcome & EVENT_CHECK_TEST)
199                 {
200                     BOOL test_failed = memcmp(test[i].test_data_out, test[i].return_data, test[i].data_size);
201                     ok(!test_failed, "Test %s, Stage %u: returned data does not match test data [csize=%u]\n",
202                             test[i].test_name, j, test[i].data_size);
203
204                     if (test_failed && test[i].print_handler)
205                     {
206                         trace("Returned data was:\n");
207                         test[i].print_handler(&test[i], test[i].return_data);
208                         trace("Test data was:\n");
209                         test[i].print_handler(&test[i], test[i].test_data_out);
210                     }
211                 }
212                 else if (outcome & EVENT_CHECK_DEFAULT)
213                 {
214                     BOOL test_failed = memcmp(test[i].default_data, test[i].return_data, test[i].data_size);
215                     ok(!test_failed, "Test %s, Stage %u: returned data does not match default data [csize=%u]\n",
216                             test[i].test_name, j, test[i].data_size);
217
218                     if (test_failed && test[i].print_handler)
219                     {
220                         trace("Returned data was:\n");
221                         test[i].print_handler(&test[i], test[i].return_data);
222                         trace("Default data was:\n");
223                         test[i].print_handler(&test[i], test[i].default_data);
224                     }
225                 }
226                 else if (outcome & EVENT_CHECK_INITIAL)
227                 {
228                     BOOL test_failed = memcmp(test[i].initial_data, test[i].return_data, test[i].data_size);
229                     ok(!test_failed, "Test %s, Stage %u: returned data does not match initial data [csize=%u]\n",
230                             test[i].test_name, j, test[i].data_size);
231
232                     if (test_failed && test[i].print_handler)
233                     {
234                         trace("Returned data was:\n");
235                         test[i].print_handler(&test[i], test[i].return_data);
236                         trace("Initial data was:\n");
237                         test[i].print_handler(&test[i], test[i].initial_data);
238                     }
239                 }
240             }
241         }
242
243         if (outcome & EVENT_APPLY_DATA)
244         {
245             for (i = 0; i < ntests; ++i)
246             {
247                 test[i].set_handler(device, &test[i], test[i].test_data_in);
248             }
249         }
250     }
251
252      /* Attempt to reset any changes made */
253     for (i=0; i < ntests; i++)
254     {
255         test[i].set_handler(device, &test[i], test[i].default_data);
256     }
257 }
258
259 struct event_data
260 {
261     DWORD stateblock;
262     IDirect3DSurface8 *original_render_target;
263     IDirect3DSwapChain8 *new_swap_chain;
264 };
265
266 static int switch_render_target(IDirect3DDevice8* device, void *data)
267 {
268     D3DPRESENT_PARAMETERS present_parameters;
269     IDirect3DSwapChain8 *swapchain = NULL;
270     IDirect3DSurface8 *backbuffer = NULL;
271     struct event_data *edata = data;
272     D3DDISPLAYMODE d3ddm;
273     HRESULT hr;
274
275     /* Parameters for new swapchain */
276     IDirect3DDevice8_GetDisplayMode(device, &d3ddm);
277     memset(&present_parameters, 0, sizeof(present_parameters));
278     present_parameters.Windowed = TRUE;
279     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
280     present_parameters.BackBufferFormat = d3ddm.Format;
281
282     /* Create new swapchain */
283     hr = IDirect3DDevice8_CreateAdditionalSwapChain(device, &present_parameters, &swapchain);
284     ok(SUCCEEDED(hr), "CreateAdditionalSwapChain returned %#x.\n", hr);
285     if (FAILED(hr)) goto error;
286
287     /* Get its backbuffer */
288     hr = IDirect3DSwapChain8_GetBackBuffer(swapchain, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
289     ok(SUCCEEDED(hr), "GetBackBuffer returned %#x.\n", hr);
290     if (FAILED(hr)) goto error;
291
292     /* Save the current render target */
293     hr = IDirect3DDevice8_GetRenderTarget(device, &edata->original_render_target);
294     ok(SUCCEEDED(hr), "GetRenderTarget returned %#x.\n", hr);
295     if (FAILED(hr)) goto error;
296
297     /* Set the new swapchain's backbuffer as a render target */
298     hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, NULL);
299     ok(SUCCEEDED(hr), "SetRenderTarget returned %#x.\n", hr);
300     if (FAILED(hr)) goto error;
301
302     IDirect3DSurface8_Release(backbuffer);
303     edata->new_swap_chain = swapchain;
304     return EVENT_OK;
305
306 error:
307     if (backbuffer) IDirect3DSurface8_Release(backbuffer);
308     if (swapchain) IDirect3DSwapChain8_Release(swapchain);
309     return EVENT_ERROR;
310 }
311
312 static int revert_render_target(IDirect3DDevice8 *device, void *data)
313 {
314     struct event_data *edata = data;
315     HRESULT hr;
316
317     /* Reset the old render target */
318     hr = IDirect3DDevice8_SetRenderTarget(device, edata->original_render_target, NULL);
319     ok(SUCCEEDED(hr), "SetRenderTarget returned %#x.\n", hr);
320     if (FAILED(hr))
321     {
322         IDirect3DSurface8_Release(edata->original_render_target);
323         return EVENT_ERROR;
324     }
325
326     IDirect3DSurface8_Release(edata->original_render_target);
327     IDirect3DSwapChain8_Release(edata->new_swap_chain);
328     return EVENT_OK;
329 }
330
331 static int begin_stateblock(IDirect3DDevice8 *device, void *data)
332 {
333     HRESULT hr;
334
335     hr = IDirect3DDevice8_BeginStateBlock(device);
336     ok(SUCCEEDED(hr), "BeginStateBlock returned %#x.\n", hr);
337     if (FAILED(hr)) return EVENT_ERROR;
338     return EVENT_OK;
339 }
340
341 static int end_stateblock(IDirect3DDevice8 *device, void *data)
342 {
343     struct event_data *edata = data;
344     HRESULT hr;
345
346     hr = IDirect3DDevice8_EndStateBlock(device, &edata->stateblock);
347     ok(SUCCEEDED(hr), "EndStateBlock returned %#x.\n", hr);
348     if (FAILED(hr)) return EVENT_ERROR;
349     return EVENT_OK;
350 }
351
352 static int abort_stateblock(IDirect3DDevice8 *device, void *data)
353 {
354     struct event_data *edata = data;
355
356     IDirect3DDevice8_DeleteStateBlock(device, edata->stateblock);
357     return EVENT_OK;
358 }
359
360 static int apply_stateblock(IDirect3DDevice8 *device, void *data)
361 {
362     struct event_data *edata = data;
363     HRESULT hr;
364
365     hr = IDirect3DDevice8_ApplyStateBlock(device, edata->stateblock);
366     ok(SUCCEEDED(hr), "Apply returned %#x.\n", hr);
367
368     IDirect3DDevice8_DeleteStateBlock(device, edata->stateblock);
369     if (FAILED(hr)) return EVENT_ERROR;
370     return EVENT_OK;
371 }
372
373 static int capture_stateblock(IDirect3DDevice8 *device, void *data)
374 {
375     struct event_data *edata = data;
376     HRESULT hr;
377
378     hr = IDirect3DDevice8_CaptureStateBlock(device, edata->stateblock);
379     ok(SUCCEEDED(hr), "Capture returned %#x.\n", hr);
380     if (FAILED(hr)) return EVENT_ERROR;
381
382     return EVENT_OK;
383 }
384
385 static void execute_test_chain_all(IDirect3DDevice8 *device, struct state_test *test, unsigned int ntests)
386 {
387     struct event_data arg;
388     unsigned int i;
389     HRESULT hr;
390
391     struct event read_events[] =
392     {
393         {NULL, EVENT_CHECK_INITIAL},
394     };
395
396     struct event write_read_events[] =
397     {
398         {NULL, EVENT_APPLY_DATA},
399         {NULL, EVENT_CHECK_TEST},
400     };
401
402     struct event abort_stateblock_events[] =
403     {
404         {begin_stateblock, EVENT_APPLY_DATA},
405         {end_stateblock, EVENT_OK},
406         {abort_stateblock, EVENT_CHECK_DEFAULT},
407     };
408
409     struct event apply_stateblock_events[] =
410     {
411         {begin_stateblock, EVENT_APPLY_DATA},
412         {end_stateblock, EVENT_OK},
413         {apply_stateblock, EVENT_CHECK_TEST},
414     };
415
416     struct event capture_reapply_stateblock_events[] =
417     {
418         {begin_stateblock, EVENT_APPLY_DATA},
419         {end_stateblock, EVENT_OK},
420         {capture_stateblock, EVENT_CHECK_DEFAULT | EVENT_APPLY_DATA},
421         {apply_stateblock, EVENT_CHECK_DEFAULT},
422     };
423
424     struct event rendertarget_switch_events[] =
425     {
426         {NULL, EVENT_APPLY_DATA},
427         {switch_render_target, EVENT_CHECK_TEST},
428         {revert_render_target, EVENT_OK},
429     };
430
431     struct event rendertarget_stateblock_events[] =
432     {
433         {begin_stateblock, EVENT_APPLY_DATA},
434         {switch_render_target, EVENT_CHECK_DEFAULT},
435         {end_stateblock, EVENT_OK},
436         {revert_render_target, EVENT_OK},
437         {apply_stateblock, EVENT_CHECK_TEST},
438     };
439
440     /* Setup each test for execution */
441     for (i = 0; i < ntests; ++i)
442     {
443         hr = test[i].setup_handler(&test[i]);
444         ok(SUCCEEDED(hr), "Test \"%s\" failed setup, aborting\n", test[i].test_name);
445         if (FAILED(hr)) return;
446     }
447
448     trace("Running initial read state tests\n");
449     execute_test_chain(device, test, ntests, read_events, 1, NULL);
450
451     trace("Running write-read state tests\n");
452     execute_test_chain(device, test, ntests, write_read_events, 2, NULL);
453
454     trace("Running stateblock abort state tests\n");
455     execute_test_chain(device, test, ntests, abort_stateblock_events, 3, &arg);
456
457     trace("Running stateblock apply state tests\n");
458     execute_test_chain(device, test, ntests, apply_stateblock_events, 3, &arg);
459
460     trace("Running stateblock capture/reapply state tests\n");
461     execute_test_chain(device, test, ntests, capture_reapply_stateblock_events, 4, &arg);
462
463     trace("Running rendertarget switch state tests\n");
464     execute_test_chain(device, test, ntests, rendertarget_switch_events, 3, &arg);
465
466     trace("Running stateblock apply over rendertarget switch interrupt tests\n");
467     execute_test_chain(device, test, ntests, rendertarget_stateblock_events, 5, &arg);
468
469     /* Cleanup resources */
470     for (i = 0; i < ntests; ++i)
471     {
472         test[i].teardown_handler(&test[i]);
473     }
474 }
475
476 /* =================== State test: Pixel and Vertex Shader constants ============ */
477
478 struct shader_constant_data
479 {
480     float float_constant[4]; /* 1x4 float constant */
481 };
482
483 struct shader_constant_arg
484 {
485     unsigned int idx;
486     BOOL pshader;
487 };
488
489 struct shader_constant_context
490 {
491     struct shader_constant_data return_data_buffer;
492 };
493
494 static void shader_constant_print_handler(const struct state_test *test, const void *data)
495 {
496     const struct shader_constant_data *scdata = data;
497
498     trace("Float constant = { %f, %f, %f, %f }\n",
499             scdata->float_constant[0], scdata->float_constant[1],
500             scdata->float_constant[2], scdata->float_constant[3]);
501 }
502
503 static void shader_constant_set_handler(IDirect3DDevice8* device, const struct state_test *test, const void *data)
504 {
505     const struct shader_constant_data *scdata = data;
506     const struct shader_constant_arg *scarg = test->test_arg;
507     unsigned int index = scarg->idx;
508     HRESULT hr;
509
510     if (!scarg->pshader)
511     {
512         hr = IDirect3DDevice8_SetVertexShaderConstant(device, index, scdata->float_constant, 1);
513         ok(SUCCEEDED(hr), "SetVertexShaderConstant returned %#x.\n", hr);
514     }
515     else
516     {
517         hr = IDirect3DDevice8_SetPixelShaderConstant(device, index, scdata->float_constant, 1);
518         ok(SUCCEEDED(hr), "SetPixelShaderConstant returned %#x.\n", hr);
519     }
520 }
521
522 static void shader_constant_get_handler(IDirect3DDevice8* device, const struct state_test *test, void *data)
523 {
524     struct shader_constant_data *scdata = data;
525     const struct shader_constant_arg *scarg = test->test_arg;
526     unsigned int index = scarg->idx;
527     HRESULT hr;
528
529     if (!scarg->pshader)
530     {
531         hr = IDirect3DDevice8_GetVertexShaderConstant(device, index, scdata->float_constant, 1);
532         ok(SUCCEEDED(hr), "GetVertexShaderConstant returned %#x.\n", hr);
533
534     }
535     else
536     {
537         hr = IDirect3DDevice8_GetPixelShaderConstant(device, index, scdata->float_constant, 1);
538         ok(SUCCEEDED(hr), "GetPixelShaderConstant returned %#x.\n", hr);
539     }
540 }
541
542 static const struct shader_constant_data shader_constant_poison_data =
543 {
544     {1.0f, 2.0f, 3.0f, 4.0f},
545 };
546
547 static const struct shader_constant_data shader_constant_default_data =
548 {
549     {0.0f, 0.0f, 0.0f, 0.0f},
550 };
551
552 static const struct shader_constant_data shader_constant_test_data =
553 {
554     {5.0f, 6.0f, 7.0f, 8.0f},
555 };
556
557 static HRESULT shader_constant_setup_handler(struct state_test *test)
558 {
559     struct shader_constant_context *ctx = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ctx));
560     if (!ctx) return E_FAIL;
561     test->test_context = ctx;
562
563     test->return_data = &ctx->return_data_buffer;
564     test->test_data_in = &shader_constant_test_data;
565     test->test_data_out = &shader_constant_test_data;
566     test->default_data = &shader_constant_default_data;
567     test->initial_data = &shader_constant_default_data;
568     test->poison_data = &shader_constant_poison_data;
569
570     test->data_size = sizeof(struct shader_constant_data);
571
572     return D3D_OK;
573 }
574
575 static void shader_constant_teardown_handler(struct state_test *test)
576 {
577     HeapFree(GetProcessHeap(), 0, test->test_context);
578 }
579
580 static void shader_constants_queue_test(struct state_test *test, const struct shader_constant_arg *test_arg)
581 {
582     test->setup_handler = shader_constant_setup_handler;
583     test->teardown_handler = shader_constant_teardown_handler;
584     test->set_handler = shader_constant_set_handler;
585     test->get_handler = shader_constant_get_handler;
586     test->print_handler = shader_constant_print_handler;
587     test->test_name = test_arg->pshader ? "set_get_pshader_constants" : "set_get_vshader_constants";
588     test->test_arg = test_arg;
589 }
590
591 /* =================== State test: Lights ===================================== */
592
593 struct light_data
594 {
595     D3DLIGHT8 light;
596     BOOL enabled;
597     HRESULT get_light_result;
598     HRESULT get_enabled_result;
599 };
600
601 struct light_arg
602 {
603     unsigned int idx;
604 };
605
606 struct light_context
607 {
608     struct light_data return_data_buffer;
609 };
610
611 static void light_print_handler(const struct state_test *test, const void *data)
612 {
613     const struct light_data *ldata = data;
614
615     trace("Get Light return value: %#x\n", ldata->get_light_result);
616     trace("Get Light enable return value: %#x\n", ldata->get_enabled_result);
617
618     trace("Light Enabled = %u\n", ldata->enabled);
619     trace("Light Type = %u\n", ldata->light.Type);
620     trace("Light Diffuse = { %f, %f, %f, %f }\n",
621             ldata->light.Diffuse.r, ldata->light.Diffuse.g,
622             ldata->light.Diffuse.b, ldata->light.Diffuse.a);
623     trace("Light Specular = { %f, %f, %f, %f}\n",
624             ldata->light.Specular.r, ldata->light.Specular.g,
625             ldata->light.Specular.b, ldata->light.Specular.a);
626     trace("Light Ambient = { %f, %f, %f, %f }\n",
627             ldata->light.Ambient.r, ldata->light.Ambient.g,
628             ldata->light.Ambient.b, ldata->light.Ambient.a);
629     trace("Light Position = { %f, %f, %f }\n",
630             ldata->light.Position.x, ldata->light.Position.y, ldata->light.Position.z);
631     trace("Light Direction = { %f, %f, %f }\n",
632             ldata->light.Direction.x, ldata->light.Direction.y, ldata->light.Direction.z);
633     trace("Light Range = %f\n", ldata->light.Range);
634     trace("Light Fallof = %f\n", ldata->light.Falloff);
635     trace("Light Attenuation0 = %f\n", ldata->light.Attenuation0);
636     trace("Light Attenuation1 = %f\n", ldata->light.Attenuation1);
637     trace("Light Attenuation2 = %f\n", ldata->light.Attenuation2);
638     trace("Light Theta = %f\n", ldata->light.Theta);
639     trace("Light Phi = %f\n", ldata->light.Phi);
640 }
641
642 static void light_set_handler(IDirect3DDevice8 *device, const struct state_test *test, const void *data)
643 {
644     const struct light_data *ldata = data;
645     const struct light_arg *larg = test->test_arg;
646     unsigned int index = larg->idx;
647     HRESULT hr;
648
649     hr = IDirect3DDevice8_SetLight(device, index, &ldata->light);
650     ok(SUCCEEDED(hr), "SetLight returned %#x.\n", hr);
651
652     hr = IDirect3DDevice8_LightEnable(device, index, ldata->enabled);
653     ok(SUCCEEDED(hr), "SetLightEnable returned %#x.\n", hr);
654 }
655
656 static void light_get_handler(IDirect3DDevice8 *device, const struct state_test *test, void *data)
657 {
658     struct light_data *ldata = data;
659     const struct light_arg *larg = test->test_arg;
660     unsigned int index = larg->idx;
661     HRESULT hr;
662
663     hr = IDirect3DDevice8_GetLightEnable(device, index, &ldata->enabled);
664     ldata->get_enabled_result = hr;
665
666     hr = IDirect3DDevice8_GetLight(device, index, &ldata->light);
667     ldata->get_light_result = hr;
668 }
669
670 static const struct light_data light_poison_data =
671 {
672     {
673         0x1337c0de,
674         {7.0, 4.0, 2.0, 1.0},
675         {7.0, 4.0, 2.0, 1.0},
676         {7.0, 4.0, 2.0, 1.0},
677         {3.3f, 4.4f, 5.5f},
678         {6.6f, 7.7f, 8.8f},
679         12.12f, 13.13f, 14.14f, 15.15f, 16.16f, 17.17f, 18.18f,
680     },
681     TRUE,
682     0x1337c0de,
683     0x1337c0de,
684 };
685
686 static const struct light_data light_default_data =
687 {
688     {
689         D3DLIGHT_DIRECTIONAL,
690         {1.0, 1.0, 1.0, 0.0},
691         {0.0, 0.0, 0.0, 0.0},
692         {0.0, 0.0, 0.0, 0.0},
693         {0.0, 0.0, 0.0},
694         {0.0, 0.0, 1.0},
695         0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
696     },
697     FALSE,
698     D3D_OK,
699     D3D_OK,
700 };
701
702 /* This is used for the initial read state (before a write causes side effects)
703  * The proper return status is D3DERR_INVALIDCALL */
704 static const struct light_data light_initial_data =
705 {
706     {
707         0x1337c0de,
708         {7.0, 4.0, 2.0, 1.0},
709         {7.0, 4.0, 2.0, 1.0},
710         {7.0, 4.0, 2.0, 1.0},
711         {3.3f, 4.4f, 5.5f},
712         {6.6f, 7.7f, 8.8f},
713         12.12f, 13.13f, 14.14f, 15.15f, 16.16f, 17.17f, 18.18f,
714     },
715     TRUE,
716     D3DERR_INVALIDCALL,
717     D3DERR_INVALIDCALL,
718 };
719
720 static const struct light_data light_test_data_in =
721 {
722     {
723         1,
724         {2.0, 2.0, 2.0, 2.0},
725         {3.0, 3.0, 3.0, 3.0},
726         {4.0, 4.0, 4.0, 4.0},
727         {5.0, 5.0, 5.0},
728         {6.0, 6.0, 6.0},
729         7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0,
730     },
731     TRUE,
732     D3D_OK,
733     D3D_OK,
734 };
735
736 /* SetLight will use 128 as the "enabled" value */
737 static const struct light_data light_test_data_out =
738 {
739     {
740         1,
741         {2.0, 2.0, 2.0, 2.0},
742         {3.0, 3.0, 3.0, 3.0},
743         {4.0, 4.0, 4.0, 4.0},
744         {5.0, 5.0, 5.0},
745         {6.0, 6.0, 6.0},
746         7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0,
747     },
748     128,
749     D3D_OK,
750     D3D_OK,
751 };
752
753 static HRESULT light_setup_handler(struct state_test *test)
754 {
755     struct light_context *ctx = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ctx));
756     if (!ctx) return E_FAIL;
757     test->test_context = ctx;
758
759     test->return_data = &ctx->return_data_buffer;
760     test->test_data_in = &light_test_data_in;
761     test->test_data_out = &light_test_data_out;
762     test->default_data = &light_default_data;
763     test->initial_data = &light_initial_data;
764     test->poison_data = &light_poison_data;
765
766     test->data_size = sizeof(struct light_data);
767
768     return D3D_OK;
769 }
770
771 static void light_teardown_handler(struct state_test *test)
772 {
773     HeapFree(GetProcessHeap(), 0, test->test_context);
774 }
775
776 static void lights_queue_test(struct state_test *test, const struct light_arg *test_arg)
777 {
778     test->setup_handler = light_setup_handler;
779     test->teardown_handler = light_teardown_handler;
780     test->set_handler = light_set_handler;
781     test->get_handler = light_get_handler;
782     test->print_handler = light_print_handler;
783     test->test_name = "set_get_light";
784     test->test_arg = test_arg;
785 }
786
787 /* =================== State test: Transforms ===================================== */
788
789 struct transform_data
790 {
791     D3DMATRIX view;
792     D3DMATRIX projection;
793     D3DMATRIX texture0;
794     D3DMATRIX texture7;
795     D3DMATRIX world0;
796     D3DMATRIX world255;
797 };
798
799 struct transform_context
800 {
801     struct transform_data return_data_buffer;
802 };
803
804 static inline void print_matrix(const char *name, const D3DMATRIX *matrix)
805 {
806     trace("%s Matrix =\n{\n", name);
807     trace("    %f %f %f %f\n", U(*matrix).m[0][0], U(*matrix).m[1][0], U(*matrix).m[2][0], U(*matrix).m[3][0]);
808     trace("    %f %f %f %f\n", U(*matrix).m[0][1], U(*matrix).m[1][1], U(*matrix).m[2][1], U(*matrix).m[3][1]);
809     trace("    %f %f %f %f\n", U(*matrix).m[0][2], U(*matrix).m[1][2], U(*matrix).m[2][2], U(*matrix).m[3][2]);
810     trace("    %f %f %f %f\n", U(*matrix).m[0][3], U(*matrix).m[1][3], U(*matrix).m[2][3], U(*matrix).m[3][3]);
811     trace("}\n");
812 }
813
814 static void transform_print_handler(const struct state_test *test, const void *data)
815 {
816     const struct transform_data *tdata = data;
817
818     print_matrix("View", &tdata->view);
819     print_matrix("Projection", &tdata->projection);
820     print_matrix("Texture0", &tdata->texture0);
821     print_matrix("Texture7", &tdata->texture7);
822     print_matrix("World0", &tdata->world0);
823     print_matrix("World255", &tdata->world255);
824 }
825
826 static void transform_set_handler(IDirect3DDevice8 *device, const struct state_test *test, const void *data)
827 {
828     const struct transform_data *tdata = data;
829     HRESULT hr;
830
831     hr = IDirect3DDevice8_SetTransform(device, D3DTS_VIEW, &tdata->view);
832     ok(SUCCEEDED(hr), "SetTransform returned %#x.\n", hr);
833
834     hr = IDirect3DDevice8_SetTransform(device, D3DTS_PROJECTION, &tdata->projection);
835     ok(SUCCEEDED(hr), "SetTransform returned %#x.\n", hr);
836
837     hr = IDirect3DDevice8_SetTransform(device, D3DTS_TEXTURE0, &tdata->texture0);
838     ok(SUCCEEDED(hr), "SetTransform returned %#x.\n", hr);
839
840     hr = IDirect3DDevice8_SetTransform(device, D3DTS_TEXTURE0 + texture_stages - 1, &tdata->texture7);
841     ok(SUCCEEDED(hr), "SetTransform returned %#x.\n", hr);
842
843     hr = IDirect3DDevice8_SetTransform(device, D3DTS_WORLD, &tdata->world0);
844     ok(SUCCEEDED(hr), "SetTransform returned %#x.\n", hr);
845
846     hr = IDirect3DDevice8_SetTransform(device, D3DTS_WORLDMATRIX(255), &tdata->world255);
847     ok(SUCCEEDED(hr), "SetTransform returned %#x.\n", hr);
848 }
849
850 static void transform_get_handler(IDirect3DDevice8 *device, const struct state_test *test, void *data)
851 {
852     struct transform_data *tdata = data;
853     HRESULT hr;
854
855     hr = IDirect3DDevice8_GetTransform(device, D3DTS_VIEW, &tdata->view);
856     ok(SUCCEEDED(hr), "GetTransform returned %#x.\n", hr);
857
858     hr = IDirect3DDevice8_GetTransform(device, D3DTS_PROJECTION, &tdata->projection);
859     ok(SUCCEEDED(hr), "GetTransform returned %#x.\n", hr);
860
861     hr = IDirect3DDevice8_GetTransform(device, D3DTS_TEXTURE0, &tdata->texture0);
862     ok(SUCCEEDED(hr), "GetTransform returned %#x.\n", hr);
863
864     hr = IDirect3DDevice8_GetTransform(device, D3DTS_TEXTURE0 + texture_stages - 1, &tdata->texture7);
865     ok(SUCCEEDED(hr), "GetTransform returned %#x.\n", hr);
866
867     hr = IDirect3DDevice8_GetTransform(device, D3DTS_WORLD, &tdata->world0);
868     ok(SUCCEEDED(hr), "GetTransform returned %#x.\n", hr);
869
870     hr = IDirect3DDevice8_GetTransform(device, D3DTS_WORLDMATRIX(255), &tdata->world255);
871     ok(SUCCEEDED(hr), "GetTransform returned %#x.\n", hr);
872 }
873
874 static const struct transform_data transform_default_data =
875 {
876     {{{
877         1.0f, 0.0f, 0.0f, 0.0f,
878         0.0f, 1.0f, 0.0f, 0.0f,
879         0.0f, 0.0f, 1.0f, 0.0f,
880         0.0f, 0.0f, 0.0f, 1.0f,
881     }}},
882     {{{
883         1.0f, 0.0f, 0.0f, 0.0f,
884         0.0f, 1.0f, 0.0f, 0.0f,
885         0.0f, 0.0f, 1.0f, 0.0f,
886         0.0f, 0.0f, 0.0f, 1.0f,
887     }}},
888     {{{
889         1.0f, 0.0f, 0.0f, 0.0f,
890         0.0f, 1.0f, 0.0f, 0.0f,
891         0.0f, 0.0f, 1.0f, 0.0f,
892         0.0f, 0.0f, 0.0f, 1.0f,
893     }}},
894     {{{
895         1.0f, 0.0f, 0.0f, 0.0f,
896         0.0f, 1.0f, 0.0f, 0.0f,
897         0.0f, 0.0f, 1.0f, 0.0f,
898         0.0f, 0.0f, 0.0f, 1.0f,
899     }}},
900     {{{
901         1.0f, 0.0f, 0.0f, 0.0f,
902         0.0f, 1.0f, 0.0f, 0.0f,
903         0.0f, 0.0f, 1.0f, 0.0f,
904         0.0f, 0.0f, 0.0f, 1.0f,
905     }}},
906     {{{
907         1.0f, 0.0f, 0.0f, 0.0f,
908         0.0f, 1.0f, 0.0f, 0.0f,
909         0.0f, 0.0f, 1.0f, 0.0f,
910         0.0f, 0.0f, 0.0f, 1.0f,
911     }}},
912 };
913
914 static const struct transform_data transform_poison_data =
915 {
916     {{{
917          1.0f,  2.0f,  3.0f,  4.0f,
918          5.0f,  6.0f,  7.0f,  8.0f,
919          9.0f, 10.0f, 11.0f, 12.0f,
920         13.0f, 14.0f, 15.0f, 16.0f,
921     }}},
922     {{{
923         17.0f, 18.0f, 19.0f, 20.0f,
924         21.0f, 22.0f, 23.0f, 24.0f,
925         25.0f, 26.0f, 27.0f, 28.0f,
926         29.0f, 30.0f, 31.0f, 32.0f,
927     }}},
928     {{{
929         33.0f, 34.0f, 35.0f, 36.0f,
930         37.0f, 38.0f, 39.0f, 40.0f,
931         41.0f, 42.0f, 43.0f, 44.0f,
932         45.0f, 46.0f, 47.0f, 48.0f,
933     }}},
934     {{{
935         49.0f, 50.0f, 51.0f, 52.0f,
936         53.0f, 54.0f, 55.0f, 56.0f,
937         57.0f, 58.0f, 59.0f, 60.0f,
938         61.0f, 62.0f, 63.0f, 64.0f,
939     }}},
940     {{{
941         64.0f, 66.0f, 67.0f, 68.0f,
942         69.0f, 70.0f, 71.0f, 72.0f,
943         73.0f, 74.0f, 75.0f, 76.0f,
944         77.0f, 78.0f, 79.0f, 80.0f,
945     }}},
946     {{{
947         81.0f, 82.0f, 83.0f, 84.0f,
948         85.0f, 86.0f, 87.0f, 88.0f,
949         89.0f, 90.0f, 91.0f, 92.0f,
950         93.0f, 94.0f, 95.0f, 96.0f,
951     }}},
952 };
953
954 static const struct transform_data transform_test_data =
955 {
956     {{{
957           1.2f,     3.4f,  -5.6f,  7.2f,
958         10.11f,  -12.13f, 14.15f, -1.5f,
959         23.56f,   12.89f, 44.56f, -1.0f,
960           2.3f,     0.0f,   4.4f,  5.5f,
961     }}},
962     {{{
963           9.2f,    38.7f,  -6.6f,  7.2f,
964         10.11f,  -12.13f, 77.15f, -1.5f,
965         23.56f,   12.89f, 14.56f, -1.0f,
966          12.3f,     0.0f,   4.4f,  5.5f,
967     }}},
968     {{{
969          10.2f,     3.4f,   0.6f,  7.2f,
970         10.11f,  -12.13f, 14.15f, -1.5f,
971         23.54f,    12.9f, 44.56f, -1.0f,
972           2.3f,     0.0f,   4.4f,  5.5f,
973     }}},
974     {{{
975           1.2f,     3.4f,  -5.6f,  7.2f,
976         10.11f,  -12.13f, -14.5f, -1.5f,
977          2.56f,   12.89f, 23.56f, -1.0f,
978         112.3f,     0.0f,   4.4f,  2.5f,
979     }}},
980     {{{
981           1.2f,   31.41f,  58.6f,  7.2f,
982         10.11f,  -12.13f, -14.5f, -1.5f,
983          2.56f,   12.89f, 11.56f, -1.0f,
984         112.3f,     0.0f,  44.4f,  2.5f,
985     }}},
986
987     {{{
988          1.20f,     3.4f,  -5.6f,  7.0f,
989         10.11f, -12.156f, -14.5f, -1.5f,
990          2.56f,   1.829f,  23.6f, -1.0f,
991         112.3f,     0.0f,  41.4f,  2.5f,
992     }}},
993 };
994
995 static HRESULT transform_setup_handler(struct state_test *test)
996 {
997     struct transform_context *ctx = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ctx));
998     if (!ctx) return E_FAIL;
999     test->test_context = ctx;
1000
1001     test->return_data = &ctx->return_data_buffer;
1002     test->test_data_in = &transform_test_data;
1003     test->test_data_out = &transform_test_data;
1004     test->default_data = &transform_default_data;
1005     test->initial_data = &transform_default_data;
1006     test->poison_data = &transform_poison_data;
1007
1008     test->data_size = sizeof(struct transform_data);
1009
1010     return D3D_OK;
1011 }
1012
1013 static void transform_teardown_handler(struct state_test *test)
1014 {
1015     HeapFree(GetProcessHeap(), 0, test->test_context);
1016 }
1017
1018 static void transform_queue_test(struct state_test *test)
1019 {
1020     test->setup_handler = transform_setup_handler;
1021     test->teardown_handler = transform_teardown_handler;
1022     test->set_handler = transform_set_handler;
1023     test->get_handler = transform_get_handler;
1024     test->print_handler = transform_print_handler;
1025     test->test_name = "set_get_transforms";
1026     test->test_arg = NULL;
1027 }
1028
1029 /* =================== State test: Render States ===================================== */
1030
1031 const D3DRENDERSTATETYPE render_state_indices[] =
1032 {
1033     D3DRS_ZENABLE,
1034     D3DRS_FILLMODE,
1035     D3DRS_SHADEMODE,
1036     D3DRS_ZWRITEENABLE,
1037     D3DRS_ALPHATESTENABLE,
1038     D3DRS_LASTPIXEL,
1039     D3DRS_SRCBLEND,
1040     D3DRS_DESTBLEND,
1041     D3DRS_CULLMODE,
1042     D3DRS_ZFUNC,
1043     D3DRS_ALPHAREF,
1044     D3DRS_ALPHAFUNC,
1045     D3DRS_DITHERENABLE,
1046     D3DRS_ALPHABLENDENABLE,
1047     D3DRS_FOGENABLE,
1048     D3DRS_SPECULARENABLE,
1049     D3DRS_FOGCOLOR,
1050     D3DRS_FOGTABLEMODE,
1051     D3DRS_FOGSTART,
1052     D3DRS_FOGEND,
1053     D3DRS_FOGDENSITY,
1054     D3DRS_RANGEFOGENABLE,
1055     D3DRS_STENCILENABLE,
1056     D3DRS_STENCILFAIL,
1057     D3DRS_STENCILZFAIL,
1058     D3DRS_STENCILPASS,
1059     D3DRS_STENCILFUNC,
1060     D3DRS_STENCILREF,
1061     D3DRS_STENCILMASK,
1062     D3DRS_STENCILWRITEMASK,
1063     D3DRS_TEXTUREFACTOR,
1064     D3DRS_WRAP0,
1065     D3DRS_WRAP1,
1066     D3DRS_WRAP2,
1067     D3DRS_WRAP3,
1068     D3DRS_WRAP4,
1069     D3DRS_WRAP5,
1070     D3DRS_WRAP6,
1071     D3DRS_WRAP7,
1072     D3DRS_CLIPPING,
1073     D3DRS_LIGHTING,
1074     D3DRS_AMBIENT,
1075     D3DRS_FOGVERTEXMODE,
1076     D3DRS_COLORVERTEX,
1077     D3DRS_LOCALVIEWER,
1078     D3DRS_NORMALIZENORMALS,
1079     D3DRS_DIFFUSEMATERIALSOURCE,
1080     D3DRS_SPECULARMATERIALSOURCE,
1081     D3DRS_AMBIENTMATERIALSOURCE,
1082     D3DRS_EMISSIVEMATERIALSOURCE,
1083     D3DRS_VERTEXBLEND,
1084     D3DRS_CLIPPLANEENABLE,
1085 #if 0 /* Driver dependent, increase array size to enable */
1086     D3DRS_POINTSIZE,
1087 #endif
1088     D3DRS_POINTSIZE_MIN,
1089     D3DRS_POINTSPRITEENABLE,
1090     D3DRS_POINTSCALEENABLE,
1091     D3DRS_POINTSCALE_A,
1092     D3DRS_POINTSCALE_B,
1093     D3DRS_POINTSCALE_C,
1094     D3DRS_MULTISAMPLEANTIALIAS,
1095     D3DRS_MULTISAMPLEMASK,
1096     D3DRS_PATCHEDGESTYLE,
1097     D3DRS_DEBUGMONITORTOKEN,
1098     D3DRS_POINTSIZE_MAX,
1099     D3DRS_INDEXEDVERTEXBLENDENABLE,
1100     D3DRS_COLORWRITEENABLE,
1101     D3DRS_TWEENFACTOR,
1102     D3DRS_BLENDOP,
1103 };
1104
1105 struct render_state_data
1106 {
1107     DWORD states[sizeof(render_state_indices) / sizeof(*render_state_indices)];
1108 };
1109
1110 struct render_state_arg
1111 {
1112     D3DPRESENT_PARAMETERS *device_pparams;
1113     float pointsize_max;
1114 };
1115
1116 struct render_state_context
1117 {
1118    struct render_state_data return_data_buffer;
1119    struct render_state_data default_data_buffer;
1120    struct render_state_data test_data_buffer;
1121    struct render_state_data poison_data_buffer;
1122 };
1123
1124 static void render_state_set_handler(IDirect3DDevice8 *device, const struct state_test *test, const void *data)
1125 {
1126     const struct render_state_data *rsdata = data;
1127     unsigned int i;
1128     HRESULT hr;
1129
1130     for (i = 0; i < sizeof(render_state_indices) / sizeof(*render_state_indices); ++i)
1131     {
1132         hr = IDirect3DDevice8_SetRenderState(device, render_state_indices[i], rsdata->states[i]);
1133         ok(SUCCEEDED(hr), "SetRenderState returned %#x.\n", hr);
1134     }
1135 }
1136
1137 static void render_state_get_handler(IDirect3DDevice8 *device, const struct state_test *test, void *data)
1138 {
1139     struct render_state_data* rsdata = data;
1140     unsigned int i;
1141     HRESULT hr;
1142
1143     for (i = 0; i < sizeof(render_state_indices) / sizeof(*render_state_indices); ++i)
1144     {
1145         hr = IDirect3DDevice8_GetRenderState(device, render_state_indices[i], &rsdata->states[i]);
1146         ok(SUCCEEDED(hr), "GetRenderState returned %#x.\n", hr);
1147     }
1148 }
1149
1150 static void render_state_print_handler(const struct state_test *test, const void *data)
1151 {
1152     const struct render_state_data *rsdata = data;
1153     unsigned int i;
1154
1155     for (i = 0; i < sizeof(render_state_indices) / sizeof(*render_state_indices); ++i)
1156     {
1157         trace("Index = %u, Value = %#x\n", i, rsdata->states[i]);
1158     }
1159 }
1160
1161 static inline DWORD to_dword(float fl)
1162 {
1163     union {float f; DWORD d;} ret;
1164
1165     ret.f = fl;
1166     return ret.d;
1167 }
1168
1169 static void render_state_default_data_init(const struct render_state_arg *rsarg, struct render_state_data *data)
1170 {
1171     DWORD zenable = rsarg->device_pparams->EnableAutoDepthStencil ? D3DZB_TRUE : D3DZB_FALSE;
1172     unsigned int idx = 0;
1173
1174     data->states[idx++] = zenable;               /* ZENABLE */
1175     data->states[idx++] = D3DFILL_SOLID;         /* FILLMODE */
1176     data->states[idx++] = D3DSHADE_GOURAUD;      /* SHADEMODE */
1177     data->states[idx++] = TRUE;                  /* ZWRITEENABLE */
1178     data->states[idx++] = FALSE;                 /* ALPHATESTENABLE */
1179     data->states[idx++] = TRUE;                  /* LASTPIXEL */
1180     data->states[idx++] = D3DBLEND_ONE;          /* SRCBLEND */
1181     data->states[idx++] = D3DBLEND_ZERO;         /* DESTBLEND */
1182     data->states[idx++] = D3DCULL_CCW;           /* CULLMODE */
1183     data->states[idx++] = D3DCMP_LESSEQUAL;      /* ZFUNC */
1184     data->states[idx++] = 0;                     /* ALPHAREF */
1185     data->states[idx++] = D3DCMP_ALWAYS;         /* ALPHAFUNC */
1186     data->states[idx++] = FALSE;                 /* DITHERENABLE */
1187     data->states[idx++] = FALSE;                 /* ALPHABLENDENABLE */
1188     data->states[idx++] = FALSE;                 /* FOGENABLE */
1189     data->states[idx++] = FALSE;                 /* SPECULARENABLE */
1190     data->states[idx++] = 0;                     /* FOGCOLOR */
1191     data->states[idx++] = D3DFOG_NONE;           /* FOGTABLEMODE */
1192     data->states[idx++] = to_dword(0.0f);        /* FOGSTART */
1193     data->states[idx++] = to_dword(1.0f);        /* FOGEND */
1194     data->states[idx++] = to_dword(1.0f);        /* FOGDENSITY */
1195     data->states[idx++] = FALSE;                 /* RANGEFOGENABLE */
1196     data->states[idx++] = FALSE;                 /* STENCILENABLE */
1197     data->states[idx++] = D3DSTENCILOP_KEEP;     /* STENCILFAIL */
1198     data->states[idx++] = D3DSTENCILOP_KEEP;     /* STENCILZFAIL */
1199     data->states[idx++] = D3DSTENCILOP_KEEP;     /* STENCILPASS */
1200     data->states[idx++] = D3DCMP_ALWAYS;         /* STENCILFUNC */
1201     data->states[idx++] = 0;                     /* STENCILREF */
1202     data->states[idx++] = 0xFFFFFFFF;            /* STENCILMASK */
1203     data->states[idx++] = 0xFFFFFFFF;            /* STENCILWRITEMASK */
1204     data->states[idx++] = 0xFFFFFFFF;            /* TEXTUREFACTOR */
1205     data->states[idx++] = 0;                     /* WRAP 0 */
1206     data->states[idx++] = 0;                     /* WRAP 1 */
1207     data->states[idx++] = 0;                     /* WRAP 2 */
1208     data->states[idx++] = 0;                     /* WRAP 3 */
1209     data->states[idx++] = 0;                     /* WRAP 4 */
1210     data->states[idx++] = 0;                     /* WRAP 5 */
1211     data->states[idx++] = 0;                     /* WRAP 6 */
1212     data->states[idx++] = 0;                     /* WRAP 7 */
1213     data->states[idx++] = TRUE;                  /* CLIPPING */
1214     data->states[idx++] = TRUE;                  /* LIGHTING */
1215     data->states[idx++] = 0;                     /* AMBIENT */
1216     data->states[idx++] = D3DFOG_NONE;           /* FOGVERTEXMODE */
1217     data->states[idx++] = TRUE;                  /* COLORVERTEX */
1218     data->states[idx++] = TRUE;                  /* LOCALVIEWER */
1219     data->states[idx++] = FALSE;                 /* NORMALIZENORMALS */
1220     data->states[idx++] = D3DMCS_COLOR1;         /* DIFFUSEMATERIALSOURCE */
1221     data->states[idx++] = D3DMCS_COLOR2;         /* SPECULARMATERIALSOURCE */
1222     data->states[idx++] = D3DMCS_MATERIAL;       /* AMBIENTMATERIALSOURCE */
1223     data->states[idx++] = D3DMCS_MATERIAL;       /* EMISSIVEMATERIALSOURCE */
1224     data->states[idx++] = D3DVBF_DISABLE;        /* VERTEXBLEND */
1225     data->states[idx++] = 0;                     /* CLIPPLANEENABLE */
1226     if (0) data->states[idx++] = to_dword(1.0f); /* POINTSIZE, driver dependent, increase array size to enable */
1227     data->states[idx++] = to_dword(0.0f);        /* POINTSIZEMIN */
1228     data->states[idx++] = FALSE;                 /* POINTSPRITEENABLE */
1229     data->states[idx++] = FALSE;                 /* POINTSCALEENABLE */
1230     data->states[idx++] = to_dword(1.0f);        /* POINTSCALE_A */
1231     data->states[idx++] = to_dword(0.0f);        /* POINTSCALE_B */
1232     data->states[idx++] = to_dword(0.0f);        /* POINTSCALE_C */
1233     data->states[idx++] = TRUE;                  /* MULTISAMPLEANTIALIAS */
1234     data->states[idx++] = 0xFFFFFFFF;            /* MULTISAMPLEMASK */
1235     data->states[idx++] = D3DPATCHEDGE_DISCRETE; /* PATCHEDGESTYLE */
1236     data->states[idx++] = 0xbaadcafe;            /* DEBUGMONITORTOKEN */
1237     data->states[idx++] = to_dword(rsarg->pointsize_max); /* POINTSIZE_MAX */
1238     data->states[idx++] = FALSE;                 /* INDEXEDVERTEXBLENDENABLE */
1239     data->states[idx++] = 0x0000000F;            /* COLORWRITEENABLE */
1240     data->states[idx++] = to_dword(0.0f);        /* TWEENFACTOR */
1241     data->states[idx++] = D3DBLENDOP_ADD;        /* BLENDOP */
1242 }
1243
1244 static void render_state_poison_data_init(struct render_state_data *data)
1245 {
1246     unsigned int i;
1247
1248     for (i = 0; i < sizeof(render_state_indices) / sizeof(*render_state_indices); ++i)
1249     {
1250         data->states[i] = 0x1337c0de;
1251     }
1252 }
1253
1254 static void render_state_test_data_init(struct render_state_data *data)
1255 {
1256     unsigned int idx = 0;
1257
1258     data->states[idx++] = D3DZB_USEW;            /* ZENABLE */
1259     data->states[idx++] = D3DFILL_WIREFRAME;     /* FILLMODE */
1260     data->states[idx++] = D3DSHADE_PHONG;        /* SHADEMODE */
1261     data->states[idx++] = FALSE;                 /* ZWRITEENABLE */
1262     data->states[idx++] = TRUE;                  /* ALPHATESTENABLE */
1263     data->states[idx++] = FALSE;                 /* LASTPIXEL */
1264     data->states[idx++] = D3DBLEND_SRCALPHASAT;  /* SRCBLEND */
1265     data->states[idx++] = D3DBLEND_INVDESTALPHA; /* DESTBLEND */
1266     data->states[idx++] = D3DCULL_CW;            /* CULLMODE */
1267     data->states[idx++] = D3DCMP_NOTEQUAL;       /* ZFUNC */
1268     data->states[idx++] = 10;                    /* ALPHAREF */
1269     data->states[idx++] = D3DCMP_GREATER;        /* ALPHAFUNC */
1270     data->states[idx++] = TRUE;                  /* DITHERENABLE */
1271     data->states[idx++] = TRUE;                  /* ALPHABLENDENABLE */
1272     data->states[idx++] = TRUE;                  /* FOGENABLE */
1273     data->states[idx++] = TRUE;                  /* SPECULARENABLE */
1274     data->states[idx++] = 255 << 31;             /* FOGCOLOR */
1275     data->states[idx++] = D3DFOG_EXP;            /* FOGTABLEMODE */
1276     data->states[idx++] = to_dword(0.1f);        /* FOGSTART */
1277     data->states[idx++] = to_dword(0.8f);        /* FOGEND */
1278     data->states[idx++] = to_dword(0.5f);        /* FOGDENSITY */
1279     data->states[idx++] = TRUE;                  /* RANGEFOGENABLE */
1280     data->states[idx++] = TRUE;                  /* STENCILENABLE */
1281     data->states[idx++] = D3DSTENCILOP_INCRSAT;  /* STENCILFAIL */
1282     data->states[idx++] = D3DSTENCILOP_REPLACE;  /* STENCILZFAIL */
1283     data->states[idx++] = D3DSTENCILOP_INVERT;   /* STENCILPASS */
1284     data->states[idx++] = D3DCMP_LESS;           /* STENCILFUNC */
1285     data->states[idx++] = 10;                    /* STENCILREF */
1286     data->states[idx++] = 0xFF00FF00;            /* STENCILMASK */
1287     data->states[idx++] = 0x00FF00FF;            /* STENCILWRITEMASK */
1288     data->states[idx++] = 0xF0F0F0F0;            /* TEXTUREFACTOR */
1289     data->states[idx++] = D3DWRAPCOORD_0 | D3DWRAPCOORD_2;                                   /* WRAP 0 */
1290     data->states[idx++] = D3DWRAPCOORD_1 | D3DWRAPCOORD_3;                                   /* WRAP 1 */
1291     data->states[idx++] = D3DWRAPCOORD_2 | D3DWRAPCOORD_3;                                   /* WRAP 2 */
1292     data->states[idx++] = D3DWRAPCOORD_3 | D3DWRAPCOORD_0;                                   /* WRAP 4 */
1293     data->states[idx++] = D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2;                  /* WRAP 5 */
1294     data->states[idx++] = D3DWRAPCOORD_1 | D3DWRAPCOORD_3 | D3DWRAPCOORD_2;                  /* WRAP 6 */
1295     data->states[idx++] = D3DWRAPCOORD_2 | D3DWRAPCOORD_1 | D3DWRAPCOORD_0;                  /* WRAP 7 */
1296     data->states[idx++] = D3DWRAPCOORD_1 | D3DWRAPCOORD_0 | D3DWRAPCOORD_2 | D3DWRAPCOORD_3; /* WRAP 8 */
1297     data->states[idx++] = FALSE;                 /* CLIPPING */
1298     data->states[idx++] = FALSE;                 /* LIGHTING */
1299     data->states[idx++] = 255 << 16;             /* AMBIENT */
1300     data->states[idx++] = D3DFOG_EXP2;           /* FOGVERTEXMODE */
1301     data->states[idx++] = FALSE;                 /* COLORVERTEX */
1302     data->states[idx++] = FALSE;                 /* LOCALVIEWER */
1303     data->states[idx++] = TRUE;                  /* NORMALIZENORMALS */
1304     data->states[idx++] = D3DMCS_COLOR2;         /* DIFFUSEMATERIALSOURCE */
1305     data->states[idx++] = D3DMCS_MATERIAL;       /* SPECULARMATERIALSOURCE */
1306     data->states[idx++] = D3DMCS_COLOR1;         /* AMBIENTMATERIALSOURCE */
1307     data->states[idx++] = D3DMCS_COLOR2;         /* EMISSIVEMATERIALSOURCE */
1308     data->states[idx++] = D3DVBF_3WEIGHTS;       /* VERTEXBLEND */
1309     data->states[idx++] = 0xf1f1f1f1;            /* CLIPPLANEENABLE */
1310     if (0) data->states[idx++] = to_dword(32.0f);/* POINTSIZE, driver dependent, increase array size to enable */
1311     data->states[idx++] = to_dword(0.7f);        /* POINTSIZEMIN */
1312     data->states[idx++] = TRUE;                  /* POINTSPRITEENABLE */
1313     data->states[idx++] = TRUE;                  /* POINTSCALEENABLE */
1314     data->states[idx++] = to_dword(0.7f);        /* POINTSCALE_A */
1315     data->states[idx++] = to_dword(0.5f);        /* POINTSCALE_B */
1316     data->states[idx++] = to_dword(0.4f);        /* POINTSCALE_C */
1317     data->states[idx++] = FALSE;                 /* MULTISAMPLEANTIALIAS */
1318     data->states[idx++] = 0xABCDDBCA;            /* MULTISAMPLEMASK */
1319     data->states[idx++] = D3DPATCHEDGE_CONTINUOUS; /* PATCHEDGESTYLE */
1320     data->states[idx++] = D3DDMT_DISABLE;        /* DEBUGMONITORTOKEN */
1321     data->states[idx++] = to_dword(77.0f);       /* POINTSIZE_MAX */
1322     data->states[idx++] = TRUE;                  /* INDEXEDVERTEXBLENDENABLE */
1323     data->states[idx++] = 0x00000009;            /* COLORWRITEENABLE */
1324     data->states[idx++] = to_dword(0.2f);        /* TWEENFACTOR */
1325     data->states[idx++] = D3DBLENDOP_REVSUBTRACT;/* BLENDOP */
1326 }
1327
1328 static HRESULT render_state_setup_handler(struct state_test *test)
1329 {
1330     const struct render_state_arg *rsarg = test->test_arg;
1331
1332     struct render_state_context *ctx = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ctx));
1333     if (!ctx) return E_FAIL;
1334     test->test_context = ctx;
1335
1336     test->return_data = &ctx->return_data_buffer;
1337     test->default_data = &ctx->default_data_buffer;
1338     test->initial_data = &ctx->default_data_buffer;
1339     test->test_data_in = &ctx->test_data_buffer;
1340     test->test_data_out = &ctx->test_data_buffer;
1341     test->poison_data = &ctx->poison_data_buffer;
1342
1343     render_state_default_data_init(rsarg, &ctx->default_data_buffer);
1344     render_state_test_data_init(&ctx->test_data_buffer);
1345     render_state_poison_data_init(&ctx->poison_data_buffer);
1346
1347     test->data_size = sizeof(struct render_state_data);
1348
1349     return D3D_OK;
1350 }
1351
1352 static void render_state_teardown_handler(struct state_test *test)
1353 {
1354     HeapFree(GetProcessHeap(), 0, test->test_context);
1355 }
1356
1357 static void render_states_queue_test(struct state_test *test, const struct render_state_arg *test_arg)
1358 {
1359     test->setup_handler = render_state_setup_handler;
1360     test->teardown_handler = render_state_teardown_handler;
1361     test->set_handler = render_state_set_handler;
1362     test->get_handler = render_state_get_handler;
1363     test->print_handler = render_state_print_handler;
1364     test->test_name = "set_get_render_states";
1365     test->test_arg = test_arg;
1366 }
1367
1368 /* =================== Main state tests function =============================== */
1369
1370 static void test_state_management(IDirect3DDevice8 *device, D3DPRESENT_PARAMETERS *device_pparams)
1371 {
1372     D3DCAPS8 caps;
1373     HRESULT hr;
1374
1375     /* Test count: 2 for shader constants
1376      *             1 for lights
1377      *             1 for transforms
1378      *             1 for render states
1379      */
1380     const int max_tests = 5;
1381     struct state_test tests[5];
1382     unsigned int tcount = 0;
1383
1384     struct shader_constant_arg pshader_constant_arg;
1385     struct shader_constant_arg vshader_constant_arg;
1386     struct render_state_arg render_state_arg;
1387     struct light_arg light_arg;
1388
1389     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
1390     ok(SUCCEEDED(hr), "GetDeviceCaps returned %#x.\n", hr);
1391     if (FAILED(hr)) return;
1392
1393     texture_stages = caps.MaxTextureBlendStages;
1394
1395     /* Zero test memory */
1396     memset(tests, 0, max_tests * sizeof(*tests));
1397
1398     if (caps.VertexShaderVersion & 0xffff)
1399     {
1400         vshader_constant_arg.idx = 0;
1401         vshader_constant_arg.pshader = FALSE;
1402         shader_constants_queue_test(&tests[tcount++], &vshader_constant_arg);
1403     }
1404
1405     if (caps.PixelShaderVersion & 0xffff)
1406     {
1407         pshader_constant_arg.idx = 0;
1408         pshader_constant_arg.pshader = TRUE;
1409         shader_constants_queue_test(&tests[tcount++], &pshader_constant_arg);
1410     }
1411
1412     light_arg.idx = 0;
1413     lights_queue_test(&tests[tcount++], &light_arg);
1414
1415     transform_queue_test(&tests[tcount++]);
1416
1417     render_state_arg.device_pparams = device_pparams;
1418     render_state_arg.pointsize_max = caps.MaxPointSize;
1419     render_states_queue_test(&tests[tcount++], &render_state_arg);
1420
1421     execute_test_chain_all(device, tests, tcount);
1422 }
1423
1424 static void test_shader_constant_apply(IDirect3DDevice8 *device)
1425 {
1426     static const float initial[] = {0.0f, 0.0f, 0.0f, 0.0f};
1427     static const float vs_const[] = {1.0f, 2.0f, 3.0f, 4.0f};
1428     static const float ps_const[] = {5.0f, 6.0f, 7.0f, 8.0f};
1429     DWORD stateblock;
1430     float ret[4];
1431     HRESULT hr;
1432
1433     hr = IDirect3DDevice8_SetVertexShaderConstant(device, 0, initial, 1);
1434     ok(SUCCEEDED(hr), "SetVertexShaderConstant returned %#x\n", hr);
1435     hr = IDirect3DDevice8_SetVertexShaderConstant(device, 1, initial, 1);
1436     ok(SUCCEEDED(hr), "SetVertexShaderConstant returned %#x\n", hr);
1437     hr = IDirect3DDevice8_SetPixelShaderConstant(device, 0, initial, 1);
1438     ok(SUCCEEDED(hr), "SetPixelShaderConstant returned %#x\n", hr);
1439     hr = IDirect3DDevice8_SetPixelShaderConstant(device, 1, initial, 1);
1440     ok(SUCCEEDED(hr), "SetPixelShaderConstant returned %#x\n", hr);
1441
1442     hr = IDirect3DDevice8_GetVertexShaderConstant(device, 0, ret, 1);
1443     ok(SUCCEEDED(hr), "GetVertexShaderConstant returned %#x\n", hr);
1444     ok(!memcmp(ret, initial, sizeof(initial)),
1445             "GetVertexShaderConstant got {%f, %f, %f, %f}, expected {%f, %f, %f, %f}\n",
1446             ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
1447     hr = IDirect3DDevice8_GetVertexShaderConstant(device, 1, ret, 1);
1448     ok(SUCCEEDED(hr), "GetVertexShaderConstant returned %#x\n", hr);
1449     ok(!memcmp(ret, initial, sizeof(initial)),
1450             "GetVertexShaderConstant got {%f, %f, %f, %f}, expected {%f, %f, %f, %f}\n",
1451             ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
1452     hr = IDirect3DDevice8_GetPixelShaderConstant(device, 0, ret, 1);
1453     ok(SUCCEEDED(hr), "GetPixelShaderConstant returned %#x\n", hr);
1454     ok(!memcmp(ret, initial, sizeof(initial)),
1455             "GetpixelShaderConstant got {%f, %f, %f, %f}, expected {%f, %f, %f, %f}\n",
1456             ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
1457     hr = IDirect3DDevice8_GetPixelShaderConstant(device, 1, ret, 1);
1458     ok(SUCCEEDED(hr), "GetPixelShaderConstant returned %#x\n", hr);
1459     ok(!memcmp(ret, initial, sizeof(initial)),
1460             "GetPixelShaderConstant got {%f, %f, %f, %f}, expected {%f, %f, %f, %f}\n",
1461             ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
1462
1463     hr = IDirect3DDevice8_SetVertexShaderConstant(device, 0, vs_const, 1);
1464     ok(SUCCEEDED(hr), "SetVertexShaderConstant returned %#x\n", hr);
1465     hr = IDirect3DDevice8_SetPixelShaderConstant(device, 0, ps_const, 1);
1466     ok(SUCCEEDED(hr), "SetPixelShaderConstant returned %#x\n", hr);
1467
1468     hr = IDirect3DDevice8_BeginStateBlock(device);
1469     ok(SUCCEEDED(hr), "BeginStateBlock returned %#x\n", hr);
1470
1471     hr = IDirect3DDevice8_SetVertexShaderConstant(device, 1, vs_const, 1);
1472     ok(SUCCEEDED(hr), "SetVertexShaderConstant returned %#x\n", hr);
1473     hr = IDirect3DDevice8_SetPixelShaderConstant(device, 1, ps_const, 1);
1474     ok(SUCCEEDED(hr), "SetPixelShaderConstant returned %#x\n", hr);
1475
1476     hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
1477     ok(SUCCEEDED(hr), "EndStateBlock returned %#x\n", hr);
1478
1479     hr = IDirect3DDevice8_GetVertexShaderConstant(device, 0, ret, 1);
1480     ok(SUCCEEDED(hr), "GetVertexShaderConstant returned %#x\n", hr);
1481     ok(!memcmp(ret, vs_const, sizeof(vs_const)),
1482             "GetVertexShaderConstant got {%f, %f, %f, %f}, expected {%f, %f, %f, %f}\n",
1483             ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
1484     hr = IDirect3DDevice8_GetVertexShaderConstant(device, 1, ret, 1);
1485     ok(SUCCEEDED(hr), "GetVertexShaderConstant returned %#x\n", hr);
1486     ok(!memcmp(ret, initial, sizeof(initial)),
1487             "GetVertexShaderConstant got {%f, %f, %f, %f}, expected {%f, %f, %f, %f}\n",
1488             ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
1489     hr = IDirect3DDevice8_GetPixelShaderConstant(device, 0, ret, 1);
1490     ok(SUCCEEDED(hr), "GetPixelShaderConstant returned %#x\n", hr);
1491     ok(!memcmp(ret, ps_const, sizeof(ps_const)),
1492             "GetPixelShaderConstant got {%f, %f, %f, %f}, expected {%f, %f, %f, %f}\n",
1493             ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
1494     hr = IDirect3DDevice8_GetPixelShaderConstant(device, 1, ret, 1);
1495     ok(SUCCEEDED(hr), "GetPixelShaderConstant returned %#x\n", hr);
1496     ok(!memcmp(ret, initial, sizeof(initial)),
1497             "GetPixelShaderConstant got {%f, %f, %f, %f}, expected {%f, %f, %f, %f}\n",
1498             ret[0], ret[1], ret[2], ret[3], initial[0], initial[1], initial[2], initial[3]);
1499
1500     hr = IDirect3DDevice8_ApplyStateBlock(device, stateblock);
1501     ok(SUCCEEDED(hr), "Apply returned %#x\n", hr);
1502
1503     /* Apply doesn't overwrite constants that aren't explicitly set on the source stateblock. */
1504     hr = IDirect3DDevice8_GetVertexShaderConstant(device, 0, ret, 1);
1505     ok(SUCCEEDED(hr), "GetVertexShaderConstant returned %#x\n", hr);
1506     ok(!memcmp(ret, vs_const, sizeof(vs_const)),
1507             "GetVertexShaderConstant got {%f, %f, %f, %f}, expected {%f, %f, %f, %f}\n",
1508             ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
1509     hr = IDirect3DDevice8_GetVertexShaderConstant(device, 1, ret, 1);
1510     ok(SUCCEEDED(hr), "GetVertexShaderConstant returned %#x\n", hr);
1511     ok(!memcmp(ret, vs_const, sizeof(vs_const)),
1512             "GetVertexShaderConstant got {%f, %f, %f, %f}, expected {%f, %f, %f, %f}\n",
1513             ret[0], ret[1], ret[2], ret[3], vs_const[0], vs_const[1], vs_const[2], vs_const[3]);
1514     hr = IDirect3DDevice8_GetPixelShaderConstant(device, 0, ret, 1);
1515     ok(SUCCEEDED(hr), "GetPixelShaderConstant returned %#x\n", hr);
1516     ok(!memcmp(ret, ps_const, sizeof(ps_const)),
1517             "GetPixelShaderConstant got {%f, %f, %f, %f}, expected {%f, %f, %f, %f}\n",
1518             ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
1519     hr = IDirect3DDevice8_GetPixelShaderConstant(device, 1, ret, 1);
1520     ok(SUCCEEDED(hr), "GetPixelShaderConstant returned %#x\n", hr);
1521     ok(!memcmp(ret, ps_const, sizeof(ps_const)),
1522             "GetPixelShaderConstant got {%f, %f, %f, %f}, expected {%f, %f, %f, %f}\n",
1523             ret[0], ret[1], ret[2], ret[3], ps_const[0], ps_const[1], ps_const[2], ps_const[3]);
1524
1525     IDirect3DDevice8_DeleteStateBlock(device, stateblock);
1526 }
1527
1528 START_TEST(stateblock)
1529 {
1530     IDirect3DDevice8 *device = NULL;
1531     D3DPRESENT_PARAMETERS device_pparams;
1532     HMODULE d3d8_module;
1533     ULONG refcount;
1534     HRESULT hr;
1535
1536     d3d8_module = LoadLibraryA("d3d8.dll");
1537     if (!d3d8_module)
1538     {
1539         skip("Could not load d3d8.dll\n");
1540         return;
1541     }
1542
1543     hr = init_d3d8(d3d8_module, &device, &device_pparams);
1544     if (FAILED(hr))
1545     {
1546         FreeLibrary(d3d8_module);
1547         return;
1548     }
1549
1550     test_begin_end_state_block(device);
1551     test_state_management(device, &device_pparams);
1552     test_shader_constant_apply(device);
1553
1554     refcount = IDirect3DDevice8_Release(device);
1555     ok(!refcount, "Device has %u references left\n", refcount);
1556
1557     FreeLibrary(d3d8_module);
1558 }