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