2 * Copyright 2006 Ivan Gyurdiev
3 * Copyright 2005, 2008 Henri Verbeet
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/test.h"
24 static DWORD texture_stages;
26 static HWND create_window(void)
29 wc.lpfnWndProc = DefWindowProc;
30 wc.lpszClassName = "d3d8_test_wc";
33 return CreateWindow("d3d8_test_wc", "d3d8_test", 0, 0, 0, 0, 0, 0, 0, 0, 0);
36 static HRESULT init_d3d8(HMODULE d3d8_module, IDirect3DDevice8 **device, D3DPRESENT_PARAMETERS *device_pparams)
38 IDirect3D8 * (WINAPI *d3d8_create)(UINT SDKVersion) = 0;
44 d3d8_create = (void *)GetProcAddress(d3d8_module, "Direct3DCreate8");
45 if (!d3d8_create) return E_FAIL;
47 d3d8 = d3d8_create(D3D_SDK_VERSION);
50 skip("Failed to create D3D8 object.\n");
54 window = create_window();
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;
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);
70 static void test_begin_end_state_block(IDirect3DDevice8 *device)
76 hr = IDirect3DDevice8_BeginStateBlock(device);
77 ok(SUCCEEDED(hr), "BeginStateBlock failed, hr %#x.\n", hr);
78 if (FAILED(hr)) return;
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;
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);
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);
102 /* ============================ State Testing Framework ========================== */
106 const char *test_name;
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;
114 /* The default data is the standard state to compare
115 * against, and restore to */
116 const void *default_data;
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;
126 /* Test resource management handlers */
127 HRESULT (*setup_handler)(struct state_test *test);
128 void (*teardown_handler)(struct state_test *test);
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);
136 const void *test_arg;
138 /* Test-specific context data */
142 /* See below for explanation of the flags */
144 #define EVENT_ERROR -1
149 IDirect3DSurface8 *original_render_target;
150 IDirect3DSwapChain8 *new_swap_chain;
166 int (*event_fn)(IDirect3DDevice8 *device, struct event_data *event_data);
167 enum stateblock_data check;
168 enum stateblock_data apply;
171 static const void *get_event_data(const struct state_test *test, enum stateblock_data data)
175 case SB_DATA_DEFAULT:
176 return test->default_data;
178 case SB_DATA_INITIAL:
179 return test->initial_data;
181 case SB_DATA_TEST_IN:
182 return test->test_data_in;
184 case SB_DATA_TEST_ALL:
185 return test->test_data_out_all;
187 case SB_DATA_TEST_VERTEX:
188 return test->test_data_out_vertex;
190 case SB_DATA_TEST_PIXEL:
191 return test->test_data_out_pixel;
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)
206 /* For each queued event */
207 for (j = 0; j < nevents; ++j)
211 /* Execute the next event handler (if available). */
212 if (event[j].event_fn)
214 if (event[j].event_fn(device, event_data) == EVENT_ERROR)
216 trace("Stage %u in error state, aborting.\n", j);
221 if (event[j].check != SB_DATA_NONE)
223 for (i = 0; i < ntests; ++i)
225 data = get_event_data(&test[i], event[j].check);
226 test[i].check_data(device, j, &test[i], data);
230 if (event[j].apply != SB_DATA_NONE)
232 for (i = 0; i < ntests; ++i)
234 data = get_event_data(&test[i], event[j].apply);
235 test[i].set_handler(device, &test[i], data);
240 /* Attempt to reset any changes made */
241 for (i=0; i < ntests; i++)
243 test[i].set_handler(device, &test[i], test[i].default_data);
247 static int switch_render_target(IDirect3DDevice8* device, struct event_data *event_data)
249 D3DPRESENT_PARAMETERS present_parameters;
250 IDirect3DSwapChain8 *swapchain = NULL;
251 IDirect3DSurface8 *backbuffer = NULL;
252 D3DDISPLAYMODE d3ddm;
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;
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;
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;
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;
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;
282 IDirect3DSurface8_Release(backbuffer);
283 event_data->new_swap_chain = swapchain;
287 if (backbuffer) IDirect3DSurface8_Release(backbuffer);
288 if (swapchain) IDirect3DSwapChain8_Release(swapchain);
292 static int revert_render_target(IDirect3DDevice8 *device, struct event_data *event_data)
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);
301 IDirect3DSurface8_Release(event_data->original_render_target);
305 IDirect3DSurface8_Release(event_data->original_render_target);
306 IDirect3DSwapChain8_Release(event_data->new_swap_chain);
310 static int create_stateblock_all(IDirect3DDevice8 *device, struct event_data *event_data)
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;
320 static int create_stateblock_vertex(IDirect3DDevice8 *device, struct event_data *event_data)
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;
330 static int create_stateblock_pixel(IDirect3DDevice8 *device, struct event_data *event_data)
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;
340 static int begin_stateblock(IDirect3DDevice8 *device, struct event_data *event_data)
344 hr = IDirect3DDevice8_BeginStateBlock(device);
345 ok(SUCCEEDED(hr), "BeginStateBlock returned %#x.\n", hr);
346 if (FAILED(hr)) return EVENT_ERROR;
350 static int end_stateblock(IDirect3DDevice8 *device, struct event_data *event_data)
354 hr = IDirect3DDevice8_EndStateBlock(device, &event_data->stateblock);
355 ok(SUCCEEDED(hr), "EndStateBlock returned %#x.\n", hr);
356 if (FAILED(hr)) return EVENT_ERROR;
360 static int delete_stateblock(IDirect3DDevice8 *device, struct event_data *event_data)
362 IDirect3DDevice8_DeleteStateBlock(device, event_data->stateblock);
366 static int apply_stateblock(IDirect3DDevice8 *device, struct event_data *event_data)
370 hr = IDirect3DDevice8_ApplyStateBlock(device, event_data->stateblock);
371 ok(SUCCEEDED(hr), "Apply returned %#x.\n", hr);
373 IDirect3DDevice8_DeleteStateBlock(device, event_data->stateblock);
374 if (FAILED(hr)) return EVENT_ERROR;
378 static int capture_stateblock(IDirect3DDevice8 *device, struct event_data *event_data)
382 hr = IDirect3DDevice8_CaptureStateBlock(device, event_data->stateblock);
383 ok(SUCCEEDED(hr), "Capture returned %#x.\n", hr);
384 if (FAILED(hr)) return EVENT_ERROR;
389 static void execute_test_chain_all(IDirect3DDevice8 *device, struct state_test *test, unsigned int ntests)
391 struct event_data arg;
395 struct event read_events[] =
397 {NULL, SB_DATA_INITIAL, SB_DATA_NONE},
400 struct event write_read_events[] =
402 {NULL, SB_DATA_NONE, SB_DATA_TEST_IN},
403 {NULL, SB_DATA_TEST_ALL, SB_DATA_NONE},
406 struct event abort_stateblock_events[] =
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},
413 struct event apply_stateblock_events[] =
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},
420 struct event capture_reapply_stateblock_events[] =
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},
428 struct event create_stateblock_capture_apply_all_events[] =
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},
435 struct event create_stateblock_apply_all_events[] =
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},
442 struct event create_stateblock_capture_apply_vertex_events[] =
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},
449 struct event create_stateblock_apply_vertex_events[] =
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},
456 struct event create_stateblock_capture_apply_pixel_events[] =
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},
463 struct event create_stateblock_apply_pixel_events[] =
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},
470 struct event rendertarget_switch_events[] =
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},
477 struct event rendertarget_stateblock_events[] =
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},
486 /* Setup each test for execution */
487 for (i = 0; i < ntests; ++i)
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;
494 trace("Running initial read state tests\n");
495 execute_test_chain(device, test, ntests, read_events, 1, NULL);
497 trace("Running write-read state tests\n");
498 execute_test_chain(device, test, ntests, write_read_events, 2, NULL);
500 trace("Running stateblock abort state tests\n");
501 execute_test_chain(device, test, ntests, abort_stateblock_events, 3, &arg);
503 trace("Running stateblock apply state tests\n");
504 execute_test_chain(device, test, ntests, apply_stateblock_events, 3, &arg);
506 trace("Running stateblock capture/reapply state tests\n");
507 execute_test_chain(device, test, ntests, capture_reapply_stateblock_events, 4, &arg);
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);
512 trace("Running create stateblock apply all state tests\n");
513 execute_test_chain(device, test, ntests, create_stateblock_apply_all_events, 3, &arg);
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);
518 trace("Running create stateblock apply vertex state tests\n");
519 execute_test_chain(device, test, ntests, create_stateblock_apply_vertex_events, 3, &arg);
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);
524 trace("Running create stateblock apply pixel state tests\n");
525 execute_test_chain(device, test, ntests, create_stateblock_apply_pixel_events, 3, &arg);
527 trace("Running rendertarget switch state tests\n");
528 execute_test_chain(device, test, ntests, rendertarget_switch_events, 3, &arg);
530 trace("Running stateblock apply over rendertarget switch interrupt tests\n");
531 execute_test_chain(device, test, ntests, rendertarget_stateblock_events, 5, &arg);
533 /* Cleanup resources */
534 for (i = 0; i < ntests; ++i)
536 test[i].teardown_handler(&test[i]);
540 /* =================== State test: Pixel and Vertex Shader constants ============ */
542 struct shader_constant_data
544 float float_constant[4]; /* 1x4 float constant */
547 struct shader_constant_arg
553 static const struct shader_constant_data shader_constant_poison_data =
555 {1.0f, 2.0f, 3.0f, 4.0f},
558 static const struct shader_constant_data shader_constant_default_data =
560 {0.0f, 0.0f, 0.0f, 0.0f},
563 static const struct shader_constant_data shader_constant_test_data =
565 {5.0f, 6.0f, 7.0f, 8.0f},
568 static void shader_constant_set_handler(IDirect3DDevice8* device, const struct state_test *test, const void *data)
570 const struct shader_constant_data *scdata = data;
571 const struct shader_constant_arg *scarg = test->test_arg;
572 unsigned int index = scarg->idx;
577 hr = IDirect3DDevice8_SetVertexShaderConstant(device, index, scdata->float_constant, 1);
578 ok(SUCCEEDED(hr), "SetVertexShaderConstant returned %#x.\n", hr);
582 hr = IDirect3DDevice8_SetPixelShaderConstant(device, index, scdata->float_constant, 1);
583 ok(SUCCEEDED(hr), "SetPixelShaderConstant returned %#x.\n", hr);
587 static void shader_constant_check_data(IDirect3DDevice8 *device, unsigned int chain_stage,
588 const struct state_test *test, const void *expected_data)
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;
595 value = shader_constant_poison_data;
599 hr = IDirect3DDevice8_GetVertexShaderConstant(device, scarg->idx, value.float_constant, 1);
600 ok(SUCCEEDED(hr), "GetVertexShaderConstant returned %#x.\n", hr);
604 hr = IDirect3DDevice8_GetPixelShaderConstant(device, scarg->idx, value.float_constant, 1);
605 ok(SUCCEEDED(hr), "GetPixelShaderConstant returned %#x.\n", hr);
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]);
617 static HRESULT shader_constant_setup_handler(struct state_test *test)
619 const struct shader_constant_arg *test_arg = test->test_arg;
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)
626 test->test_data_out_vertex = &shader_constant_default_data;
627 test->test_data_out_pixel = &shader_constant_test_data;
631 test->test_data_out_vertex = &shader_constant_test_data;
632 test->test_data_out_pixel = &shader_constant_default_data;
634 test->default_data = &shader_constant_default_data;
635 test->initial_data = &shader_constant_default_data;
640 static void shader_constant_teardown_handler(struct state_test *test)
644 static void shader_constants_queue_test(struct state_test *test, const struct shader_constant_arg *test_arg)
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;
654 /* =================== State test: Lights ===================================== */
660 HRESULT get_light_result;
661 HRESULT get_enabled_result;
669 static const struct light_data light_poison_data =
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},
678 12.12f, 13.13f, 14.14f, 15.15f, 16.16f, 17.17f, 18.18f,
685 static const struct light_data light_default_data =
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},
694 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
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 =
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},
712 12.12f, 13.13f, 14.14f, 15.15f, 16.16f, 17.17f, 18.18f,
719 static const struct light_data light_test_data_in =
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},
728 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0,
735 /* SetLight will use 128 as the "enabled" value */
736 static const struct light_data light_test_data_out =
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},
745 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0,
752 static void light_set_handler(IDirect3DDevice8 *device, const struct state_test *test, const void *data)
754 const struct light_data *ldata = data;
755 const struct light_arg *larg = test->test_arg;
756 unsigned int index = larg->idx;
759 hr = IDirect3DDevice8_SetLight(device, index, &ldata->light);
760 ok(SUCCEEDED(hr), "SetLight returned %#x.\n", hr);
762 hr = IDirect3DDevice8_LightEnable(device, index, ldata->enabled);
763 ok(SUCCEEDED(hr), "SetLightEnable returned %#x.\n", hr);
766 static void light_check_data(IDirect3DDevice8 *device, unsigned int chain_stage,
767 const struct state_test *test, const void *expected_data)
769 const struct light_arg *larg = test->test_arg;
770 const struct light_data *ldata = expected_data;
771 struct light_data value;
773 value = light_poison_data;
775 value.get_enabled_result = IDirect3DDevice8_GetLightEnable(device, larg->idx, &value.enabled);
776 value.get_light_result = IDirect3DDevice8_GetLight(device, larg->idx, &value.light);
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);
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);
843 static HRESULT light_setup_handler(struct state_test *test)
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;
856 static void light_teardown_handler(struct state_test *test)
860 static void lights_queue_test(struct state_test *test, const struct light_arg *test_arg)
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;
870 /* =================== State test: Transforms ===================================== */
872 struct transform_data
875 D3DMATRIX projection;
882 static const struct transform_data transform_default_data =
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,
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,
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,
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,
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,
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,
922 static const struct transform_data transform_poison_data =
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,
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,
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,
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,
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,
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,
962 static const struct transform_data transform_test_data =
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,
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,
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,
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,
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,
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,
1004 static void transform_set_handler(IDirect3DDevice8 *device, const struct state_test *test, const void *data)
1006 const struct transform_data *tdata = data;
1009 hr = IDirect3DDevice8_SetTransform(device, D3DTS_VIEW, &tdata->view);
1010 ok(SUCCEEDED(hr), "SetTransform returned %#x.\n", hr);
1012 hr = IDirect3DDevice8_SetTransform(device, D3DTS_PROJECTION, &tdata->projection);
1013 ok(SUCCEEDED(hr), "SetTransform returned %#x.\n", hr);
1015 hr = IDirect3DDevice8_SetTransform(device, D3DTS_TEXTURE0, &tdata->texture0);
1016 ok(SUCCEEDED(hr), "SetTransform returned %#x.\n", hr);
1018 hr = IDirect3DDevice8_SetTransform(device, D3DTS_TEXTURE0 + texture_stages - 1, &tdata->texture7);
1019 ok(SUCCEEDED(hr), "SetTransform returned %#x.\n", hr);
1021 hr = IDirect3DDevice8_SetTransform(device, D3DTS_WORLD, &tdata->world0);
1022 ok(SUCCEEDED(hr), "SetTransform returned %#x.\n", hr);
1024 hr = IDirect3DDevice8_SetTransform(device, D3DTS_WORLDMATRIX(255), &tdata->world255);
1025 ok(SUCCEEDED(hr), "SetTransform returned %#x.\n", hr);
1028 static void compare_matrix(const char *name, unsigned int chain_stage,
1029 const D3DMATRIX *received, const D3DMATRIX *expected)
1031 ok(!memcmp(expected, received, sizeof(*expected)),
1032 "Chain stage %u, matrix %s:\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"
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"
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]);
1056 static void transform_check_data(IDirect3DDevice8 *device, unsigned int chain_stage,
1057 const struct state_test *test, const void *expected_data)
1059 const struct transform_data *tdata = expected_data;
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);
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);
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);
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);
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);
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);
1094 static HRESULT transform_setup_handler(struct state_test *test)
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;
1107 static void transform_teardown_handler(struct state_test *test)
1111 static void transform_queue_test(struct state_test *test)
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;
1121 /* =================== State test: Render States ===================================== */
1123 const D3DRENDERSTATETYPE render_state_indices[] =
1129 D3DRS_ALPHATESTENABLE,
1138 D3DRS_ALPHABLENDENABLE,
1140 D3DRS_SPECULARENABLE,
1146 D3DRS_RANGEFOGENABLE,
1147 D3DRS_STENCILENABLE,
1154 D3DRS_STENCILWRITEMASK,
1155 D3DRS_TEXTUREFACTOR,
1167 D3DRS_FOGVERTEXMODE,
1170 D3DRS_NORMALIZENORMALS,
1171 D3DRS_DIFFUSEMATERIALSOURCE,
1172 D3DRS_SPECULARMATERIALSOURCE,
1173 D3DRS_AMBIENTMATERIALSOURCE,
1174 D3DRS_EMISSIVEMATERIALSOURCE,
1176 D3DRS_CLIPPLANEENABLE,
1177 #if 0 /* Driver dependent */
1180 D3DRS_POINTSIZE_MIN,
1181 D3DRS_POINTSPRITEENABLE,
1182 D3DRS_POINTSCALEENABLE,
1186 D3DRS_MULTISAMPLEANTIALIAS,
1187 D3DRS_MULTISAMPLEMASK,
1188 D3DRS_PATCHEDGESTYLE,
1189 #if 0 /* Apparently not recorded in the stateblock */
1190 D3DRS_DEBUGMONITORTOKEN,
1192 D3DRS_POINTSIZE_MAX,
1193 D3DRS_INDEXEDVERTEXBLENDENABLE,
1194 D3DRS_COLORWRITEENABLE,
1199 struct render_state_data
1201 DWORD states[sizeof(render_state_indices) / sizeof(*render_state_indices)];
1204 struct render_state_arg
1206 D3DPRESENT_PARAMETERS *device_pparams;
1207 float pointsize_max;
1210 struct render_state_context
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;
1219 static void render_state_set_handler(IDirect3DDevice8 *device, const struct state_test *test, const void *data)
1221 const struct render_state_data *rsdata = data;
1225 for (i = 0; i < sizeof(render_state_indices) / sizeof(*render_state_indices); ++i)
1227 hr = IDirect3DDevice8_SetRenderState(device, render_state_indices[i], rsdata->states[i]);
1228 ok(SUCCEEDED(hr), "SetRenderState returned %#x.\n", hr);
1232 static void render_state_check_data(IDirect3DDevice8 *device, unsigned int chain_stage,
1233 const struct state_test *test, const void *expected_data)
1235 const struct render_state_context *ctx = test->test_context;
1236 const struct render_state_data *rsdata = expected_data;
1240 for (i = 0; i < sizeof(render_state_indices) / sizeof(*render_state_indices); ++i)
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);
1250 static inline DWORD to_dword(float fl)
1252 union {float f; DWORD d;} ret;
1258 static void render_state_default_data_init(const struct render_state_arg *rsarg, struct render_state_data *data)
1260 DWORD zenable = rsarg->device_pparams->EnableAutoDepthStencil ? D3DZB_TRUE : D3DZB_FALSE;
1261 unsigned int idx = 0;
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 */
1333 static void render_state_poison_data_init(struct render_state_data *data)
1337 for (i = 0; i < sizeof(render_state_indices) / sizeof(*render_state_indices); ++i)
1339 data->states[i] = 0x1337c0de;
1343 static void render_state_test_data_init(struct render_state_data *data)
1345 unsigned int idx = 0;
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 */
1417 static HRESULT render_state_setup_handler(struct state_test *test)
1419 static const DWORD states_vertex[] =
1422 D3DRS_AMBIENTMATERIALSOURCE,
1424 D3DRS_CLIPPLANEENABLE,
1427 D3DRS_DIFFUSEMATERIALSOURCE,
1428 D3DRS_EMISSIVEMATERIALSOURCE,
1435 D3DRS_FOGVERTEXMODE,
1436 D3DRS_INDEXEDVERTEXBLENDENABLE,
1439 D3DRS_MULTISAMPLEANTIALIAS,
1440 D3DRS_MULTISAMPLEMASK,
1441 D3DRS_NORMALIZENORMALS,
1442 D3DRS_PATCHEDGESTYLE,
1446 D3DRS_POINTSCALEENABLE,
1448 D3DRS_POINTSIZE_MAX,
1449 D3DRS_POINTSIZE_MIN,
1450 D3DRS_POINTSPRITEENABLE,
1451 D3DRS_RANGEFOGENABLE,
1453 D3DRS_SPECULARENABLE,
1454 D3DRS_SPECULARMATERIALSOURCE,
1459 static const DWORD states_pixel[] =
1461 D3DRS_ALPHABLENDENABLE,
1464 D3DRS_ALPHATESTENABLE,
1466 D3DRS_COLORWRITEENABLE,
1476 D3DRS_STENCILENABLE,
1482 D3DRS_STENCILWRITEMASK,
1484 D3DRS_TEXTUREFACTOR,
1498 const struct render_state_arg *rsarg = test->test_arg;
1501 struct render_state_context *ctx = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ctx));
1502 if (!ctx) return E_FAIL;
1503 test->test_context = ctx;
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;
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);
1516 for (i = 0; i < sizeof(render_state_indices) / sizeof(*render_state_indices); ++i)
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)
1521 if (render_state_indices[i] == states_vertex[j])
1523 ctx->test_data_vertex_buffer.states[i] = ctx->test_data_all_buffer.states[i];
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)
1531 if (render_state_indices[i] == states_pixel[j])
1533 ctx->test_data_pixel_buffer.states[i] = ctx->test_data_all_buffer.states[i];
1542 static void render_state_teardown_handler(struct state_test *test)
1544 HeapFree(GetProcessHeap(), 0, test->test_context);
1547 static void render_states_queue_test(struct state_test *test, const struct render_state_arg *test_arg)
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;
1557 /* =================== Main state tests function =============================== */
1559 static void test_state_management(IDirect3DDevice8 *device, D3DPRESENT_PARAMETERS *device_pparams)
1564 /* Test count: 2 for shader constants
1567 * 1 for render states
1569 const int max_tests = 5;
1570 struct state_test tests[5];
1571 unsigned int tcount = 0;
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;
1578 hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
1579 ok(SUCCEEDED(hr), "GetDeviceCaps returned %#x.\n", hr);
1580 if (FAILED(hr)) return;
1582 texture_stages = caps.MaxTextureBlendStages;
1584 /* Zero test memory */
1585 memset(tests, 0, max_tests * sizeof(*tests));
1587 if (caps.VertexShaderVersion & 0xffff)
1589 vshader_constant_arg.idx = 0;
1590 vshader_constant_arg.pshader = FALSE;
1591 shader_constants_queue_test(&tests[tcount++], &vshader_constant_arg);
1594 if (caps.PixelShaderVersion & 0xffff)
1596 pshader_constant_arg.idx = 0;
1597 pshader_constant_arg.pshader = TRUE;
1598 shader_constants_queue_test(&tests[tcount++], &pshader_constant_arg);
1602 lights_queue_test(&tests[tcount++], &light_arg);
1604 transform_queue_test(&tests[tcount++]);
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);
1610 execute_test_chain_all(device, tests, tcount);
1613 static void test_shader_constant_apply(IDirect3DDevice8 *device)
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};
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);
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]);
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);
1657 hr = IDirect3DDevice8_BeginStateBlock(device);
1658 ok(SUCCEEDED(hr), "BeginStateBlock returned %#x\n", hr);
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);
1665 hr = IDirect3DDevice8_EndStateBlock(device, &stateblock);
1666 ok(SUCCEEDED(hr), "EndStateBlock returned %#x\n", hr);
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]);
1689 hr = IDirect3DDevice8_ApplyStateBlock(device, stateblock);
1690 ok(SUCCEEDED(hr), "Apply returned %#x\n", hr);
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]);
1714 IDirect3DDevice8_DeleteStateBlock(device, stateblock);
1717 START_TEST(stateblock)
1719 IDirect3DDevice8 *device = NULL;
1720 D3DPRESENT_PARAMETERS device_pparams;
1721 HMODULE d3d8_module;
1725 d3d8_module = LoadLibraryA("d3d8.dll");
1728 skip("Could not load d3d8.dll\n");
1732 hr = init_d3d8(d3d8_module, &device, &device_pparams);
1735 FreeLibrary(d3d8_module);
1739 test_begin_end_state_block(device);
1740 test_state_management(device, &device_pparams);
1741 test_shader_constant_apply(device);
1743 refcount = IDirect3DDevice8_Release(device);
1744 ok(!refcount, "Device has %u references left\n", refcount);
1746 FreeLibrary(d3d8_module);