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