d3d9/tests: Fix the depth stencil size tests on AMD.
[wine] / dlls / d3d9 / tests / visual.c
1 /*
2  * Copyright 2005, 2007-2008 Henri Verbeet
3  * Copyright (C) 2007-2008 Stefan Dösinger(for CodeWeavers)
4  * Copyright (C) 2008 Jason Green(for TransGaming)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 /* This test framework allows limited testing of rendering results. Things are rendered, shown on
22  * the framebuffer, read back from there and compared to expected colors.
23  *
24  * However, neither d3d nor opengl is guaranteed to be pixel exact, and thus the capability of this test
25  * is rather limited. As a general guideline for adding tests, do not rely on corner pixels. Draw a big enough
26  * area which shows specific behavior(like a quad on the whole screen), and try to get resulting colors with
27  * all bits set or unset in all channels(like pure red, green, blue, white, black). Hopefully everything that
28  * causes visible results in games can be tested in a way that does not depend on pixel exactness
29  */
30
31 #define COBJMACROS
32 #include <d3d9.h>
33 #include "wine/test.h"
34
35 static HMODULE d3d9_handle = 0;
36
37 static HWND create_window(void)
38 {
39     WNDCLASS wc = {0};
40     HWND ret;
41     wc.lpfnWndProc = DefWindowProc;
42     wc.lpszClassName = "d3d9_test_wc";
43     RegisterClass(&wc);
44
45     ret = CreateWindow("d3d9_test_wc", "d3d9_test",
46                         WS_SYSMENU | WS_POPUP , 0, 0, 640, 480, 0, 0, 0, 0);
47     ShowWindow(ret, SW_SHOW);
48     return ret;
49 }
50
51 static BOOL color_match(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
52 {
53     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
54     c1 >>= 8; c2 >>= 8;
55     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
56     c1 >>= 8; c2 >>= 8;
57     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
58     c1 >>= 8; c2 >>= 8;
59     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
60     return TRUE;
61 }
62
63 /* Locks a given surface and returns the color at (x,y).  It's the caller's
64  * responsibility to only pass in lockable surfaces and valid x,y coordinates */
65 static DWORD getPixelColorFromSurface(IDirect3DSurface9 *surface, UINT x, UINT y)
66 {
67     DWORD color;
68     HRESULT hr;
69     D3DSURFACE_DESC desc;
70     RECT rectToLock = {x, y, x+1, y+1};
71     D3DLOCKED_RECT lockedRect;
72
73     hr = IDirect3DSurface9_GetDesc(surface, &desc);
74     if(FAILED(hr))  /* This is not a test */
75     {
76         trace("Can't get the surface description, hr=%08x\n", hr);
77         return 0xdeadbeef;
78     }
79
80     hr = IDirect3DSurface9_LockRect(surface, &lockedRect, &rectToLock, D3DLOCK_READONLY);
81     if(FAILED(hr))  /* This is not a test */
82     {
83         trace("Can't lock the surface, hr=%08x\n", hr);
84         return 0xdeadbeef;
85     }
86     switch(desc.Format) {
87         case D3DFMT_A8R8G8B8:
88         {
89             color = ((DWORD *) lockedRect.pBits)[0] & 0xffffffff;
90             break;
91         }
92         default:
93             trace("Error: unknown surface format: %d\n", desc.Format);
94             color = 0xdeadbeef;
95             break;
96     }
97     hr = IDirect3DSurface9_UnlockRect(surface);
98     if(FAILED(hr))
99     {
100         trace("Can't unlock the surface, hr=%08x\n", hr);
101     }
102     return color;
103 }
104
105 static DWORD getPixelColor(IDirect3DDevice9 *device, UINT x, UINT y)
106 {
107     DWORD ret;
108     IDirect3DSurface9 *surf = NULL, *target = NULL;
109     HRESULT hr;
110     D3DLOCKED_RECT lockedRect;
111     RECT rectToLock = {x, y, x+1, y+1};
112
113     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 640, 480,
114             D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL);
115     if (FAILED(hr) || !surf)
116     {
117         trace("Can't create an offscreen plain surface to read the render target data, hr=%08x\n", hr);
118         return 0xdeadbeef;
119     }
120
121     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &target);
122     if(FAILED(hr))
123     {
124         trace("Can't get the render target, hr=%08x\n", hr);
125         ret = 0xdeadbeed;
126         goto out;
127     }
128
129     hr = IDirect3DDevice9_GetRenderTargetData(device, target, surf);
130     if (FAILED(hr))
131     {
132         trace("Can't read the render target data, hr=%08x\n", hr);
133         ret = 0xdeadbeec;
134         goto out;
135     }
136
137     hr = IDirect3DSurface9_LockRect(surf, &lockedRect, &rectToLock, D3DLOCK_READONLY);
138     if(FAILED(hr))
139     {
140         trace("Can't lock the offscreen surface, hr=%08x\n", hr);
141         ret = 0xdeadbeeb;
142         goto out;
143     }
144
145     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
146      * really important for these tests
147      */
148     ret = ((DWORD *) lockedRect.pBits)[0] & 0x00ffffff;
149     hr = IDirect3DSurface9_UnlockRect(surf);
150     if(FAILED(hr))
151     {
152         trace("Can't unlock the offscreen surface, hr=%08x\n", hr);
153     }
154
155 out:
156     if(target) IDirect3DSurface9_Release(target);
157     if(surf) IDirect3DSurface9_Release(surf);
158     return ret;
159 }
160
161 static IDirect3DDevice9 *init_d3d9(void)
162 {
163     IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion) = 0;
164     IDirect3D9 *d3d9_ptr = 0;
165     IDirect3DDevice9 *device_ptr = 0;
166     D3DPRESENT_PARAMETERS present_parameters;
167     HRESULT hr;
168     D3DADAPTER_IDENTIFIER9 identifier;
169
170     d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
171     ok(d3d9_create != NULL, "Failed to get address of Direct3DCreate9\n");
172     if (!d3d9_create) return NULL;
173
174     d3d9_ptr = d3d9_create(D3D_SDK_VERSION);
175     if (!d3d9_ptr)
176     {
177         skip("could not create D3D9\n");
178         return NULL;
179     }
180
181     ZeroMemory(&present_parameters, sizeof(present_parameters));
182     present_parameters.Windowed = TRUE;
183     present_parameters.hDeviceWindow = create_window();
184     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
185     present_parameters.BackBufferWidth = 640;
186     present_parameters.BackBufferHeight = 480;
187     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
188     present_parameters.EnableAutoDepthStencil = TRUE;
189     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
190
191     memset(&identifier, 0, sizeof(identifier));
192     hr = IDirect3D9_GetAdapterIdentifier(d3d9_ptr, 0, 0, &identifier);
193     ok(hr == D3D_OK, "Failed to get adapter identifier description\n");
194     trace("Driver string: \"%s\"\n", identifier.Driver);
195     trace("Description string: \"%s\"\n", identifier.Description);
196     ok(identifier.Description[0] != '\0', "Empty driver description\n");
197     trace("Device name string: \"%s\"\n", identifier.DeviceName);
198     ok(identifier.DeviceName[0]  != '\0', "Empty device name\n");
199     trace("Driver version %d.%d.%d.%d\n",
200           HIWORD(U(identifier.DriverVersion).HighPart), LOWORD(U(identifier.DriverVersion).HighPart),
201           HIWORD(U(identifier.DriverVersion).LowPart), LOWORD(U(identifier.DriverVersion).LowPart));
202
203     hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
204             present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
205     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
206             "Failed to create a device, hr %#x.\n", hr);
207
208     return device_ptr;
209 }
210
211 struct vertex
212 {
213     float x, y, z;
214     DWORD diffuse;
215 };
216
217 struct tvertex
218 {
219     float x, y, z, rhw;
220     DWORD diffuse;
221 };
222
223 struct nvertex
224 {
225     float x, y, z;
226     float nx, ny, nz;
227     DWORD diffuse;
228 };
229
230 static void lighting_test(IDirect3DDevice9 *device)
231 {
232     HRESULT hr;
233     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
234     DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
235     DWORD color;
236     D3DMATERIAL9 material, old_material;
237     DWORD cop, carg;
238     DWORD old_colorwrite;
239
240     float mat[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
241                       0.0f, 1.0f, 0.0f, 0.0f,
242                       0.0f, 0.0f, 1.0f, 0.0f,
243                       0.0f, 0.0f, 0.0f, 1.0f };
244
245     struct vertex unlitquad[] =
246     {
247         {-1.0f, -1.0f,   0.1f,                          0xffff0000},
248         {-1.0f,  0.0f,   0.1f,                          0xffff0000},
249         { 0.0f,  0.0f,   0.1f,                          0xffff0000},
250         { 0.0f, -1.0f,   0.1f,                          0xffff0000},
251     };
252     struct vertex litquad[] =
253     {
254         {-1.0f,  0.0f,   0.1f,                          0xff00ff00},
255         {-1.0f,  1.0f,   0.1f,                          0xff00ff00},
256         { 0.0f,  1.0f,   0.1f,                          0xff00ff00},
257         { 0.0f,  0.0f,   0.1f,                          0xff00ff00},
258     };
259     struct nvertex unlitnquad[] =
260     {
261         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
262         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
263         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
264         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
265     };
266     struct nvertex litnquad[] =
267     {
268         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
269         { 0.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
270         { 1.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
271         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
272     };
273     WORD Indices[] = {0, 1, 2, 2, 3, 0};
274
275     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
276     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
277
278     /* Setup some states that may cause issues */
279     hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(0), (D3DMATRIX *) mat);
280     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %08x\n", hr);
281     hr = IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, (D3DMATRIX *)mat);
282     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %08x\n", hr);
283     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, (D3DMATRIX *) mat);
284     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %08x\n", hr);
285     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
286     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
287     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
288     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
289     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
290     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
291     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
292     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
293     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, FALSE);
294     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
295     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
296     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
297     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, FALSE);
298     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
299     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
300     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
301     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_COLORWRITEENABLE, &old_colorwrite);
302     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
303     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
304     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
305
306     hr = IDirect3DDevice9_SetFVF(device, 0);
307     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
308
309     hr = IDirect3DDevice9_SetFVF(device, fvf);
310     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
311
312     hr = IDirect3DDevice9_BeginScene(device);
313     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
314     if(hr == D3D_OK)
315     {
316         /* No lights are defined... That means, lit vertices should be entirely black */
317         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
318         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
319         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
320                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitquad, sizeof(unlitquad[0]));
321         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
322
323         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
324         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
325         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
326                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litquad, sizeof(litquad[0]));
327         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
328
329         hr = IDirect3DDevice9_SetFVF(device, nfvf);
330         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
331
332         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
333         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
334         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
335                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitnquad, sizeof(unlitnquad[0]));
336         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
337
338         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
339         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
340         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
341                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litnquad, sizeof(litnquad[0]));
342         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
343
344         IDirect3DDevice9_EndScene(device);
345         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
346     }
347
348     color = getPixelColor(device, 160, 360); /* Lower left quad - unlit without normals */
349     ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x, expected 0x00ff0000.\n", color);
350     color = getPixelColor(device, 160, 120); /* Upper left quad - lit without normals */
351     ok(color == 0x00000000, "Lit quad without normals has color 0x%08x, expected 0x00000000.\n", color);
352     color = getPixelColor(device, 480, 360); /* Lower left quad - unlit with normals */
353     ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x, expected 0x000000ff.\n", color);
354     color = getPixelColor(device, 480, 120); /* Upper left quad - lit with normals */
355     ok(color == 0x00000000, "Lit quad with normals has color 0x%08x, expected 0x00000000.\n", color);
356
357     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
358
359     hr = IDirect3DDevice9_GetMaterial(device, &old_material);
360     ok(hr == D3D_OK, "IDirect3DDevice9_GetMaterial returned %08x\n", hr);
361     memset(&material, 0, sizeof(material));
362     material.Diffuse.r = 0.0;
363     material.Diffuse.g = 0.0;
364     material.Diffuse.b = 0.0;
365     material.Diffuse.a = 1.0;
366     material.Ambient.r = 0.0;
367     material.Ambient.g = 0.0;
368     material.Ambient.b = 0.0;
369     material.Ambient.a = 0.0;
370     material.Specular.r = 0.0;
371     material.Specular.g = 0.0;
372     material.Specular.b = 0.0;
373     material.Specular.a = 0.0;
374     material.Emissive.r = 0.0;
375     material.Emissive.g = 0.0;
376     material.Emissive.b = 0.0;
377     material.Emissive.a = 0.0;
378     material.Power = 0.0;
379     IDirect3DDevice9_SetMaterial(device, &material);
380     ok(hr == D3D_OK, "IDirect3DDevice9_SetMaterial returned %08x\n", hr);
381
382     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
383     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
384     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
385     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
386
387     hr = IDirect3DDevice9_GetTextureStageState(device, 0, D3DTSS_COLOROP, &cop);
388     ok(hr == D3D_OK, "IDirect3DDevice9_GetTextureStageState returned %08x\n", hr);
389     hr = IDirect3DDevice9_GetTextureStageState(device, 0, D3DTSS_COLORARG1, &carg);
390     ok(hr == D3D_OK, "IDirect3DDevice9_GetTextureStageState returned %08x\n", hr);
391     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
392     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
393     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE | D3DTA_ALPHAREPLICATE);
394     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
395
396     hr = IDirect3DDevice9_BeginScene(device);
397     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
398     if(SUCCEEDED(hr)) {
399         struct vertex lighting_test[] = {
400             {-1.0,   -1.0,   0.1,    0x8000ff00},
401             { 1.0,   -1.0,   0.1,    0x80000000},
402             {-1.0,    1.0,   0.1,    0x8000ff00},
403             { 1.0,    1.0,   0.1,    0x80000000}
404         };
405         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
406         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr=%08x\n", hr);
407         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, lighting_test, sizeof(lighting_test[0]));
408         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
409
410         hr = IDirect3DDevice9_EndScene(device);
411         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
412     }
413
414     color = getPixelColor(device, 320, 240);
415     ok(color == 0x00ffffff, "Lit vertex alpha test returned color %08x, expected 0x00ffffff\n", color);
416     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
417
418     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, cop);
419     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
420     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
421     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
422     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
423     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
424     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
425     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
426     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, old_colorwrite);
427     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
428     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, carg);
429     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
430     hr = IDirect3DDevice9_SetMaterial(device, &old_material);
431     ok(hr == D3D_OK, "IDirect3DDevice9_SetMaterial returned %08x\n", hr);
432 }
433
434 static void clear_test(IDirect3DDevice9 *device)
435 {
436     /* Tests the correctness of clearing parameters */
437     HRESULT hr;
438     D3DRECT rect[2];
439     D3DRECT rect_negneg;
440     DWORD color;
441     D3DVIEWPORT9 old_vp, vp;
442     RECT scissor;
443     DWORD oldColorWrite;
444     BOOL invalid_clear_failed = FALSE;
445
446     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
447     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
448
449     /* Positive x, negative y */
450     rect[0].x1 = 0;
451     rect[0].y1 = 480;
452     rect[0].x2 = 320;
453     rect[0].y2 = 240;
454
455     /* Positive x, positive y */
456     rect[1].x1 = 0;
457     rect[1].y1 = 0;
458     rect[1].x2 = 320;
459     rect[1].y2 = 240;
460     /* Clear 2 rectangles with one call. The refrast returns an error in this case, every real driver tested so far
461      * returns D3D_OK, but ignores the rectangle silently
462      */
463     hr = IDirect3DDevice9_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
464     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
465     if(hr == D3DERR_INVALIDCALL) invalid_clear_failed = TRUE;
466
467     /* negative x, negative y */
468     rect_negneg.x1 = 640;
469     rect_negneg.y1 = 240;
470     rect_negneg.x2 = 320;
471     rect_negneg.y2 = 0;
472     hr = IDirect3DDevice9_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
473     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
474     if(hr == D3DERR_INVALIDCALL) invalid_clear_failed = TRUE;
475
476     color = getPixelColor(device, 160, 360); /* lower left quad */
477     ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
478     color = getPixelColor(device, 160, 120); /* upper left quad */
479     if(invalid_clear_failed) {
480         /* If the negative rectangle was refused, the other rectangles in the list shouldn't be cleared either */
481         ok(color == 0x00ffffff, "Clear rectangle 1(pos, pos) has color %08x\n", color);
482     } else {
483         /* If the negative rectangle was dropped silently, the correct ones are cleared */
484         ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
485     }
486     color = getPixelColor(device, 480, 360); /* lower right quad  */
487     ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
488     color = getPixelColor(device, 480, 120); /* upper right quad */
489     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
490
491     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
492
493     /* Hack to work around a nvidia windows driver bug. The clear below is supposed to
494      * clear the red quad in the top left part of the render target. For some reason it
495      * doesn't work if the clear color is 0xffffffff on some versions of the Nvidia Windows
496      * driver(tested on 8.17.12.5896, Win7). A clear with a different color works around
497      * this bug and fixes the clear with the white color. Even 0xfeffffff works, but let's
498      * pick some obvious value
499      */
500     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xdeadbabe, 0.0, 0);
501     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
502
503     /* Test how the viewport affects clears */
504     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
505     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
506     hr = IDirect3DDevice9_GetViewport(device, &old_vp);
507     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
508
509     vp.X = 160;
510     vp.Y = 120;
511     vp.Width = 160;
512     vp.Height = 120;
513     vp.MinZ = 0.0;
514     vp.MaxZ = 1.0;
515     hr = IDirect3DDevice9_SetViewport(device, &vp);
516     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
517     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
518     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
519
520     vp.X = 320;
521     vp.Y = 240;
522     vp.Width = 320;
523     vp.Height = 240;
524     vp.MinZ = 0.0;
525     vp.MaxZ = 1.0;
526     hr = IDirect3DDevice9_SetViewport(device, &vp);
527     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
528     rect[0].x1 = 160;
529     rect[0].y1 = 120;
530     rect[0].x2 = 480;
531     rect[0].y2 = 360;
532     hr = IDirect3DDevice9_Clear(device, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
533     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
534
535     hr = IDirect3DDevice9_SetViewport(device, &old_vp);
536     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
537
538     color = getPixelColor(device, 158, 118);
539     ok(color == 0x00ffffff, "(158,118) has color %08x\n", color);
540     color = getPixelColor(device, 162, 118);
541     ok(color == 0x00ffffff, "(162,118) has color %08x\n", color);
542     color = getPixelColor(device, 158, 122);
543     ok(color == 0x00ffffff, "(158,122) has color %08x\n", color);
544     color = getPixelColor(device, 162, 122);
545     ok(color == 0x000000ff, "(162,122) has color %08x\n", color);
546
547     color = getPixelColor(device, 318, 238);
548     ok(color == 0x000000ff, "(318,238) has color %08x\n", color);
549     color = getPixelColor(device, 322, 238);
550     ok(color == 0x00ffffff, "(322,328) has color %08x\n", color);
551     color = getPixelColor(device, 318, 242);
552     ok(color == 0x00ffffff, "(318,242) has color %08x\n", color);
553     color = getPixelColor(device, 322, 242);
554     ok(color == 0x0000ff00, "(322,242) has color %08x\n", color);
555
556     color = getPixelColor(device, 478, 358);
557     ok(color == 0x0000ff00, "(478,358 has color %08x\n", color);
558     color = getPixelColor(device, 482, 358);
559     ok(color == 0x00ffffff, "(482,358) has color %08x\n", color);
560     color = getPixelColor(device, 478, 362);
561     ok(color == 0x00ffffff, "(478,362) has color %08x\n", color);
562     color = getPixelColor(device, 482, 362);
563     ok(color == 0x00ffffff, "(482,362) has color %08x\n", color);
564
565     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
566
567     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
568     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
569
570     scissor.left = 160;
571     scissor.right = 480;
572     scissor.top = 120;
573     scissor.bottom = 360;
574     hr = IDirect3DDevice9_SetScissorRect(device, &scissor);
575     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %08x\n", hr);
576     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, TRUE);
577     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %08x\n", hr);
578
579     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
580     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
581     hr = IDirect3DDevice9_Clear(device, 1, &rect[1], D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
582     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
583
584     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, FALSE);
585     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %08x\n", hr);
586
587     color = getPixelColor(device, 158, 118);
588     ok(color == 0x00ffffff, "Pixel 158/118 has color %08x\n", color);
589     color = getPixelColor(device, 162, 118);
590     ok(color == 0x00ffffff, "Pixel 162/118 has color %08x\n", color);
591     color = getPixelColor(device, 158, 122);
592     ok(color == 0x00ffffff, "Pixel 158/122 has color %08x\n", color);
593     color = getPixelColor(device, 162, 122);
594     ok(color == 0x00ff0000, "Pixel 162/122 has color %08x\n", color);
595
596     color = getPixelColor(device, 158, 358);
597     ok(color == 0x00ffffff, "Pixel 158/358 has color %08x\n", color);
598     color = getPixelColor(device, 162, 358);
599     ok(color == 0x0000ff00, "Pixel 162/358 has color %08x\n", color);
600     color = getPixelColor(device, 158, 358);
601     ok(color == 0x00ffffff, "Pixel 158/358 has color %08x\n", color);
602     color = getPixelColor(device, 162, 362);
603     ok(color == 0x00ffffff, "Pixel 162/362 has color %08x\n", color);
604
605     color = getPixelColor(device, 478, 118);
606     ok(color == 0x00ffffff, "Pixel 158/118 has color %08x\n", color);
607     color = getPixelColor(device, 478, 122);
608     ok(color == 0x0000ff00, "Pixel 162/118 has color %08x\n", color);
609     color = getPixelColor(device, 482, 122);
610     ok(color == 0x00ffffff, "Pixel 158/122 has color %08x\n", color);
611     color = getPixelColor(device, 482, 358);
612     ok(color == 0x00ffffff, "Pixel 162/122 has color %08x\n", color);
613
614     color = getPixelColor(device, 478, 358);
615     ok(color == 0x0000ff00, "Pixel 478/358 has color %08x\n", color);
616     color = getPixelColor(device, 478, 362);
617     ok(color == 0x00ffffff, "Pixel 478/118 has color %08x\n", color);
618     color = getPixelColor(device, 482, 358);
619     ok(color == 0x00ffffff, "Pixel 482/122 has color %08x\n", color);
620     color = getPixelColor(device, 482, 362);
621     ok(color == 0x00ffffff, "Pixel 482/122 has color %08x\n", color);
622
623     color = getPixelColor(device, 318, 238);
624     ok(color == 0x00ff0000, "Pixel 318/238 has color %08x\n", color);
625     color = getPixelColor(device, 318, 242);
626     ok(color == 0x0000ff00, "Pixel 318/242 has color %08x\n", color);
627     color = getPixelColor(device, 322, 238);
628     ok(color == 0x0000ff00, "Pixel 322/238 has color %08x\n", color);
629     color = getPixelColor(device, 322, 242);
630     ok(color == 0x0000ff00, "Pixel 322/242 has color %08x\n", color);
631
632     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
633
634     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_COLORWRITEENABLE, &oldColorWrite);
635     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
636     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED);
637     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
638
639     /* Same nvidia windows driver trouble with white clears as earlier in the same test */
640     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xdeadbeef, 0.0, 0);
641     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
642
643     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
644     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
645
646     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, oldColorWrite);
647     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
648
649     /* Colorwriteenable does not affect the clear */
650     color = getPixelColor(device, 320, 240);
651     ok(color == 0x00ffffff, "Color write protected clear returned color %08x\n", color);
652
653     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
654 }
655
656 static void color_fill_test(IDirect3DDevice9 *device)
657 {
658     HRESULT hr;
659     IDirect3DSurface9 *backbuffer = NULL;
660     IDirect3DSurface9 *rt_surface = NULL;
661     IDirect3DSurface9 *offscreen_surface = NULL;
662     DWORD fill_color, color;
663
664     /* Test ColorFill on a the backbuffer (should pass) */
665     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
666     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
667     if(backbuffer)
668     {
669         fill_color = 0x112233;
670         hr = IDirect3DDevice9_ColorFill(device, backbuffer, NULL, fill_color);
671         ok(SUCCEEDED(hr), "Color fill failed, hr %#x.\n", hr);
672
673         color = getPixelColor(device, 0, 0);
674         ok(color == fill_color, "Expected color %08x, got %08x\n", fill_color, color);
675
676         IDirect3DSurface9_Release(backbuffer);
677     }
678
679     /* Test ColorFill on a render target surface (should pass) */
680     hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &rt_surface, NULL );
681     ok(hr == D3D_OK, "Unable to create render target surface, hr = %08x\n", hr);
682     if(rt_surface)
683     {
684         fill_color = 0x445566;
685         hr = IDirect3DDevice9_ColorFill(device, rt_surface, NULL, fill_color);
686         ok(SUCCEEDED(hr), "Color fill failed, hr %#x.\n", hr);
687
688         color = getPixelColorFromSurface(rt_surface, 0, 0);
689         ok(color == fill_color, "Expected color %08x, got %08x\n", fill_color, color);
690
691         IDirect3DSurface9_Release(rt_surface);
692     }
693
694     /* Test ColorFill on a offscreen plain surface in D3DPOOL_DEFAULT (should pass) */
695     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
696             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &offscreen_surface, NULL);
697     ok(hr == D3D_OK, "Unable to create offscreen plain surface, hr = %08x\n", hr);
698     if(offscreen_surface)
699     {
700         fill_color = 0x778899;
701         hr = IDirect3DDevice9_ColorFill(device, offscreen_surface, NULL, fill_color);
702         ok(SUCCEEDED(hr), "Color fill failed, hr %#x.\n", hr);
703
704         color = getPixelColorFromSurface(offscreen_surface, 0, 0);
705         ok(color == fill_color, "Expected color %08x, got %08x\n", fill_color, color);
706
707         IDirect3DSurface9_Release(offscreen_surface);
708     }
709
710     /* Try ColorFill on a offscreen surface in sysmem (should fail) */
711     offscreen_surface = NULL;
712     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
713             D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &offscreen_surface, NULL);
714     ok(hr == D3D_OK, "Unable to create offscreen plain surface, hr = %08x\n", hr);
715     if(offscreen_surface)
716     {
717         hr = IDirect3DDevice9_ColorFill(device, offscreen_surface, NULL, 0);
718         ok(hr == D3DERR_INVALIDCALL, "ColorFill on offscreen sysmem surface failed with hr = %08x\n", hr);
719
720         IDirect3DSurface9_Release(offscreen_surface);
721     }
722 }
723
724 typedef struct {
725     float in[4];
726     DWORD out;
727 } test_data_t;
728
729 /*
730  *  c7      mova    ARGB            mov     ARGB
731  * -2.4     -2      0x00ffff00      -3      0x00ff0000
732  * -1.6     -2      0x00ffff00      -2      0x00ffff00
733  * -0.4      0      0x0000ffff      -1      0x0000ff00
734  *  0.4      0      0x0000ffff       0      0x0000ffff
735  *  1.6      2      0x00ff00ff       1      0x000000ff
736  *  2.4      2      0x00ff00ff       2      0x00ff00ff
737  */
738 static void test_mova(IDirect3DDevice9 *device)
739 {
740     static const DWORD mova_test[] = {
741         0xfffe0200,                                                             /* vs_2_0                       */
742         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
743         0x05000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0   */
744         0x05000051, 0xa00f0001, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, /* def c1, 1.0, 1.0, 0.0, 1.0   */
745         0x05000051, 0xa00f0002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, /* def c2, 0.0, 1.0, 0.0, 1.0   */
746         0x05000051, 0xa00f0003, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 0.0, 1.0, 1.0, 1.0   */
747         0x05000051, 0xa00f0004, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c4, 0.0, 0.0, 1.0, 1.0   */
748         0x05000051, 0xa00f0005, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, /* def c5, 1.0, 0.0, 1.0, 1.0   */
749         0x05000051, 0xa00f0006, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c6, 1.0, 1.0, 1.0, 1.0   */
750         0x0200002e, 0xb0010000, 0xa0000007,                                     /* mova a0.x, c7.x              */
751         0x03000001, 0xd00f0000, 0xa0e42003, 0xb0000000,                         /* mov oD0, c[a0.x + 3]         */
752         0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
753         0x0000ffff                                                              /* END                          */
754     };
755     static const DWORD mov_test[] = {
756         0xfffe0101,                                                             /* vs_1_1                       */
757         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
758         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0   */
759         0x00000051, 0xa00f0001, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, /* def c1, 1.0, 1.0, 0.0, 1.0   */
760         0x00000051, 0xa00f0002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, /* def c2, 0.0, 1.0, 0.0, 1.0   */
761         0x00000051, 0xa00f0003, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 0.0, 1.0, 1.0, 1.0   */
762         0x00000051, 0xa00f0004, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c4, 0.0, 0.0, 1.0, 1.0   */
763         0x00000051, 0xa00f0005, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, /* def c5, 1.0, 0.0, 1.0, 1.0   */
764         0x00000051, 0xa00f0006, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c6, 1.0, 1.0, 1.0, 1.0   */
765         0x00000001, 0xb0010000, 0xa0000007,                                     /* mov a0.x, c7.x               */
766         0x00000001, 0xd00f0000, 0xa0e42003,                                     /* mov oD0, c[a0.x + 3]         */
767         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
768         0x0000ffff                                                              /* END                          */
769     };
770
771     static const test_data_t test_data[2][6] = {
772         {
773             {{-2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff0000},
774             {{-1.6f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
775             {{-0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ff00},
776             {{ 0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
777             {{ 1.6f, 0.0f, 0.0f, 0.0f}, 0x000000ff},
778             {{ 2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff}
779         },
780         {
781             {{-2.4f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
782             {{-1.6f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
783             {{-0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
784             {{ 0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
785             {{ 1.6f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff},
786             {{ 2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff}
787         }
788     };
789
790     static const float quad[][3] = {
791         {-1.0f, -1.0f, 0.0f},
792         {-1.0f,  1.0f, 0.0f},
793         { 1.0f, -1.0f, 0.0f},
794         { 1.0f,  1.0f, 0.0f},
795     };
796
797     static const D3DVERTEXELEMENT9 decl_elements[] = {
798         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
799         D3DDECL_END()
800     };
801
802     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
803     IDirect3DVertexShader9 *mova_shader = NULL;
804     IDirect3DVertexShader9 *mov_shader = NULL;
805     HRESULT hr;
806     UINT i, j;
807
808     hr = IDirect3DDevice9_CreateVertexShader(device, mova_test, &mova_shader);
809     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
810     hr = IDirect3DDevice9_CreateVertexShader(device, mov_test, &mov_shader);
811     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
812     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
813     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
814     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
815     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
816
817     hr = IDirect3DDevice9_SetVertexShader(device, mov_shader);
818     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
819     for(j = 0; j < 2; ++j)
820     {
821         for (i = 0; i < (sizeof(test_data[0]) / sizeof(test_data_t)); ++i)
822         {
823             DWORD color;
824
825             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 7, test_data[j][i].in, 1);
826             ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
827
828             hr = IDirect3DDevice9_BeginScene(device);
829             ok(SUCCEEDED(hr), "BeginScene failed (%08x)\n", hr);
830
831             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], 3 * sizeof(float));
832             ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
833
834             hr = IDirect3DDevice9_EndScene(device);
835             ok(SUCCEEDED(hr), "EndScene failed (%08x)\n", hr);
836
837             color = getPixelColor(device, 320, 240);
838             ok(color == test_data[j][i].out, "Expected color %08x, got %08x (for input %f, instruction %s)\n",
839                test_data[j][i].out, color, test_data[j][i].in[0], j == 0 ? "mov" : "mova");
840
841             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
842             ok(SUCCEEDED(hr), "Present failed (%08x)\n", hr);
843
844             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
845             ok(SUCCEEDED(hr), "Clear failed (%08x)\n", hr);
846         }
847         hr = IDirect3DDevice9_SetVertexShader(device, mova_shader);
848         ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
849     }
850
851     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
852     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
853
854     IDirect3DVertexDeclaration9_Release(vertex_declaration);
855     IDirect3DVertexShader9_Release(mova_shader);
856     IDirect3DVertexShader9_Release(mov_shader);
857 }
858
859 struct sVertex {
860     float x, y, z;
861     DWORD diffuse;
862     DWORD specular;
863 };
864
865 struct sVertexT {
866     float x, y, z, rhw;
867     DWORD diffuse;
868     DWORD specular;
869 };
870
871 static void fog_test(IDirect3DDevice9 *device)
872 {
873     HRESULT hr;
874     D3DCOLOR color;
875     float start = 0.0f, end = 1.0f;
876     D3DCAPS9 caps;
877     int i;
878
879     /* Gets full z based fog with linear fog, no fog with specular color */
880     struct sVertex untransformed_1[] = {
881         {-1,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
882         {-1,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
883         { 0,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
884         { 0,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
885     };
886     /* Ok, I am too lazy to deal with transform matrices */
887     struct sVertex untransformed_2[] = {
888         {-1,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
889         {-1,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
890         { 0,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
891         { 0,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
892     };
893     /* Untransformed ones. Give them a different diffuse color to make the test look
894      * nicer. It also makes making sure that they are drawn correctly easier.
895      */
896     struct sVertexT transformed_1[] = {
897         {320,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
898         {640,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
899         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
900         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
901     };
902     struct sVertexT transformed_2[] = {
903         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
904         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
905         {640,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
906         {320,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
907     };
908     struct vertex rev_fog_quads[] = {
909        {-1.0,   -1.0,   0.1,    0x000000ff},
910        {-1.0,    0.0,   0.1,    0x000000ff},
911        { 0.0,    0.0,   0.1,    0x000000ff},
912        { 0.0,   -1.0,   0.1,    0x000000ff},
913
914        { 0.0,   -1.0,   0.9,    0x000000ff},
915        { 0.0,    0.0,   0.9,    0x000000ff},
916        { 1.0,    0.0,   0.9,    0x000000ff},
917        { 1.0,   -1.0,   0.9,    0x000000ff},
918
919        { 0.0,    0.0,   0.4,    0x000000ff},
920        { 0.0,    1.0,   0.4,    0x000000ff},
921        { 1.0,    1.0,   0.4,    0x000000ff},
922        { 1.0,    0.0,   0.4,    0x000000ff},
923
924        {-1.0,    0.0,   0.7,    0x000000ff},
925        {-1.0,    1.0,   0.7,    0x000000ff},
926        { 0.0,    1.0,   0.7,    0x000000ff},
927        { 0.0,    0.0,   0.7,    0x000000ff},
928     };
929     WORD Indices[] = {0, 1, 2, 2, 3, 0};
930
931     const float ident_mat[16] =
932     {
933         1.0f, 0.0f, 0.0f, 0.0f,
934         0.0f, 1.0f, 0.0f, 0.0f,
935         0.0f, 0.0f, 1.0f, 0.0f,
936         0.0f, 0.0f, 0.0f, 1.0f
937     };
938     const float world_mat1[16] =
939     {
940         1.0f, 0.0f,  0.0f, 0.0f,
941         0.0f, 1.0f,  0.0f, 0.0f,
942         0.0f, 0.0f,  1.0f, 0.0f,
943         0.0f, 0.0f, -0.5f, 1.0f
944     };
945     const float world_mat2[16] =
946     {
947         1.0f, 0.0f, 0.0f, 0.0f,
948         0.0f, 1.0f, 0.0f, 0.0f,
949         0.0f, 0.0f, 1.0f, 0.0f,
950         0.0f, 0.0f, 1.0f, 1.0f
951     };
952     const float proj_mat[16] =
953     {
954         1.0f, 0.0f,  0.0f, 0.0f,
955         0.0f, 1.0f,  0.0f, 0.0f,
956         0.0f, 0.0f,  1.0f, 0.0f,
957         0.0f, 0.0f, -1.0f, 1.0f
958     };
959
960     const struct sVertex far_quad1[] =
961     {
962         {-1.0f, -1.0f, 0.5f, 0xffff0000, 0xff000000},
963         {-1.0f,  0.0f, 0.5f, 0xffff0000, 0xff000000},
964         { 0.0f,  0.0f, 0.5f, 0xffff0000, 0xff000000},
965         { 0.0f, -1.0f, 0.5f, 0xffff0000, 0xff000000},
966     };
967     const struct sVertex far_quad2[] =
968     {
969         {-1.0f, 0.0f, 1.5f, 0xffff0000, 0xff000000},
970         {-1.0f, 1.0f, 1.5f, 0xffff0000, 0xff000000},
971         { 0.0f, 1.0f, 1.5f, 0xffff0000, 0xff000000},
972         { 0.0f, 0.0f, 1.5f, 0xffff0000, 0xff000000},
973     };
974
975     memset(&caps, 0, sizeof(caps));
976     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
977     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %08x\n", hr);
978     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
979     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
980
981     /* Setup initial states: No lighting, fog on, fog color */
982     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
983     ok(hr == D3D_OK, "Turning off lighting returned %08x\n", hr);
984     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
985     ok(hr == D3D_OK, "Turning on fog calculations returned %08x\n", hr);
986     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
987     ok(hr == D3D_OK, "Setting fog color returned %#08x\n", hr);
988
989     /* First test: Both table fog and vertex fog off */
990     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
991     ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
992     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
993     ok(hr == D3D_OK, "Turning off vertex fog returned %08x\n", hr);
994
995     /* Start = 0, end = 1. Should be default, but set them */
996     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
997     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
998     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
999     ok(hr == D3D_OK, "Setting fog end returned %08x\n", hr);
1000
1001     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
1002     {
1003         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
1004         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
1005         /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
1006         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
1007                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, untransformed_1,
1008                                                      sizeof(untransformed_1[0]));
1009         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
1010
1011         /* That makes it use the Z value */
1012         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
1013         ok(hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR returned %#08x\n", hr);
1014         /* Untransformed, vertex fog != none (or table fog != none):
1015          * Use the Z value as input into the equation
1016          */
1017         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
1018                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, untransformed_2,
1019                                                      sizeof(untransformed_2[0]));
1020         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
1021
1022         /* transformed verts */
1023         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
1024         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
1025         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
1026         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
1027                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
1028                                                      sizeof(transformed_1[0]));
1029         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
1030
1031         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
1032         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
1033         /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
1034          * equation
1035          */
1036         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
1037                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_2,
1038                                                      sizeof(transformed_2[0]));
1039         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
1040
1041         hr = IDirect3DDevice9_EndScene(device);
1042         ok(hr == D3D_OK, "EndScene returned %08x\n", hr);
1043     }
1044     else
1045     {
1046         ok(FALSE, "BeginScene failed\n");
1047     }
1048
1049     color = getPixelColor(device, 160, 360);
1050     ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color);
1051     color = getPixelColor(device, 160, 120);
1052     ok(color_match(color, 0x0000ff00, 1), "Untransformed vertex with linear vertex fog has color %08x\n", color);
1053     color = getPixelColor(device, 480, 120);
1054     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
1055     if(caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
1056     {
1057         color = getPixelColor(device, 480, 360);
1058         ok(color_match(color, 0x0000ff00, 1), "Transformed vertex with linear table fog has color %08x\n", color);
1059     }
1060     else
1061     {
1062         /* Without fog table support the vertex fog is still applied, even though table fog is turned on.
1063          * The settings above result in no fogging with vertex fog
1064          */
1065         color = getPixelColor(device, 480, 120);
1066         ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
1067         trace("Info: Table fog not supported by this device\n");
1068     }
1069     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1070
1071     /* Now test the special case fogstart == fogend */
1072     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
1073     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
1074
1075     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
1076     {
1077         start = 512;
1078         end = 512;
1079         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
1080         ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
1081         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
1082         ok(hr == D3D_OK, "Setting fog end returned %08x\n", hr);
1083
1084         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
1085         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
1086         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
1087         ok( hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR returned %08x\n", hr);
1088         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
1089         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
1090
1091         /* Untransformed vertex, z coord = 0.1, fogstart = 512, fogend = 512. Would result in
1092          * a completely fog-free primitive because start > zcoord, but because start == end, the primitive
1093          * is fully covered by fog. The same happens to the 2nd untransformed quad with z = 1.0.
1094          * The third transformed quad remains unfogged because the fogcoords are read from the specular
1095          * color and has fixed fogstart and fogend.
1096          */
1097         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
1098                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, untransformed_1,
1099                 sizeof(untransformed_1[0]));
1100         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
1101         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
1102                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, untransformed_2,
1103                 sizeof(untransformed_2[0]));
1104         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
1105
1106         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
1107         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
1108         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
1109         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
1110                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
1111                 sizeof(transformed_1[0]));
1112         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
1113
1114         hr = IDirect3DDevice9_EndScene(device);
1115         ok(hr == D3D_OK, "EndScene returned %08x\n", hr);
1116     }
1117     else
1118     {
1119         ok(FALSE, "BeginScene failed\n");
1120     }
1121     color = getPixelColor(device, 160, 360);
1122     ok(color_match(color, 0x0000ff00, 1), "Untransformed vertex with vertex fog and z = 0.1 has color %08x\n", color);
1123     color = getPixelColor(device, 160, 120);
1124     ok(color_match(color, 0x0000ff00, 1), "Untransformed vertex with vertex fog and z = 1.0 has color %08x\n", color);
1125     color = getPixelColor(device, 480, 120);
1126     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
1127     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1128
1129     /* Test "reversed" fog without shaders. With shaders this fails on a few Windows D3D implementations,
1130      * but without shaders it seems to work everywhere
1131      */
1132     end = 0.2;
1133     start = 0.8;
1134     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
1135     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
1136     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
1137     ok(hr == D3D_OK, "Setting fog end returned %08x\n", hr);
1138     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1139     ok( hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
1140
1141     /* Test reversed fog without shaders. ATI cards have problems with reversed fog and shaders, so
1142      * it doesn't seem very important for games. ATI cards also have problems with reversed table fog,
1143      * so skip this for now
1144      */
1145     for(i = 0; i < 1 /*2 - Table fog test disabled, fails on ATI */; i++) {
1146         const char *mode = (i ? "table" : "vertex");
1147         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
1148         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
1149         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, i == 0 ? D3DFOG_LINEAR : D3DFOG_NONE);
1150         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1151         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, i == 0 ? D3DFOG_NONE : D3DFOG_LINEAR);
1152         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1153         hr = IDirect3DDevice9_BeginScene(device);
1154         ok( hr == D3D_OK, "IDirect3DDDevice9_BeginScene returned %08x\n", hr);
1155         if(SUCCEEDED(hr)) {
1156             WORD Indices2[] = { 0,  1,  2,  2,  3, 0,
1157                                 4,  5,  6,  6,  7, 4,
1158                                 8,  9, 10, 10, 11, 8,
1159                             12, 13, 14, 14, 15, 12};
1160
1161             hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */,
1162                     16 /* NumVerts */, 8 /*PrimCount */, Indices2, D3DFMT_INDEX16, rev_fog_quads,
1163                     sizeof(rev_fog_quads[0]));
1164             ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
1165
1166             hr = IDirect3DDevice9_EndScene(device);
1167             ok( hr == D3D_OK, "IDirect3DDDevice9_EndScene returned %08x\n", hr);
1168         }
1169         color = getPixelColor(device, 160, 360);
1170         ok(color_match(color, 0x0000ff00, 1),
1171                 "Reversed %s fog: z=0.1 has color 0x%08x, expected 0x0000ff00 or 0x0000fe00\n", mode, color);
1172
1173         color = getPixelColor(device, 160, 120);
1174         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x2b, 0xd4), 2),
1175                 "Reversed %s fog: z=0.7 has color 0x%08x\n", mode, color);
1176
1177         color = getPixelColor(device, 480, 120);
1178         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xaa, 0x55), 2),
1179                 "Reversed %s fog: z=0.4 has color 0x%08x\n", mode, color);
1180
1181         color = getPixelColor(device, 480, 360);
1182         ok(color == 0x000000ff, "Reversed %s fog: z=0.9 has color 0x%08x, expected 0x000000ff\n", mode, color);
1183
1184         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1185
1186         if(!(caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)) {
1187             skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping reversed table fog test\n");
1188             break;
1189         }
1190     }
1191
1192     if (caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
1193     {
1194         /* A simple fog + non-identity world matrix test */
1195         hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(0), (const D3DMATRIX *)world_mat1);
1196         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %#08x\n", hr);
1197
1198         start = 0.0;
1199         end = 1.0;
1200         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *)&start));
1201         ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
1202         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *)&end));
1203         ok(hr == D3D_OK, "Setting fog end returned %08x\n", hr);
1204         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
1205         ok(hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %#08x\n", hr);
1206         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
1207         ok(hr == D3D_OK, "Turning off vertex fog returned %#08x\n", hr);
1208
1209         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1210         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %#08x\n", hr);
1211
1212         if (IDirect3DDevice9_BeginScene(device) == D3D_OK)
1213         {
1214             hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
1215             ok(hr == D3D_OK, "SetVertexShader returned %#08x\n", hr);
1216
1217             hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4,
1218                     2, Indices, D3DFMT_INDEX16, far_quad1, sizeof(far_quad1[0]));
1219             ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
1220
1221             hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4,
1222                     2, Indices, D3DFMT_INDEX16, far_quad2, sizeof(far_quad2[0]));
1223             ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
1224
1225             hr = IDirect3DDevice9_EndScene(device);
1226             ok(hr == D3D_OK, "EndScene returned %#08x\n", hr);
1227         }
1228         else
1229         {
1230             ok(FALSE, "BeginScene failed\n");
1231         }
1232
1233         color = getPixelColor(device, 160, 360);
1234         ok(color_match(color, 0x00ff0000, 4), "Unfogged quad has color %08x\n", color);
1235         color = getPixelColor(device, 160, 120);
1236         ok(color == 0x0000ff00, "Fogged out quad has color %08x\n", color);
1237
1238         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1239
1240         /* Test fog behavior with an orthogonal (but non-identity) projection matrix */
1241         hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(0), (const D3DMATRIX *)world_mat2);
1242         ok(hr == D3D_OK, "SetTransform returned %#08x\n", hr);
1243         hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, (const D3DMATRIX *)proj_mat);
1244         ok(hr == D3D_OK, "SetTransform returned %#08x\n", hr);
1245
1246         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1247         ok(hr == D3D_OK, "Clear returned %#08x\n", hr);
1248
1249         if (IDirect3DDevice9_BeginScene(device) == D3D_OK)
1250         {
1251             hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
1252             ok(hr == D3D_OK, "SetVertexShader returned %#08x\n", hr);
1253
1254             hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4,
1255                     2, Indices, D3DFMT_INDEX16, untransformed_1, sizeof(untransformed_1[0]));
1256             ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
1257
1258             hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4,
1259                     2, Indices, D3DFMT_INDEX16, untransformed_2, sizeof(untransformed_2[0]));
1260             ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
1261
1262             hr = IDirect3DDevice9_EndScene(device);
1263             ok(hr == D3D_OK, "EndScene returned %#08x\n", hr);
1264         }
1265         else
1266         {
1267             ok(FALSE, "BeginScene failed\n");
1268         }
1269
1270         color = getPixelColor(device, 160, 360);
1271         todo_wine ok(color_match(color, 0x00e51900, 4), "Partially fogged quad has color %08x\n", color);
1272         color = getPixelColor(device, 160, 120);
1273         ok(color == 0x0000ff00, "Fogged out quad has color %08x\n", color);
1274
1275         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1276
1277         hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(0), (const D3DMATRIX *)ident_mat);
1278         ok(hr == D3D_OK, "SetTransform returned %#08x\n", hr);
1279         hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, (const D3DMATRIX *)ident_mat);
1280         ok(hr == D3D_OK, "SetTransform returned %#08x\n", hr);
1281     }
1282     else
1283     {
1284         skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests\n");
1285     }
1286
1287     /* Test RANGEFOG vs FOGTABLEMODE */
1288     if ((caps.RasterCaps & (D3DPRASTERCAPS_FOGTABLE | D3DPRASTERCAPS_FOGRANGE)) ==
1289             (D3DPRASTERCAPS_FOGTABLE | D3DPRASTERCAPS_FOGRANGE))
1290     {
1291         struct sVertex untransformed_3[] =
1292         {
1293             {-1.0,-1.0,   0.4999f,      0xFFFF0000,     0xFF000000  },
1294             {-1.0, 1.0,   0.4999f,      0xFFFF0000,     0xFF000000  },
1295             { 1.0,-1.0,   0.4999f,      0xFFFF0000,     0xFF000000  },
1296             { 1.0, 1.0,   0.4999f,      0xFFFF0000,     0xFF000000  },
1297         };
1298
1299         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1300         ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed, hr %#x.\n", hr);
1301         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
1302         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetFVF failed, hr %#x.\n", hr);
1303
1304         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_RANGEFOGENABLE, TRUE);
1305         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
1306
1307         /* z=0.4999, set the fogstart to 0.5 and fogend slightly higher. If range fog
1308          * is not used, the fog coordinate will be equal to fogstart and the quad not
1309          * fogged. If range fog is used the fog coordinate will be slightly higher and
1310          * the fog coordinate will be > fogend, so we get a fully fogged quad. The fog
1311          * is calculated per vertex and interpolated, so even the center of the screen
1312          * where the difference doesn't matter will be fogged, but check the corners in
1313          * case a d3d/gl implementation decides to calculate the fog factor per fragment */
1314         start = 0.5f;
1315         end = 0.50001f;
1316         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
1317         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
1318         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
1319         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
1320
1321         /* Table fog: Range fog is not used */
1322         hr = IDirect3DDevice9_BeginScene(device);
1323         ok(SUCCEEDED(hr), "IDirect3DDevice9_BeginScene failed, hr %#x.\n", hr);
1324         if (SUCCEEDED(hr))
1325         {
1326             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
1327             ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
1328             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, untransformed_3, sizeof(*untransformed_3));
1329             ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitiveUP failed, hr %#x.\n", hr);
1330             hr = IDirect3DDevice9_EndScene(device);
1331             ok(SUCCEEDED(hr), "IDirect3DDevice9_EndScene failed, hr %#x.\n", hr);
1332         }
1333         color = getPixelColor(device, 10, 10);
1334         ok(color == 0x00ff0000, "Rangefog with table fog returned color 0x%08x\n", color);
1335         color = getPixelColor(device, 630, 10);
1336         ok(color == 0x00ff0000, "Rangefog with table fog returned color 0x%08x\n", color);
1337         color = getPixelColor(device, 10, 470);
1338         ok(color == 0x00ff0000, "Rangefog with table fog returned color 0x%08x\n", color);
1339         color = getPixelColor(device, 630, 470);
1340         ok(color == 0x00ff0000, "Rangefog with table fog returned color 0x%08x\n", color);
1341
1342         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1343         ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed, hr %#x.\n", hr);
1344
1345         /* Vertex fog: Rangefog is used */
1346         hr = IDirect3DDevice9_BeginScene(device);
1347         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP returned %#08x\n", hr);
1348         if (SUCCEEDED(hr))
1349         {
1350             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
1351             ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
1352             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
1353             ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
1354             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, untransformed_3, sizeof(*untransformed_3));
1355             ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitiveUP failed, hr %#x.\n", hr);
1356             hr = IDirect3DDevice9_EndScene(device);
1357             ok(SUCCEEDED(hr), "IDirect3DDevice9_EndScene failed, hr %#x.\n", hr);
1358         }
1359         color = getPixelColor(device, 10, 10);
1360         ok(color == 0x0000ff00, "Rangefog with vertex fog returned color 0x%08x\n", color);
1361         color = getPixelColor(device, 630, 10);
1362         ok(color == 0x0000ff00, "Rangefog with vertex fog returned color 0x%08x\n", color);
1363         color = getPixelColor(device, 10, 470);
1364         ok(color == 0x0000ff00, "Rangefog with vertex fog returned color 0x%08x\n", color);
1365         color = getPixelColor(device, 630, 470);
1366         ok(color == 0x0000ff00, "Rangefog with vertex fog returned color 0x%08x\n", color);
1367
1368         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1369         ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed, hr %#x.\n", hr);
1370
1371         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_RANGEFOGENABLE, FALSE);
1372         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
1373     }
1374     else
1375     {
1376         skip("Range fog or table fog not supported, skipping range fog tests\n");
1377     }
1378
1379     /* Turn off the fog master switch to avoid confusing other tests */
1380     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
1381     ok(hr == D3D_OK, "Turning off fog calculations returned %08x\n", hr);
1382     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
1383     ok( hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR returned %08x\n", hr);
1384     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
1385     ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
1386 }
1387
1388 /* This test verifies the behaviour of cube maps wrt. texture wrapping.
1389  * D3D cube map wrapping always behaves like GL_CLAMP_TO_EDGE,
1390  * regardless of the actual addressing mode set. The way this test works is
1391  * that we sample in one of the corners of the cubemap with filtering enabled,
1392  * and check the interpolated color. There are essentially two reasonable
1393  * things an implementation can do: Either pick one of the faces and
1394  * interpolate the edge texel with itself (i.e., clamp within the face), or
1395  * interpolate between the edge texels of the three involved faces. It should
1396  * never involve the border color or the other side (texcoord wrapping) of a
1397  * face in the interpolation. */
1398 static void test_cube_wrap(IDirect3DDevice9 *device)
1399 {
1400     static const float quad[][6] = {
1401         {-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1402         {-1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1403         { 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1404         { 1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1405     };
1406
1407     static const D3DVERTEXELEMENT9 decl_elements[] = {
1408         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1409         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1410         D3DDECL_END()
1411     };
1412
1413     static const struct {
1414         D3DTEXTUREADDRESS mode;
1415         const char *name;
1416     } address_modes[] = {
1417         {D3DTADDRESS_WRAP, "D3DTADDRESS_WRAP"},
1418         {D3DTADDRESS_MIRROR, "D3DTADDRESS_MIRROR"},
1419         {D3DTADDRESS_CLAMP, "D3DTADDRESS_CLAMP"},
1420         {D3DTADDRESS_BORDER, "D3DTADDRESS_BORDER"},
1421         {D3DTADDRESS_MIRRORONCE, "D3DTADDRESS_MIRRORONCE"},
1422     };
1423
1424     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1425     IDirect3DCubeTexture9 *texture = NULL;
1426     IDirect3DSurface9 *surface = NULL;
1427     IDirect3DSurface9 *face_surface;
1428     D3DLOCKED_RECT locked_rect;
1429     HRESULT hr;
1430     UINT x;
1431     INT y, face;
1432
1433     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1434     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1435     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1436     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1437
1438     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
1439             D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL);
1440     ok(SUCCEEDED(hr), "CreateOffscreenPlainSurface failed (0x%08x)\n", hr);
1441
1442     hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
1443             D3DPOOL_DEFAULT, &texture, NULL);
1444     ok(SUCCEEDED(hr), "CreateCubeTexture failed (0x%08x)\n", hr);
1445
1446     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
1447     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1448
1449     for (y = 0; y < 128; ++y)
1450     {
1451         DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1452         for (x = 0; x < 64; ++x)
1453         {
1454             *ptr++ = 0xff0000ff;
1455         }
1456         for (x = 64; x < 128; ++x)
1457         {
1458             *ptr++ = 0xffff0000;
1459         }
1460     }
1461
1462     hr = IDirect3DSurface9_UnlockRect(surface);
1463     ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
1464
1465     hr= IDirect3DCubeTexture9_GetCubeMapSurface(texture, 0, 0, &face_surface);
1466     ok(SUCCEEDED(hr), "GetCubeMapSurface failed (0x%08x)\n", hr);
1467
1468     hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, face_surface, NULL);
1469     ok(SUCCEEDED(hr), "UpdateSurface failed (0x%08x)\n", hr);
1470
1471     IDirect3DSurface9_Release(face_surface);
1472
1473     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
1474     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1475
1476     for (y = 0; y < 128; ++y)
1477     {
1478         DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1479         for (x = 0; x < 64; ++x)
1480         {
1481             *ptr++ = 0xffff0000;
1482         }
1483         for (x = 64; x < 128; ++x)
1484         {
1485             *ptr++ = 0xff0000ff;
1486         }
1487     }
1488
1489     hr = IDirect3DSurface9_UnlockRect(surface);
1490     ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
1491
1492     /* Create cube faces */
1493     for (face = 1; face < 6; ++face)
1494     {
1495         hr= IDirect3DCubeTexture9_GetCubeMapSurface(texture, face, 0, &face_surface);
1496         ok(SUCCEEDED(hr), "GetCubeMapSurface failed (0x%08x)\n", hr);
1497
1498         hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, face_surface, NULL);
1499         ok(SUCCEEDED(hr), "UpdateSurface failed (0x%08x)\n", hr);
1500
1501         IDirect3DSurface9_Release(face_surface);
1502     }
1503
1504     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
1505     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1506
1507     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
1508     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1509     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
1510     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1511     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_BORDERCOLOR, 0xff00ff00);
1512     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_BORDERCOLOR failed (0x%08x)\n", hr);
1513
1514     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1515     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1516
1517     for (x = 0; x < (sizeof(address_modes) / sizeof(*address_modes)); ++x)
1518     {
1519         DWORD color;
1520
1521         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, address_modes[x].mode);
1522         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU (%s) failed (0x%08x)\n", address_modes[x].name, hr);
1523         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, address_modes[x].mode);
1524         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV (%s) failed (0x%08x)\n", address_modes[x].name, hr);
1525
1526         hr = IDirect3DDevice9_BeginScene(device);
1527         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1528
1529         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1530         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
1531
1532         hr = IDirect3DDevice9_EndScene(device);
1533         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1534
1535         color = getPixelColor(device, 320, 240);
1536         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xff), 1),
1537                 "Got color 0x%08x for addressing mode %s, expected 0x000000ff.\n",
1538                 color, address_modes[x].name);
1539
1540         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1541         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1542
1543         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
1544         ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
1545     }
1546
1547     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1548     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1549
1550     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1551     IDirect3DCubeTexture9_Release(texture);
1552     IDirect3DSurface9_Release(surface);
1553 }
1554
1555 static void offscreen_test(IDirect3DDevice9 *device)
1556 {
1557     HRESULT hr;
1558     IDirect3DTexture9 *offscreenTexture = NULL;
1559     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
1560     DWORD color;
1561
1562     static const float quad[][5] = {
1563         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
1564         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
1565         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
1566         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
1567     };
1568
1569     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
1570     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
1571
1572     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
1573     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %08x\n", hr);
1574     if(!offscreenTexture) {
1575         trace("Failed to create an X8R8G8B8 offscreen texture, trying R5G6B5\n");
1576         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
1577         ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %08x\n", hr);
1578         if(!offscreenTexture) {
1579             skip("Cannot create an offscreen render target\n");
1580             goto out;
1581         }
1582     }
1583
1584     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1585     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
1586     if(!backbuffer) {
1587         goto out;
1588     }
1589
1590     hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
1591     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %08x\n", hr);
1592     if(!offscreen) {
1593         goto out;
1594     }
1595
1596     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
1597     ok(hr == D3D_OK, "SetFVF failed, hr = %08x\n", hr);
1598
1599     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
1600     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
1601     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
1602     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
1603     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
1604     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1605     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
1606     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1607     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1608     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1609
1610     if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
1611         hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
1612         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
1613         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1614         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
1615
1616         /* Draw without textures - Should result in a white quad */
1617         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
1618         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %08x\n", hr);
1619
1620         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
1621         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
1622         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
1623         ok(hr == D3D_OK, "SetTexture failed, %08x\n", hr);
1624
1625         /* This time with the texture */
1626         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
1627         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %08x\n", hr);
1628
1629         IDirect3DDevice9_EndScene(device);
1630     }
1631
1632     /* Center quad - should be white */
1633     color = getPixelColor(device, 320, 240);
1634     ok(color == 0x00ffffff, "Offscreen failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1635     /* Some quad in the cleared part of the texture */
1636     color = getPixelColor(device, 170, 240);
1637     ok(color == 0x00ff00ff, "Offscreen failed: Got color 0x%08x, expected 0x00ff00ff.\n", color);
1638     /* Part of the originally cleared back buffer */
1639     color = getPixelColor(device, 10, 10);
1640     ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1641     if(0) {
1642         /* Lower left corner of the screen, where back buffer offscreen rendering draws the offscreen texture.
1643          * It should be red, but the offscreen texture may leave some junk there. Not tested yet. Depending on
1644          * the offscreen rendering mode this test would succeed or fail
1645          */
1646         color = getPixelColor(device, 10, 470);
1647         ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1648     }
1649
1650     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1651
1652 out:
1653     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1654     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture returned %#x.\n", hr);
1655
1656     /* restore things */
1657     if(backbuffer) {
1658         IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
1659         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderTarget returned %#x.\n", hr);
1660         IDirect3DSurface9_Release(backbuffer);
1661     }
1662     if(offscreenTexture) {
1663         IDirect3DTexture9_Release(offscreenTexture);
1664     }
1665     if(offscreen) {
1666         IDirect3DSurface9_Release(offscreen);
1667     }
1668 }
1669
1670 /* This test tests fog in combination with shaders.
1671  * What's tested: linear fog (vertex and table) with pixel shader
1672  *                linear table fog with non foggy vertex shader
1673  *                vertex fog with foggy vertex shader, non-linear
1674  *                fog with shader, non-linear fog with foggy shader,
1675  *                linear table fog with foggy shader
1676  */
1677 static void fog_with_shader_test(IDirect3DDevice9 *device)
1678 {
1679     HRESULT hr;
1680     DWORD color;
1681     union {
1682         float f;
1683         DWORD i;
1684     } start, end;
1685     unsigned int i, j;
1686
1687     /* basic vertex shader without fog computation ("non foggy") */
1688     static const DWORD vertex_shader_code1[] = {
1689         0xfffe0101,                                                             /* vs_1_1                       */
1690         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
1691         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                */
1692         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
1693         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                  */
1694         0x0000ffff
1695     };
1696     /* basic vertex shader with reversed fog computation ("foggy") */
1697     static const DWORD vertex_shader_code2[] = {
1698         0xfffe0101,                                                             /* vs_1_1                        */
1699         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0               */
1700         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                 */
1701         0x00000051, 0xa00f0000, 0xbfa00000, 0x00000000, 0xbf666666, 0x00000000, /* def c0, -1.25, 0.0, -0.9, 0.0 */
1702         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                  */
1703         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                   */
1704         0x00000002, 0x800f0000, 0x90aa0000, 0xa0aa0000,                         /* add r0, v0.z, c0.z            */
1705         0x00000005, 0xc00f0001, 0x80000000, 0xa0000000,                         /* mul oFog, r0.x, c0.x          */
1706         0x0000ffff
1707     };
1708     /* basic pixel shader */
1709     static const DWORD pixel_shader_code[] = {
1710         0xffff0101,                                                             /* ps_1_1     */
1711         0x00000001, 0x800f0000, 0x90e40000,                                     /* mov r0, vo */
1712         0x0000ffff
1713     };
1714
1715     static struct vertex quad[] = {
1716         {-1.0f, -1.0f,  0.0f,          0xFFFF0000  },
1717         {-1.0f,  1.0f,  0.0f,          0xFFFF0000  },
1718         { 1.0f, -1.0f,  0.0f,          0xFFFF0000  },
1719         { 1.0f,  1.0f,  0.0f,          0xFFFF0000  },
1720     };
1721
1722     static const D3DVERTEXELEMENT9 decl_elements[] = {
1723         {0,  0, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1724         {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
1725         D3DDECL_END()
1726     };
1727
1728     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1729     IDirect3DVertexShader9      *vertex_shader[3]   = {NULL, NULL, NULL};
1730     IDirect3DPixelShader9       *pixel_shader[2]    = {NULL, NULL};
1731
1732     /* This reference data was collected on a nVidia GeForce 7600GS driver version 84.19 DirectX version 9.0c on Windows XP */
1733     static const struct test_data_t {
1734         int vshader;
1735         int pshader;
1736         D3DFOGMODE vfog;
1737         D3DFOGMODE tfog;
1738         unsigned int color[11];
1739     } test_data[] = {
1740         /* only pixel shader: */
1741         {0, 1, D3DFOG_NONE, D3DFOG_LINEAR,
1742         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1743         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1744         {0, 1, D3DFOG_EXP, D3DFOG_LINEAR,
1745         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1746         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1747         {0, 1, D3DFOG_EXP2, D3DFOG_LINEAR,
1748         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1749         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1750         {0, 1, D3DFOG_LINEAR, D3DFOG_NONE,
1751         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1752         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1753         {0, 1, D3DFOG_LINEAR, D3DFOG_LINEAR,
1754         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1755         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1756
1757         /* vertex shader */
1758         {1, 0, D3DFOG_NONE, D3DFOG_NONE,
1759         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1760          0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1761         {1, 0, D3DFOG_NONE, D3DFOG_LINEAR,
1762         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1763         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1764         {1, 0, D3DFOG_EXP, D3DFOG_LINEAR,
1765         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1766         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1767
1768         {1, 0, D3DFOG_EXP2, D3DFOG_LINEAR,
1769         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1770         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1771         {1, 0, D3DFOG_LINEAR, D3DFOG_LINEAR,
1772         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1773         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1774
1775         /* vertex shader and pixel shader */
1776         /* The next 4 tests would read the fog coord output, but it isn't available.
1777          * The result is a fully fogged quad, no matter what the Z coord is. This is on
1778          * a geforce 7400, 97.52 driver, Windows Vista, but probably hardware dependent.
1779          * These tests should be disabled if some other hardware behaves differently
1780          */
1781         {1, 1, D3DFOG_NONE, D3DFOG_NONE,
1782         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1783         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1784         {1, 1, D3DFOG_LINEAR, D3DFOG_NONE,
1785         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1786         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1787         {1, 1, D3DFOG_EXP, D3DFOG_NONE,
1788         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1789         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1790         {1, 1, D3DFOG_EXP2, D3DFOG_NONE,
1791         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1792         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1793
1794         /* These use the Z coordinate with linear table fog */
1795         {1, 1, D3DFOG_NONE, D3DFOG_LINEAR,
1796         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1797         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1798         {1, 1, D3DFOG_EXP, D3DFOG_LINEAR,
1799         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1800         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1801         {1, 1, D3DFOG_EXP2, D3DFOG_LINEAR,
1802         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1803         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1804         {1, 1, D3DFOG_LINEAR, D3DFOG_LINEAR,
1805         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1806         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1807
1808         /* Non-linear table fog without fog coord */
1809         {1, 1, D3DFOG_NONE, D3DFOG_EXP,
1810         {0x00ff0000, 0x00e71800, 0x00d12e00, 0x00bd4200, 0x00ab5400, 0x009b6400,
1811         0x008d7200, 0x007f8000, 0x00738c00, 0x00689700, 0x005ea100}},
1812         {1, 1, D3DFOG_NONE, D3DFOG_EXP2,
1813         {0x00fd0200, 0x00f50200, 0x00f50a00, 0x00e91600, 0x00d92600, 0x00c73800,
1814         0x00b24d00, 0x009c6300, 0x00867900, 0x00728d00, 0x005ea100}},
1815
1816 #if 0  /* FIXME: these fail on GeForce 8500 */
1817         /* foggy vertex shader */
1818         {2, 0, D3DFOG_NONE, D3DFOG_NONE,
1819         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1820          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1821         {2, 0, D3DFOG_EXP, D3DFOG_NONE,
1822         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1823          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1824         {2, 0, D3DFOG_EXP2, D3DFOG_NONE,
1825         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1826          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1827         {2, 0, D3DFOG_LINEAR, D3DFOG_NONE,
1828         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1829          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1830 #endif
1831
1832         /* foggy vertex shader and pixel shader. First 4 tests with vertex fog,
1833          * all using the fixed fog-coord linear fog
1834          */
1835         {2, 1, D3DFOG_NONE, D3DFOG_NONE,
1836         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1837          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1838         {2, 1, D3DFOG_EXP, D3DFOG_NONE,
1839         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1840          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1841         {2, 1, D3DFOG_EXP2, D3DFOG_NONE,
1842         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1843          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1844         {2, 1, D3DFOG_LINEAR, D3DFOG_NONE,
1845         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1846          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1847
1848         /* These use table fog. Here the shader-provided fog coordinate is
1849          * ignored and the z coordinate used instead
1850          */
1851         {2, 1, D3DFOG_NONE, D3DFOG_EXP,
1852         {0x00ff0000, 0x00e71800, 0x00d12e00, 0x00bd4200, 0x00ab5400, 0x009b6400,
1853         0x008d7200, 0x007f8000, 0x00738c00, 0x00689700, 0x005ea100}},
1854         {2, 1, D3DFOG_NONE, D3DFOG_EXP2,
1855         {0x00fd0200, 0x00f50200, 0x00f50a00, 0x00e91600, 0x00d92600, 0x00c73800,
1856         0x00b24d00, 0x009c6300, 0x00867900, 0x00728d00, 0x005ea100}},
1857         {2, 1, D3DFOG_NONE, D3DFOG_LINEAR,
1858         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1859         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1860     };
1861
1862     /* NOTE: changing these values will not affect the tests with foggy vertex shader, as the values are hardcoded in the shader*/
1863     start.f=0.1f;
1864     end.f=0.9f;
1865
1866     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code1, &vertex_shader[1]);
1867     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1868     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code2, &vertex_shader[2]);
1869     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1870     hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader[1]);
1871     ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1872     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1873     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
1874
1875     /* Setup initial states: No lighting, fog on, fog color */
1876     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1877     ok(hr == D3D_OK, "Turning off lighting failed (%08x)\n", hr);
1878     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
1879     ok(hr == D3D_OK, "Turning on fog calculations failed (%08x)\n", hr);
1880     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
1881     ok(hr == D3D_OK, "Setting fog color failed (%08x)\n", hr);
1882     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1883     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1884
1885     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
1886     ok(hr == D3D_OK, "Turning off table fog failed (%08x)\n", hr);
1887     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
1888     ok(hr == D3D_OK, "Turning off vertex fog failed (%08x)\n", hr);
1889
1890     /* Use fogtart = 0.1 and end = 0.9 to test behavior outside the fog transition phase, too*/
1891     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, start.i);
1892     ok(hr == D3D_OK, "Setting fog start failed (%08x)\n", hr);
1893     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, end.i);
1894     ok(hr == D3D_OK, "Setting fog end failed (%08x)\n", hr);
1895
1896     for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++)
1897     {
1898         hr = IDirect3DDevice9_SetVertexShader(device, vertex_shader[test_data[i].vshader]);
1899         ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1900         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader[test_data[i].pshader]);
1901         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1902         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, test_data[i].vfog);
1903         ok( hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1904         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, test_data[i].tfog);
1905         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1906
1907         for(j=0; j < 11; j++)
1908         {
1909             /* Don't use the whole zrange to prevent rounding errors */
1910             quad[0].z = 0.001f + (float)j / 10.02f;
1911             quad[1].z = 0.001f + (float)j / 10.02f;
1912             quad[2].z = 0.001f + (float)j / 10.02f;
1913             quad[3].z = 0.001f + (float)j / 10.02f;
1914
1915             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1916             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
1917
1918             hr = IDirect3DDevice9_BeginScene(device);
1919             ok( hr == D3D_OK, "BeginScene returned failed (%08x)\n", hr);
1920
1921             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1922             ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1923
1924             hr = IDirect3DDevice9_EndScene(device);
1925             ok(hr == D3D_OK, "EndScene failed (%08x)\n", hr);
1926
1927             /* As the red and green component are the result of blending use 5% tolerance on the expected value */
1928             color = getPixelColor(device, 128, 240);
1929             ok(color_match(color, test_data[i].color[j], 13),
1930                 "fog vs%i ps%i fvm%i ftm%i %d: got color %08x, expected %08x +-5%%\n",
1931                 test_data[i].vshader, test_data[i].pshader, test_data[i].vfog, test_data[i].tfog, j, color, test_data[i].color[j]);
1932
1933             IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1934         }
1935     }
1936
1937     /* reset states */
1938     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
1939     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1940     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1941     ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1942     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1943     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1944     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
1945     ok(hr == D3D_OK, "Turning off fog calculations failed (%08x)\n", hr);
1946
1947     IDirect3DVertexShader9_Release(vertex_shader[1]);
1948     IDirect3DVertexShader9_Release(vertex_shader[2]);
1949     IDirect3DPixelShader9_Release(pixel_shader[1]);
1950     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1951 }
1952
1953 static void generate_bumpmap_textures(IDirect3DDevice9 *device) {
1954     unsigned int i, x, y;
1955     HRESULT hr;
1956     IDirect3DTexture9 *texture[2] = {NULL, NULL};
1957     D3DLOCKED_RECT locked_rect;
1958
1959     /* Generate the textures */
1960     for(i=0; i<2; i++)
1961     {
1962         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, i?D3DFMT_A8R8G8B8:D3DFMT_V8U8,
1963                                             D3DPOOL_MANAGED, &texture[i], NULL);
1964         ok(SUCCEEDED(hr), "CreateTexture failed (0x%08x)\n", hr);
1965
1966         hr = IDirect3DTexture9_LockRect(texture[i], 0, &locked_rect, NULL, 0);
1967         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1968         for (y = 0; y < 128; ++y)
1969         {
1970             if(i)
1971             { /* Set up black texture with 2x2 texel white spot in the middle */
1972                 DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1973                 for (x = 0; x < 128; ++x)
1974                 {
1975                     if(y>62 && y<66 && x>62 && x<66)
1976                         *ptr++ = 0xffffffff;
1977                     else
1978                         *ptr++ = 0xff000000;
1979                 }
1980             }
1981             else
1982             { /* Set up a displacement map which points away from the center parallel to the closest axis.
1983                * (if multiplied with bumpenvmat)
1984               */
1985                 WORD *ptr = (WORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1986                 for (x = 0; x < 128; ++x)
1987                 {
1988                     if(abs(x-64)>abs(y-64))
1989                     {
1990                         if(x < 64)
1991                             *ptr++ = 0xc000;
1992                         else
1993                             *ptr++ = 0x4000;
1994                     }
1995                     else
1996                     {
1997                         if(y < 64)
1998                             *ptr++ = 0x0040;
1999                         else
2000                             *ptr++ = 0x00c0;
2001                     }
2002                 }
2003             }
2004         }
2005         hr = IDirect3DTexture9_UnlockRect(texture[i], 0);
2006         ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
2007
2008         hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture[i]);
2009         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
2010
2011         /* Disable texture filtering */
2012         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MINFILTER, D3DTEXF_POINT);
2013         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
2014         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
2015         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
2016
2017         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
2018         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU failed (0x%08x)\n", hr);
2019         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
2020         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV failed (0x%08x)\n", hr);
2021     }
2022 }
2023
2024 /* test the behavior of the texbem instruction
2025  * with normal 2D and projective 2D textures
2026  */
2027 static void texbem_test(IDirect3DDevice9 *device)
2028 {
2029     HRESULT hr;
2030     DWORD color;
2031     int i;
2032
2033     static const DWORD pixel_shader_code[] = {
2034         0xffff0101,                         /* ps_1_1*/
2035         0x00000042, 0xb00f0000,             /* tex t0*/
2036         0x00000043, 0xb00f0001, 0xb0e40000, /* texbem t1, t0*/
2037         0x00000001, 0x800f0000, 0xb0e40001, /* mov r0, t1*/
2038         0x0000ffff
2039     };
2040     static const DWORD double_texbem_code[] =  {
2041         0xffff0103,                                         /* ps_1_3           */
2042         0x00000042, 0xb00f0000,                             /* tex t0           */
2043         0x00000043, 0xb00f0001, 0xb0e40000,                 /* texbem t1, t0    */
2044         0x00000042, 0xb00f0002,                             /* tex t2           */
2045         0x00000043, 0xb00f0003, 0xb0e40002,                 /* texbem t3, t2    */
2046         0x00000002, 0x800f0000, 0xb0e40001, 0xb0e40003,     /* add r0, t1, t3   */
2047         0x0000ffff                                          /* end              */
2048     };
2049
2050
2051     static const float quad[][7] = {
2052         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f},
2053         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f},
2054         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 1.0f, 0.0f},
2055         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 1.0f, 1.0f},
2056     };
2057     static const float quad_proj[][9] = {
2058         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f,   0.0f,   0.0f, 0.0f, 128.0f},
2059         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f,   0.0f, 128.0f, 0.0f, 128.0f},
2060         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 128.0f,   0.0f, 0.0f, 128.0f},
2061         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 128.0f, 128.0f, 0.0f, 128.0f},
2062     };
2063
2064     static const D3DVERTEXELEMENT9 decl_elements[][4] = { {
2065         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2066         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
2067         {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
2068         D3DDECL_END()
2069     },{
2070         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2071         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
2072         {0, 20, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
2073         D3DDECL_END()
2074     } };
2075
2076     /* use asymmetric matrix to test loading */
2077     float bumpenvmat[4] = {0.0,0.5,-0.5,0.0};
2078
2079     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
2080     IDirect3DPixelShader9       *pixel_shader       = NULL;
2081     IDirect3DTexture9           *texture            = NULL, *texture1, *texture2;
2082     D3DLOCKED_RECT locked_rect;
2083
2084     generate_bumpmap_textures(device);
2085
2086     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
2087     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
2088     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
2089     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
2090     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
2091
2092     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
2093     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
2094
2095     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
2096     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
2097
2098     for(i=0; i<2; i++)
2099     {
2100         if(i)
2101         {
2102             hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4|D3DTTFF_PROJECTED);
2103             ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
2104         }
2105
2106         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements[i], &vertex_declaration);
2107         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
2108         hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
2109         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
2110
2111         hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader);
2112         ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
2113         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader);
2114         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
2115
2116         hr = IDirect3DDevice9_BeginScene(device);
2117         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
2118
2119         if(!i)
2120             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
2121         else
2122             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad_proj[0], sizeof(quad_proj[0]));
2123         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
2124
2125         hr = IDirect3DDevice9_EndScene(device);
2126         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
2127
2128         color = getPixelColor(device, 320-32, 240);
2129         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2130         color = getPixelColor(device, 320+32, 240);
2131         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2132         color = getPixelColor(device, 320, 240-32);
2133         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2134         color = getPixelColor(device, 320, 240+32);
2135         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2136
2137         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2138         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2139
2140         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
2141         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
2142         IDirect3DPixelShader9_Release(pixel_shader);
2143
2144         hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2145         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
2146         IDirect3DVertexDeclaration9_Release(vertex_declaration);
2147     }
2148
2149     /* clean up */
2150     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
2151     ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
2152
2153     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
2154     ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
2155
2156     for(i=0; i<2; i++)
2157     {
2158         hr = IDirect3DDevice9_GetTexture(device, i, (IDirect3DBaseTexture9 **) &texture);
2159         ok(SUCCEEDED(hr), "IDirect3DDevice9_GetTexture failed (0x%08x)\n", hr);
2160         IDirect3DTexture9_Release(texture); /* For the GetTexture */
2161         hr = IDirect3DDevice9_SetTexture(device, i, NULL);
2162         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
2163         IDirect3DTexture9_Release(texture);
2164     }
2165
2166     /* Test double texbem */
2167     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_V8U8, D3DPOOL_MANAGED, &texture, NULL);
2168     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed (0x%08x)\n", hr);
2169     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_V8U8, D3DPOOL_MANAGED, &texture1, NULL);
2170     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed (0x%08x)\n", hr);
2171     hr = IDirect3DDevice9_CreateTexture(device, 8, 8, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture2, NULL);
2172     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed (0x%08x)\n", hr);
2173     hr = IDirect3DDevice9_CreatePixelShader(device, double_texbem_code, &pixel_shader);
2174     ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
2175
2176     hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
2177     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
2178     ((signed char *) locked_rect.pBits)[0] = (-1.0 / 8.0) * 127;
2179     ((signed char *) locked_rect.pBits)[1] = ( 1.0 / 8.0) * 127;
2180
2181     hr = IDirect3DTexture9_UnlockRect(texture, 0);
2182     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
2183
2184     hr = IDirect3DTexture9_LockRect(texture1, 0, &locked_rect, NULL, 0);
2185     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
2186     ((signed char *) locked_rect.pBits)[0] = (-2.0 / 8.0) * 127;
2187     ((signed char *) locked_rect.pBits)[1] = (-4.0 / 8.0) * 127;
2188     hr = IDirect3DTexture9_UnlockRect(texture1, 0);
2189     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
2190
2191     {
2192         /* Some data without any meaning, just to have an 8x8 array to see which element is picked */
2193 #define tex  0x00ff0000
2194 #define tex1 0x0000ff00
2195 #define origin 0x000000ff
2196         static const DWORD pixel_data[] = {
2197             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
2198             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
2199             0x000000ff, tex1      , 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
2200             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
2201             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, origin,     0x000000ff, tex       , 0x000000ff,
2202             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
2203             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
2204             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
2205         };
2206 #undef tex1
2207 #undef tex2
2208 #undef origin
2209
2210         hr = IDirect3DTexture9_LockRect(texture2, 0, &locked_rect, NULL, 0);
2211         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
2212         for(i = 0; i < 8; i++) {
2213             memcpy(((char *) locked_rect.pBits) + i * locked_rect.Pitch, pixel_data + 8 * i, 8 * sizeof(DWORD));
2214         }
2215         hr = IDirect3DTexture9_UnlockRect(texture2, 0);
2216         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
2217     }
2218
2219     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
2220     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2221     hr = IDirect3DDevice9_SetTexture(device, 1, (IDirect3DBaseTexture9 *) texture2);
2222     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2223     hr = IDirect3DDevice9_SetTexture(device, 2, (IDirect3DBaseTexture9 *) texture1);
2224     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2225     hr = IDirect3DDevice9_SetTexture(device, 3, (IDirect3DBaseTexture9 *) texture2);
2226     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2227     hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader);
2228     ok(SUCCEEDED(hr), "Direct3DDevice9_SetPixelShader failed (0x%08x)\n", hr);
2229     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX4);
2230     ok(SUCCEEDED(hr), "Direct3DDevice9_SetPixelShader failed (0x%08x)\n", hr);
2231
2232     bumpenvmat[0] =-1.0;  bumpenvmat[2] =  2.0;
2233     bumpenvmat[1] = 0.0;  bumpenvmat[3] =  0.0;
2234     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
2235     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2236     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
2237     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2238     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
2239     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2240     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
2241     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2242
2243     bumpenvmat[0] = 1.5; bumpenvmat[2] =  0.0;
2244     bumpenvmat[1] = 0.0; bumpenvmat[3] =  0.5;
2245     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
2246     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2247     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
2248     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2249     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
2250     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2251     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
2252     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2253
2254     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
2255     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2256     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
2257     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2258     hr = IDirect3DDevice9_SetSamplerState(device, 1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
2259     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2260     hr = IDirect3DDevice9_SetSamplerState(device, 1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
2261     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2262     hr = IDirect3DDevice9_SetSamplerState(device, 2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
2263     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2264     hr = IDirect3DDevice9_SetSamplerState(device, 2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
2265     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2266     hr = IDirect3DDevice9_SetSamplerState(device, 3, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
2267     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2268     hr = IDirect3DDevice9_SetSamplerState(device, 3, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
2269     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2270
2271     hr = IDirect3DDevice9_BeginScene(device);
2272     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
2273     if(SUCCEEDED(hr)) {
2274         static const float double_quad[] = {
2275             -1.0,   -1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
2276              1.0,   -1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
2277             -1.0,    1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
2278              1.0,    1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
2279         };
2280
2281         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, double_quad, sizeof(float) * 11);
2282         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
2283         hr = IDirect3DDevice9_EndScene(device);
2284         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
2285     }
2286     color = getPixelColor(device, 320, 240);
2287     ok(color == 0x00ffff00, "double texbem failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
2288
2289     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
2290     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2291     hr = IDirect3DDevice9_SetTexture(device, 1, NULL);
2292     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2293     hr = IDirect3DDevice9_SetTexture(device, 2, NULL);
2294     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2295     hr = IDirect3DDevice9_SetTexture(device, 3, NULL);
2296     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2297     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
2298     ok(SUCCEEDED(hr), "Direct3DDevice9_SetPixelShader failed (0x%08x)\n", hr);
2299
2300     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2301     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2302
2303     IDirect3DPixelShader9_Release(pixel_shader);
2304     IDirect3DTexture9_Release(texture);
2305     IDirect3DTexture9_Release(texture1);
2306     IDirect3DTexture9_Release(texture2);
2307 }
2308
2309 static void z_range_test(IDirect3DDevice9 *device)
2310 {
2311     const struct vertex quad[] =
2312     {
2313         {-1.0f,  0.0f,   1.1f,                          0xffff0000},
2314         {-1.0f,  1.0f,   1.1f,                          0xffff0000},
2315         { 1.0f,  0.0f,  -1.1f,                          0xffff0000},
2316         { 1.0f,  1.0f,  -1.1f,                          0xffff0000},
2317     };
2318     const struct vertex quad2[] =
2319     {
2320         {-1.0f,  0.0f,   1.1f,                          0xff0000ff},
2321         {-1.0f,  1.0f,   1.1f,                          0xff0000ff},
2322         { 1.0f,  0.0f,  -1.1f,                          0xff0000ff},
2323         { 1.0f,  1.0f,  -1.1f,                          0xff0000ff},
2324     };
2325
2326     const struct tvertex quad3[] =
2327     {
2328         {    0,   240,   1.1f,  1.0,                    0xffffff00},
2329         {    0,   480,   1.1f,  1.0,                    0xffffff00},
2330         {  640,   240,  -1.1f,  1.0,                    0xffffff00},
2331         {  640,   480,  -1.1f,  1.0,                    0xffffff00},
2332     };
2333     const struct tvertex quad4[] =
2334     {
2335         {    0,   240,   1.1f,  1.0,                    0xff00ff00},
2336         {    0,   480,   1.1f,  1.0,                    0xff00ff00},
2337         {  640,   240,  -1.1f,  1.0,                    0xff00ff00},
2338         {  640,   480,  -1.1f,  1.0,                    0xff00ff00},
2339     };
2340     HRESULT hr;
2341     DWORD color;
2342     IDirect3DVertexShader9 *shader;
2343     IDirect3DVertexDeclaration9 *decl;
2344     D3DCAPS9 caps;
2345     const DWORD shader_code[] = {
2346         0xfffe0101,                                     /* vs_1_1           */
2347         0x0000001f, 0x80000000, 0x900f0000,             /* dcl_position v0  */
2348         0x00000001, 0xc00f0000, 0x90e40000,             /* mov oPos, v0     */
2349         0x00000001, 0xd00f0000, 0xa0e40000,             /* mov oD0, c0      */
2350         0x0000ffff                                      /* end              */
2351     };
2352     static const D3DVERTEXELEMENT9 decl_elements[] = {
2353         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2354         D3DDECL_END()
2355     };
2356
2357     IDirect3DDevice9_GetDeviceCaps(device, &caps);
2358
2359     /* Does the Present clear the depth stencil? Clear the depth buffer with some value != 0,
2360      * then call Present. Then clear the color buffer to make sure it has some defined content
2361      * after the Present with D3DSWAPEFFECT_DISCARD. After that draw a plane that is somewhere cut
2362      * by the depth value.
2363      */
2364     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.75, 0);
2365     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
2366     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2367     ok(SUCCEEDED(hr), "IDirect3DDevice9_Present returned %#x.\n", hr);
2368     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4, 0);
2369     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
2370
2371     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, TRUE);
2372     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2373     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
2374     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2375     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
2376     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2377     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
2378     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2379     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
2380     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
2381
2382     hr = IDirect3DDevice9_BeginScene(device);
2383     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2384     if(hr == D3D_OK)
2385     {
2386         /* Test the untransformed vertex path */
2387         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
2388         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2389         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS);
2390         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2391         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad2, sizeof(quad2[0]));
2392         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2393
2394         /* Test the transformed vertex path */
2395         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2396         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
2397
2398         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad4, sizeof(quad4[0]));
2399         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2400         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
2401         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2402         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad3, sizeof(quad3[0]));
2403         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2404
2405         hr = IDirect3DDevice9_EndScene(device);
2406         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2407     }
2408
2409     /* Do not test the exact corner pixels, but go pretty close to them */
2410
2411     /* Clipped because z > 1.0 */
2412     color = getPixelColor(device, 28, 238);
2413     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2414     color = getPixelColor(device, 28, 241);
2415     if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_CLIPTLVERTS)
2416     {
2417         ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2418     }
2419     else
2420     {
2421         ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
2422     }
2423
2424     /* Not clipped, > z buffer clear value(0.75) */
2425     color = getPixelColor(device, 31, 238);
2426     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2427     color = getPixelColor(device, 31, 241);
2428     ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
2429     color = getPixelColor(device, 100, 238);
2430     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2431     color = getPixelColor(device, 100, 241);
2432     ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
2433
2434     /* Not clipped, < z buffer clear value */
2435     color = getPixelColor(device, 104, 238);
2436     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2437     color = getPixelColor(device, 104, 241);
2438     ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color);
2439     color = getPixelColor(device, 318, 238);
2440     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2441     color = getPixelColor(device, 318, 241);
2442     ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color);
2443
2444     /* Clipped because z < 0.0 */
2445     color = getPixelColor(device, 321, 238);
2446     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2447     color = getPixelColor(device, 321, 241);
2448     if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_CLIPTLVERTS)
2449     {
2450         ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2451     }
2452     else
2453     {
2454         ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2455     }
2456
2457     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2458     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2459
2460     /* Test the shader path */
2461     if (caps.VertexShaderVersion < D3DVS_VERSION(1, 1)) {
2462         skip("Vertex shaders not supported\n");
2463         goto out;
2464     }
2465     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
2466     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
2467     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
2468     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
2469
2470     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4, 0);
2471
2472     IDirect3DDevice9_SetVertexDeclaration(device, decl);
2473     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
2474     IDirect3DDevice9_SetVertexShader(device, shader);
2475     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
2476
2477     hr = IDirect3DDevice9_BeginScene(device);
2478     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2479     if(hr == D3D_OK)
2480     {
2481         float colorf[] = {1.0, 0.0, 0.0, 1.0};
2482         float colorf2[] = {0.0, 0.0, 1.0, 1.0};
2483         IDirect3DDevice9_SetVertexShaderConstantF(device, 0, colorf, 1);
2484         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
2485         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2486         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS);
2487         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2488         IDirect3DDevice9_SetVertexShaderConstantF(device, 0, colorf2, 1);
2489         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad2, sizeof(quad2[0]));
2490         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2491
2492         hr = IDirect3DDevice9_EndScene(device);
2493         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2494     }
2495
2496     IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2497     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
2498     IDirect3DDevice9_SetVertexShader(device, NULL);
2499     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
2500
2501     IDirect3DVertexDeclaration9_Release(decl);
2502     IDirect3DVertexShader9_Release(shader);
2503
2504     /* Z < 1.0 */
2505     color = getPixelColor(device, 28, 238);
2506     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2507
2508     /* 1.0 < z < 0.75 */
2509     color = getPixelColor(device, 31, 238);
2510     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2511     color = getPixelColor(device, 100, 238);
2512     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2513
2514     /* 0.75 < z < 0.0 */
2515     color = getPixelColor(device, 104, 238);
2516     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2517     color = getPixelColor(device, 318, 238);
2518     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2519
2520     /* 0.0 < z */
2521     color = getPixelColor(device, 321, 238);
2522     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2523
2524     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2525     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2526
2527     out:
2528     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
2529     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2530     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
2531     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2532     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
2533     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2534 }
2535
2536 static void fill_surface(IDirect3DSurface9 *surface, DWORD color)
2537 {
2538     D3DSURFACE_DESC desc;
2539     D3DLOCKED_RECT l;
2540     HRESULT hr;
2541     unsigned int x, y;
2542     DWORD *mem;
2543
2544     memset(&desc, 0, sizeof(desc));
2545     memset(&l, 0, sizeof(l));
2546     hr = IDirect3DSurface9_GetDesc(surface, &desc);
2547     ok(hr == D3D_OK, "IDirect3DSurface9_GetDesc failed with %08x\n", hr);
2548     hr = IDirect3DSurface9_LockRect(surface, &l, NULL, 0);
2549     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed with %08x\n", hr);
2550     if(FAILED(hr)) return;
2551
2552     for(y = 0; y < desc.Height; y++)
2553     {
2554         mem = (DWORD *) ((BYTE *) l.pBits + y * l.Pitch);
2555         for(x = 0; x < l.Pitch / sizeof(DWORD); x++)
2556         {
2557             mem[x] = color;
2558         }
2559     }
2560     hr = IDirect3DSurface9_UnlockRect(surface);
2561     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed with %08x\n", hr);
2562 }
2563
2564 /* This tests a variety of possible StretchRect() situations */
2565 static void stretchrect_test(IDirect3DDevice9 *device)
2566 {
2567     HRESULT hr;
2568     IDirect3DTexture9 *tex_rt32 = NULL, *tex_rt64 = NULL, *tex_rt_dest64 = NULL, *tex_rt_dest640_480 = NULL;
2569     IDirect3DSurface9 *surf_tex_rt32 = NULL, *surf_tex_rt64 = NULL, *surf_tex_rt_dest64 = NULL, *surf_tex_rt_dest640_480 = NULL;
2570     IDirect3DTexture9 *tex32 = NULL, *tex64 = NULL, *tex_dest64 = NULL;
2571     IDirect3DSurface9 *surf_tex32 = NULL, *surf_tex64 = NULL, *surf_tex_dest64 = NULL;
2572     IDirect3DSurface9 *surf_rt32 = NULL, *surf_rt64 = NULL, *surf_rt_dest64 = NULL;
2573     IDirect3DSurface9 *surf_offscreen32 = NULL, *surf_offscreen64 = NULL, *surf_offscreen_dest64 = NULL;
2574     IDirect3DSurface9 *surf_temp32 = NULL, *surf_temp64 = NULL;
2575     IDirect3DSurface9 *orig_rt = NULL;
2576     IDirect3DSurface9 *backbuffer = NULL;
2577     DWORD color;
2578
2579     RECT src_rect64 = {0, 0, 64, 64};
2580     RECT src_rect64_flipy = {0, 64, 64, 0};
2581     RECT dst_rect64 = {0, 0, 64, 64};
2582     RECT dst_rect64_flipy = {0, 64, 64, 0};
2583
2584     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &orig_rt);
2585     ok(hr == D3D_OK, "Can't get render target, hr = %08x\n", hr);
2586     if(!orig_rt) {
2587         goto out;
2588     }
2589
2590     /* Create our temporary surfaces in system memory */
2591     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf_temp32, NULL);
2592     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2593     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf_temp64, NULL);
2594     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2595
2596     /* Create offscreen plain surfaces in D3DPOOL_DEFAULT */
2597     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_offscreen32, NULL);
2598     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2599     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_offscreen64, NULL);
2600     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2601     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_offscreen_dest64, NULL);
2602     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2603
2604     /* Create render target surfaces */
2605     hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &surf_rt32, NULL );
2606     ok(hr == D3D_OK, "Creating the render target surface failed with %08x\n", hr);
2607     hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &surf_rt64, NULL );
2608     ok(hr == D3D_OK, "Creating the render target surface failed with %08x\n", hr);
2609     hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &surf_rt_dest64, NULL );
2610     ok(hr == D3D_OK, "Creating the render target surface failed with %08x\n", hr);
2611     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
2612     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
2613
2614     /* Create render target textures */
2615     hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt32, NULL);
2616     ok(hr == D3D_OK, "Creating the render target texture failed with %08x\n", hr);
2617     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt64, NULL);
2618     ok(hr == D3D_OK, "Creating the render target texture failed with %08x\n", hr);
2619     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt_dest64, NULL);
2620     ok(hr == D3D_OK, "Creating the render target texture failed with %08x\n", hr);
2621     hr = IDirect3DDevice9_CreateTexture(device, 640, 480, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt_dest640_480, NULL);
2622     ok(hr == D3D_OK, "Creating the render target texture failed with %08x\n", hr);
2623     if (tex_rt32) {
2624         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt32, 0, &surf_tex_rt32);
2625         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2626     }
2627     if (tex_rt64) {
2628         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt64, 0, &surf_tex_rt64);
2629         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2630     }
2631     if (tex_rt_dest64) {
2632         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt_dest64, 0, &surf_tex_rt_dest64);
2633         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2634     }
2635     if (tex_rt_dest64) {
2636         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt_dest640_480, 0, &surf_tex_rt_dest640_480);
2637         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2638     }
2639
2640     /* Create regular textures in D3DPOOL_DEFAULT */
2641     hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex32, NULL);
2642     ok(hr == D3D_OK, "Creating the regular texture failed with %08x\n", hr);
2643     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex64, NULL);
2644     ok(hr == D3D_OK, "Creating the regular texture failed with %08x\n", hr);
2645     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_dest64, NULL);
2646     ok(hr == D3D_OK, "Creating the regular texture failed with %08x\n", hr);
2647     if (tex32) {
2648         hr = IDirect3DTexture9_GetSurfaceLevel(tex32, 0, &surf_tex32);
2649         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2650     }
2651     if (tex64) {
2652         hr = IDirect3DTexture9_GetSurfaceLevel(tex64, 0, &surf_tex64);
2653         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2654     }
2655     if (tex_dest64) {
2656         hr = IDirect3DTexture9_GetSurfaceLevel(tex_dest64, 0, &surf_tex_dest64);
2657         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2658     }
2659
2660     /*********************************************************************
2661      * Tests for when the source parameter is an offscreen plain surface *
2662      *********************************************************************/
2663
2664     /* Fill the offscreen 64x64 surface with green */
2665     if (surf_offscreen64)
2666         fill_surface(surf_offscreen64, 0xff00ff00);
2667
2668     /* offscreenplain ==> offscreenplain, same size */
2669     if(surf_offscreen64 && surf_offscreen_dest64) {
2670         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_offscreen_dest64, NULL, 0);
2671         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2672
2673         if (hr == D3D_OK) {
2674             color = getPixelColorFromSurface(surf_offscreen_dest64, 32, 32);
2675             ok(color == 0xff00ff00, "StretchRect offscreen ==> offscreen same size failed: Got color 0x%08x, expected 0xff00ff00.\n", color);
2676         }
2677
2678         /* Blit without scaling */
2679         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64, surf_offscreen_dest64, &dst_rect64, 0);
2680         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2681
2682         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
2683         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64_flipy, surf_offscreen_dest64, &dst_rect64, 0);
2684         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2685
2686         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
2687         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64, surf_offscreen_dest64, &dst_rect64_flipy, 0);
2688         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2689     }
2690
2691     /* offscreenplain ==> rendertarget texture, same size */
2692     if(surf_offscreen64 && surf_tex_rt_dest64 && surf_temp64) {
2693         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_tex_rt_dest64, NULL, 0);
2694         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2695
2696         /* We can't lock rendertarget textures, so copy to our temp surface first */
2697         if (hr == D3D_OK) {
2698             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2699             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2700         }
2701
2702         if (hr == D3D_OK) {
2703             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2704             ok(color == 0xff00ff00, "StretchRect offscreen ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xff00ff00.\n", color);
2705         }
2706
2707         /* Blit without scaling */
2708         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64, surf_tex_rt_dest64, &dst_rect64, 0);
2709         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2710
2711         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
2712         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64_flipy, surf_tex_rt_dest64, &dst_rect64, 0);
2713         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2714
2715         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
2716         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64, surf_tex_rt_dest64, &dst_rect64_flipy, 0);
2717         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2718     }
2719
2720     /* offscreenplain ==> rendertarget surface, same size */
2721     if(surf_offscreen64 && surf_rt_dest64) {
2722         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_rt_dest64, NULL, 0);
2723         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2724
2725         if (hr == D3D_OK) {
2726             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2727             ok(color == 0xff00ff00, "StretchRect offscreen ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xff00ff00.\n", color);
2728         }
2729
2730         /* Blit without scaling */
2731         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64, surf_rt_dest64, &dst_rect64, 0);
2732         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2733
2734         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
2735         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64_flipy, surf_rt_dest64, &dst_rect64, 0);
2736         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2737
2738         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
2739         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64, surf_rt_dest64, &dst_rect64_flipy, 0);
2740         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2741     }
2742
2743     /* offscreenplain ==> texture, same size (should fail) */
2744     if(surf_offscreen64 && surf_tex_dest64) {
2745         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_tex_dest64, NULL, 0);
2746         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2747     }
2748
2749     /* Fill the smaller offscreen surface with red */
2750     fill_surface(surf_offscreen32, 0xffff0000);
2751
2752     /* offscreenplain ==> offscreenplain, scaling (should fail) */
2753     if(surf_offscreen32 && surf_offscreen64) {
2754         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_offscreen64, NULL, 0);
2755         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2756     }
2757
2758     /* offscreenplain ==> rendertarget texture, scaling */
2759     if(surf_offscreen32 && surf_tex_rt_dest64 && surf_temp64) {
2760         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_tex_rt_dest64, NULL, 0);
2761         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2762
2763         /* We can't lock rendertarget textures, so copy to our temp surface first */
2764         if (hr == D3D_OK) {
2765             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2766             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2767         }
2768
2769         if (hr == D3D_OK) {
2770             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2771             ok(color == 0xffff0000, "StretchRect offscreen ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2772         }
2773     }
2774
2775     /* offscreenplain ==> rendertarget surface, scaling */
2776     if(surf_offscreen32 && surf_rt_dest64) {
2777         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_rt_dest64, NULL, 0);
2778         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2779
2780         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2781         ok(color == 0xffff0000, "StretchRect offscreen ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2782     }
2783
2784     /* offscreenplain ==> texture, scaling (should fail) */
2785     if(surf_offscreen32 && surf_tex_dest64) {
2786         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_tex_dest64, NULL, 0);
2787         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2788     }
2789
2790     /************************************************************
2791      * Tests for when the source parameter is a regular texture *
2792      ************************************************************/
2793
2794     /* Fill the surface of the regular texture with blue */
2795     if (surf_tex64 && surf_temp64) {
2796         /* Can't fill the surf_tex directly because it's created in D3DPOOL_DEFAULT */
2797         fill_surface(surf_temp64, 0xff0000ff);
2798         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp64, NULL, surf_tex64, NULL);
2799         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
2800     }
2801
2802     /* texture ==> offscreenplain, same size */
2803     if(surf_tex64 && surf_offscreen64) {
2804         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_offscreen64, NULL, 0);
2805         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2806     }
2807
2808     /* texture ==> rendertarget texture, same size */
2809     if(surf_tex64 && surf_tex_rt_dest64 && surf_temp64) {
2810         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_tex_rt_dest64, NULL, 0);
2811         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2812
2813         /* We can't lock rendertarget textures, so copy to our temp surface first */
2814         if (hr == D3D_OK) {
2815             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2816             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2817         }
2818
2819         if (hr == D3D_OK) {
2820             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2821             ok(color == 0xff0000ff, "StretchRect texture ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xff0000ff.\n", color);
2822         }
2823
2824         /* Blit without scaling */
2825         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, &src_rect64, surf_tex_rt_dest64, &dst_rect64, 0);
2826         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2827
2828         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
2829         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, &src_rect64_flipy, surf_tex_rt_dest64, &dst_rect64, 0);
2830         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2831
2832         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
2833         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, &src_rect64, surf_tex_rt_dest64, &dst_rect64_flipy, 0);
2834         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2835     }
2836
2837     /* texture ==> rendertarget surface, same size */
2838     if(surf_tex64 && surf_rt_dest64) {
2839         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_rt_dest64, NULL, 0);
2840         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2841
2842         if (hr == D3D_OK) {
2843             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2844             ok(color == 0xff0000ff, "StretchRect texture ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xff0000ff.\n", color);
2845         }
2846
2847         /* Blit without scaling */
2848         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, &src_rect64, surf_rt_dest64, &dst_rect64, 0);
2849         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2850
2851         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
2852         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, &src_rect64_flipy, surf_rt_dest64, &dst_rect64, 0);
2853         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2854
2855         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
2856         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, &src_rect64, surf_rt_dest64, &dst_rect64_flipy, 0);
2857         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2858     }
2859
2860     /* texture ==> texture, same size (should fail) */
2861     if(surf_tex64 && surf_tex_dest64) {
2862         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_tex_dest64, NULL, 0);
2863         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2864     }
2865
2866     /* Fill the surface of the smaller regular texture with red */
2867     if (surf_tex32 && surf_temp32) {
2868         /* Can't fill the surf_tex directly because it's created in D3DPOOL_DEFAULT */
2869         fill_surface(surf_temp32, 0xffff0000);
2870         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp32, NULL, surf_tex32, NULL);
2871         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
2872     }
2873
2874     /* texture ==> offscreenplain, scaling (should fail) */
2875     if(surf_tex32 && surf_offscreen64) {
2876         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_offscreen64, NULL, 0);
2877         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2878     }
2879
2880     /* texture ==> rendertarget texture, scaling */
2881     if(surf_tex32 && surf_tex_rt_dest64 && surf_temp64) {
2882         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_tex_rt_dest64, NULL, 0);
2883         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2884
2885         /* We can't lock rendertarget textures, so copy to our temp surface first */
2886         if (hr == D3D_OK) {
2887             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2888             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2889         }
2890
2891         if (hr == D3D_OK) {
2892             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2893             ok(color == 0xffff0000, "StretchRect texture ==> rendertarget texture scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2894         }
2895     }
2896
2897     /* texture ==> rendertarget surface, scaling */
2898     if(surf_tex32 && surf_rt_dest64) {
2899         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_rt_dest64, NULL, 0);
2900         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2901
2902         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2903         ok(color == 0xffff0000, "StretchRect texture ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2904     }
2905
2906     /* texture ==> texture, scaling (should fail) */
2907     if(surf_tex32 && surf_tex_dest64) {
2908         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_tex_dest64, NULL, 0);
2909         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2910     }
2911
2912     /*****************************************************************
2913      * Tests for when the source parameter is a rendertarget texture *
2914      *****************************************************************/
2915
2916     /* Fill the surface of the rendertarget texture with white */
2917     if (surf_tex_rt64 && surf_temp64) {
2918         /* Can't fill the surf_tex_rt directly because it's created in D3DPOOL_DEFAULT */
2919         fill_surface(surf_temp64, 0xffffffff);
2920         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp64, NULL, surf_tex_rt64, NULL);
2921         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
2922     }
2923
2924     /* rendertarget texture ==> offscreenplain, same size */
2925     if(surf_tex_rt64 && surf_offscreen64) {
2926         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_offscreen64, NULL, 0);
2927         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2928     }
2929
2930     /* rendertarget texture ==> rendertarget texture, same size */
2931     if(surf_tex_rt64 && surf_tex_rt_dest64 && surf_temp64) {
2932         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_tex_rt_dest64, NULL, 0);
2933         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2934
2935         /* We can't lock rendertarget textures, so copy to our temp surface first */
2936         if (hr == D3D_OK) {
2937             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2938             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2939         }
2940
2941         if (hr == D3D_OK) {
2942             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2943             ok(color == 0xffffffff, "StretchRect rendertarget texture ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xffffffff.\n", color);
2944         }
2945
2946         /* Blit without scaling */
2947         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, &src_rect64, surf_tex_rt_dest64, &dst_rect64, 0);
2948         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2949
2950         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
2951         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, &src_rect64_flipy, surf_tex_rt_dest64, &dst_rect64, 0);
2952         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2953
2954         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
2955         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, &src_rect64, surf_tex_rt_dest64, &dst_rect64_flipy, 0);
2956         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2957     }
2958
2959     /* rendertarget texture ==> rendertarget surface, same size */
2960     if(surf_tex_rt64 && surf_rt_dest64) {
2961         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_rt_dest64, NULL, 0);
2962         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2963
2964         if (hr == D3D_OK) {
2965             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2966             ok(color == 0xffffffff, "StretchRect rendertarget texture ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xffffffff.\n", color);
2967         }
2968
2969         /* Blit without scaling */
2970         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, &src_rect64, surf_rt_dest64, &dst_rect64, 0);
2971         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2972
2973         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
2974         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, &src_rect64_flipy, surf_rt_dest64, &dst_rect64, 0);
2975         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2976
2977         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
2978         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, &src_rect64, surf_rt_dest64, &dst_rect64_flipy, 0);
2979         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2980     }
2981
2982     /* rendertarget texture ==> texture, same size (should fail) */
2983     if(surf_tex_rt64 && surf_tex_dest64) {
2984         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_tex_dest64, NULL, 0);
2985         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2986     }
2987
2988     /* Fill the surface of the smaller rendertarget texture with red */
2989     if (surf_tex_rt32 && surf_temp32) {
2990         /* Can't fill the surf_tex_rt directly because it's created in D3DPOOL_DEFAULT */
2991         fill_surface(surf_temp32, 0xffff0000);
2992         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp32, NULL, surf_tex_rt32, NULL);
2993         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
2994     }
2995
2996     /* rendertarget texture ==> offscreenplain, scaling (should fail) */
2997     if(surf_tex_rt32 && surf_offscreen64) {
2998         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_offscreen64, NULL, 0);
2999         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
3000     }
3001
3002     /* rendertarget texture ==> rendertarget texture, scaling */
3003     if(surf_tex_rt32 && surf_tex_rt_dest64 && surf_temp64) {
3004         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_tex_rt_dest64, NULL, 0);
3005         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3006
3007         /* We can't lock rendertarget textures, so copy to our temp surface first */
3008         if (hr == D3D_OK) {
3009             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
3010             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
3011         }
3012
3013         if (hr == D3D_OK) {
3014             color = getPixelColorFromSurface(surf_temp64, 48, 48);
3015             ok(color == 0xffff0000, "StretchRect rendertarget texture ==> rendertarget texture scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
3016         }
3017     }
3018
3019     /* rendertarget texture ==> rendertarget surface, scaling */
3020     if(surf_tex_rt32 && surf_rt_dest64) {
3021         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_rt_dest64, NULL, 0);
3022         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3023
3024         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
3025         ok(color == 0xffff0000, "StretchRect rendertarget texture ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
3026     }
3027
3028     /* rendertarget texture ==> texture, scaling (should fail) */
3029     if(surf_tex_rt32 && surf_tex_dest64) {
3030         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_tex_dest64, NULL, 0);
3031         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
3032     }
3033
3034     /*****************************************************************
3035      * Tests for when the source parameter is a rendertarget surface *
3036      *****************************************************************/
3037
3038     /* Fill the surface of the rendertarget surface with black */
3039     if (surf_rt64)
3040         fill_surface(surf_rt64, 0xff000000);
3041
3042     /* rendertarget texture ==> offscreenplain, same size */
3043     if(surf_rt64 && surf_offscreen64) {
3044         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_offscreen64, NULL, 0);
3045         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
3046     }
3047
3048     /* rendertarget surface ==> rendertarget texture, same size */
3049     if(surf_rt64 && surf_tex_rt_dest64 && surf_temp64) {
3050         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_tex_rt_dest64, NULL, 0);
3051         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3052
3053         /* We can't lock rendertarget textures, so copy to our temp surface first */
3054         if (hr == D3D_OK) {
3055             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
3056             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
3057         }
3058
3059         if (hr == D3D_OK) {
3060             color = getPixelColorFromSurface(surf_temp64, 32, 32);
3061             ok(color == 0xff000000, "StretchRect rendertarget surface ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xff000000.\n", color);
3062         }
3063
3064         /* Blit without scaling */
3065         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, &src_rect64, surf_tex_rt_dest64, &dst_rect64, 0);
3066         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3067
3068         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
3069         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, &src_rect64_flipy, surf_tex_rt_dest64, &dst_rect64, 0);
3070         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3071
3072         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
3073         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, &src_rect64, surf_tex_rt_dest64, &dst_rect64_flipy, 0);
3074         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3075     }
3076
3077     /* rendertarget surface ==> rendertarget surface, same size */
3078     if(surf_rt64 && surf_rt_dest64) {
3079         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_rt_dest64, NULL, 0);
3080         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3081
3082         if (hr == D3D_OK) {
3083             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
3084             ok(color == 0xff000000, "StretchRect rendertarget surface ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xff000000.\n", color);
3085         }
3086
3087         /* Blit without scaling */
3088         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, &src_rect64, surf_rt_dest64, &dst_rect64, 0);
3089         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3090
3091         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
3092         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, &src_rect64_flipy, surf_rt_dest64, &dst_rect64_flipy, 0);
3093         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3094
3095         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
3096         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, &src_rect64, surf_rt_dest64, &dst_rect64_flipy, 0);
3097         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3098     }
3099
3100     /* rendertarget surface ==> texture, same size (should fail) */
3101     if(surf_rt64 && surf_tex_dest64) {
3102         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_tex_dest64, NULL, 0);
3103         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
3104     }
3105
3106     /* Fill the surface of the smaller rendertarget texture with red */
3107     if (surf_rt32)
3108         fill_surface(surf_rt32, 0xffff0000);
3109
3110     /* rendertarget surface ==> offscreenplain, scaling (should fail) */
3111     if(surf_rt32 && surf_offscreen64) {
3112         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_offscreen64, NULL, 0);
3113         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
3114     }
3115
3116     /* rendertarget surface ==> rendertarget texture, scaling */
3117     if(surf_rt32 && surf_tex_rt_dest64 && surf_temp64) {
3118         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_tex_rt_dest64, NULL, 0);
3119         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3120
3121         /* We can't lock rendertarget textures, so copy to our temp surface first */
3122         if (hr == D3D_OK) {
3123             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
3124             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
3125         }
3126
3127         if (hr == D3D_OK) {
3128             color = getPixelColorFromSurface(surf_temp64, 48, 48);
3129             ok(color == 0xffff0000, "StretchRect rendertarget surface ==> rendertarget texture scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
3130         }
3131     }
3132
3133     /* rendertarget surface ==> rendertarget surface, scaling */
3134     if(surf_rt32 && surf_rt_dest64) {
3135         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_rt_dest64, NULL, 0);
3136         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3137
3138         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
3139         ok(color == 0xffff0000, "StretchRect rendertarget surface ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
3140     }
3141
3142     /* rendertarget surface ==> texture, scaling (should fail) */
3143     if(surf_rt32 && surf_tex_dest64) {
3144         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_tex_dest64, NULL, 0);
3145         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
3146     }
3147
3148     /* backbuffer ==> surface tests (no scaling) */
3149     if(backbuffer && surf_tex_rt_dest640_480)
3150     {
3151         RECT src_rect = {0, 0, 640, 480};
3152         RECT src_rect_flipy = {0, 480, 640, 0};
3153         RECT dst_rect = {0, 0, 640, 480};
3154         RECT dst_rect_flipy = {0, 480, 640, 0};
3155
3156         /* Blit with NULL rectangles */
3157         hr = IDirect3DDevice9_StretchRect(device, backbuffer, NULL, surf_tex_rt_dest640_480, NULL, 0);
3158         ok( hr == D3D_OK, "StretchRect backbuffer ==> texture same size failed:\n");
3159
3160         /* Blit without scaling */
3161         hr = IDirect3DDevice9_StretchRect(device, backbuffer, &src_rect, surf_tex_rt_dest640_480, &dst_rect, 0);
3162         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
3163
3164         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
3165         hr = IDirect3DDevice9_StretchRect(device, backbuffer, &src_rect_flipy, surf_tex_rt_dest640_480, &dst_rect, 0);
3166         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3167
3168         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
3169         hr = IDirect3DDevice9_StretchRect(device, backbuffer, &src_rect, surf_tex_rt_dest640_480, &dst_rect_flipy, 0);
3170         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3171     }
3172
3173     /* TODO: Test format conversions */
3174
3175
3176 out:
3177     /* Clean up */
3178     if (backbuffer)
3179         IDirect3DSurface9_Release(backbuffer);
3180     if (surf_rt32)
3181         IDirect3DSurface9_Release(surf_rt32);
3182     if (surf_rt64)
3183         IDirect3DSurface9_Release(surf_rt64);
3184     if (surf_rt_dest64)
3185         IDirect3DSurface9_Release(surf_rt_dest64);
3186     if (surf_temp32)
3187         IDirect3DSurface9_Release(surf_temp32);
3188     if (surf_temp64)
3189         IDirect3DSurface9_Release(surf_temp64);
3190     if (surf_offscreen32)
3191         IDirect3DSurface9_Release(surf_offscreen32);
3192     if (surf_offscreen64)
3193         IDirect3DSurface9_Release(surf_offscreen64);
3194     if (surf_offscreen_dest64)
3195         IDirect3DSurface9_Release(surf_offscreen_dest64);
3196
3197     if (tex_rt32) {
3198         if (surf_tex_rt32)
3199             IDirect3DSurface9_Release(surf_tex_rt32);
3200         IDirect3DTexture9_Release(tex_rt32);
3201     }
3202     if (tex_rt64) {
3203         if (surf_tex_rt64)
3204             IDirect3DSurface9_Release(surf_tex_rt64);
3205         IDirect3DTexture9_Release(tex_rt64);
3206     }
3207     if (tex_rt_dest64) {
3208         if (surf_tex_rt_dest64)
3209             IDirect3DSurface9_Release(surf_tex_rt_dest64);
3210         IDirect3DTexture9_Release(tex_rt_dest64);
3211     }
3212     if (tex_rt_dest640_480) {
3213         if (surf_tex_rt_dest640_480)
3214             IDirect3DSurface9_Release(surf_tex_rt_dest640_480);
3215         IDirect3DTexture9_Release(tex_rt_dest640_480);
3216     }
3217     if (tex32) {
3218         if (surf_tex32)
3219             IDirect3DSurface9_Release(surf_tex32);
3220         IDirect3DTexture9_Release(tex32);
3221     }
3222     if (tex64) {
3223         if (surf_tex64)
3224             IDirect3DSurface9_Release(surf_tex64);
3225         IDirect3DTexture9_Release(tex64);
3226     }
3227     if (tex_dest64) {
3228         if (surf_tex_dest64)
3229             IDirect3DSurface9_Release(surf_tex_dest64);
3230         IDirect3DTexture9_Release(tex_dest64);
3231     }
3232
3233     if (orig_rt) {
3234         hr = IDirect3DDevice9_SetRenderTarget(device, 0, orig_rt);
3235         ok(hr == D3D_OK, "IDirect3DSetRenderTarget failed with %08x\n", hr);
3236         IDirect3DSurface9_Release(orig_rt);
3237     }
3238 }
3239
3240 static void maxmip_test(IDirect3DDevice9 *device)
3241 {
3242     IDirect3DTexture9 *texture = NULL;
3243     IDirect3DSurface9 *surface = NULL;
3244     HRESULT hr;
3245     DWORD color;
3246     static const struct
3247     {
3248         struct
3249         {
3250             float x, y, z;
3251             float s, t;
3252         }
3253         v[4];
3254     }
3255     quads[] =
3256     {
3257         {{
3258             {-1.0, -1.0,  0.0,  0.0,  0.0},
3259             {-1.0,  0.0,  0.0,  0.0,  1.0},
3260             { 0.0, -1.0,  0.0,  1.0,  0.0},
3261             { 0.0,  0.0,  0.0,  1.0,  1.0},
3262         }},
3263         {{
3264             { 0.0, -1.0,  0.0,  0.0,  0.0},
3265             { 0.0,  0.0,  0.0,  0.0,  1.0},
3266             { 1.0, -1.0,  0.0,  1.0,  0.0},
3267             { 1.0,  0.0,  0.0,  1.0,  1.0},
3268         }},
3269         {{
3270             { 0.0,  0.0,  0.0,  0.0,  0.0},
3271             { 0.0,  1.0,  0.0,  0.0,  1.0},
3272             { 1.0,  0.0,  0.0,  1.0,  0.0},
3273             { 1.0,  1.0,  0.0,  1.0,  1.0},
3274         }},
3275         {{
3276             {-1.0,  0.0,  0.0,  0.0,  0.0},
3277             {-1.0,  1.0,  0.0,  0.0,  1.0},
3278             { 0.0,  0.0,  0.0,  1.0,  0.0},
3279             { 0.0,  1.0,  0.0,  1.0,  1.0},
3280         }},
3281     };
3282
3283     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
3284                                         &texture, NULL);
3285     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
3286     if(!texture)
3287     {
3288         skip("Failed to create test texture\n");
3289         return;
3290     }
3291
3292     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
3293     ok(SUCCEEDED(hr), "IDirect3DTexture9_GetSurfaceLevel returned %#x.\n", hr);
3294     fill_surface(surface, 0xffff0000);
3295     IDirect3DSurface9_Release(surface);
3296     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface);
3297     ok(SUCCEEDED(hr), "IDirect3DTexture9_GetSurfaceLevel returned %#x.\n", hr);
3298     fill_surface(surface, 0xff00ff00);
3299     IDirect3DSurface9_Release(surface);
3300     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
3301     ok(SUCCEEDED(hr), "IDirect3DTexture9_GetSurfaceLevel returned %#x.\n", hr);
3302     fill_surface(surface, 0xff0000ff);
3303     IDirect3DSurface9_Release(surface);
3304
3305     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3306     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3307     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3308     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3309
3310     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
3311     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3312
3313     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
3314     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3315
3316     hr = IDirect3DDevice9_BeginScene(device);
3317     if(SUCCEEDED(hr))
3318     {
3319         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
3320         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3321         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[0], sizeof(*quads->v));
3322         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3323
3324         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
3325         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3326         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[1], sizeof(*quads->v));
3327         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3328
3329         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
3330         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3331         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[2], sizeof(*quads->v));
3332         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3333
3334         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
3335         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3336         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[3], sizeof(*quads->v));
3337         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3338         hr = IDirect3DDevice9_EndScene(device);
3339         ok(SUCCEEDED(hr), "EndScene failed (%08x)\n", hr);
3340     }
3341
3342     /* With mipmapping disabled, the max mip level is ignored, only level 0 is used */
3343     color = getPixelColor(device, 160, 360);
3344     ok(color == 0x00ff0000, "MaxMip 0, no mipfilter has color 0x%08x.\n", color);
3345     color = getPixelColor(device, 480, 360);
3346     ok(color == 0x00ff0000, "MaxMip 1, no mipfilter has color 0x%08x.\n", color);
3347     color = getPixelColor(device, 480, 120);
3348     ok(color == 0x00ff0000, "MaxMip 2, no mipfilter has color 0x%08x.\n", color);
3349     color = getPixelColor(device, 160, 120);
3350     ok(color == 0x00ff0000, "MaxMip 3, no mipfilter has color 0x%08x.\n", color);
3351     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3352     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
3353
3354     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
3355     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3356
3357     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
3358     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3359
3360     hr = IDirect3DDevice9_BeginScene(device);
3361     if(SUCCEEDED(hr))
3362     {
3363         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
3364         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3365         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[0], sizeof(*quads->v));
3366         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3367
3368         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
3369         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3370         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[1], sizeof(*quads->v));
3371         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3372
3373         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
3374         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3375         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[2], sizeof(*quads->v));
3376         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3377
3378         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
3379         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3380         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[3], sizeof(*quads->v));
3381         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3382         hr = IDirect3DDevice9_EndScene(device);
3383         ok(SUCCEEDED(hr), "IDirect3DDevice9_EndScene returned %#x.\n", hr);
3384     }
3385
3386     /* Max Mip level 0-2 sample from the specified texture level, Max Mip
3387      * level 3 (> levels in texture) samples from the highest level in the
3388      * texture (level 2). */
3389     color = getPixelColor(device, 160, 360);
3390     ok(color == 0x00ff0000, "MaxMip 0, point mipfilter has color 0x%08x.\n", color);
3391     color = getPixelColor(device, 480, 360);
3392     ok(color == 0x0000ff00, "MaxMip 1, point mipfilter has color 0x%08x.\n", color);
3393     color = getPixelColor(device, 480, 120);
3394     ok(color == 0x000000ff, "MaxMip 2, point mipfilter has color 0x%08x.\n", color);
3395     color = getPixelColor(device, 160, 120);
3396     ok(color == 0x000000ff, "MaxMip 3, point mipfilter has color 0x%08x.\n", color);
3397     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3398     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
3399
3400     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
3401     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3402
3403     hr = IDirect3DDevice9_BeginScene(device);
3404     if(SUCCEEDED(hr))
3405     {
3406         DWORD ret;
3407
3408         /* Mipmapping OFF, LOD level smaller than MAXMIPLEVEL. LOD level limits */
3409         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
3410         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3411         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
3412         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3413         ret = IDirect3DTexture9_SetLOD(texture, 1);
3414         ok(ret == 0, "IDirect3DTexture9_SetLOD returned %u, expected 0\n", ret);
3415         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[0], sizeof(*quads->v));
3416         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3417
3418         /* Mipmapping ON, LOD level smaller than max mip level. LOD level limits */
3419         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
3420         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3421         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
3422         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3423         ret = IDirect3DTexture9_SetLOD(texture, 2);
3424         ok(ret == 1, "IDirect3DTexture9_SetLOD returned %u, expected 1\n", ret);
3425         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[1], sizeof(*quads->v));
3426         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3427
3428         /* Mipmapping ON, LOD level bigger than max mip level. MAXMIPLEVEL limits */
3429         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
3430         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3431         ret = IDirect3DTexture9_SetLOD(texture, 1);
3432         ok(ret == 2, "IDirect3DTexture9_SetLOD returned %u, expected 2\n", ret);
3433         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[2], sizeof(*quads->v));
3434         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3435
3436         /* Mipmapping OFF, LOD level bigger than max mip level. LOD level limits */
3437         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
3438         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3439         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
3440         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3441         ret = IDirect3DTexture9_SetLOD(texture, 1);
3442         ok(ret == 1, "IDirect3DTexture9_SetLOD returned %u, expected 1\n", ret);
3443         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[3], sizeof(*quads->v));
3444         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3445         hr = IDirect3DDevice9_EndScene(device);
3446         ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
3447     }
3448
3449     /* Max Mip level 0-2 sample from the specified texture level, Max Mip
3450      * level 3 (> levels in texture) samples from the highest level in the
3451      * texture (level 2). */
3452     color = getPixelColor(device, 160, 360);
3453     ok(color == 0x0000ff00, "MaxMip 0, LOD 1, none mipfilter has color 0x%08x.\n", color);
3454     color = getPixelColor(device, 480, 360);
3455     ok(color == 0x000000ff, "MaxMip 1, LOD 2, point mipfilter has color 0x%08x.\n", color);
3456     color = getPixelColor(device, 480, 120);
3457     ok(color == 0x000000ff, "MaxMip 2, LOD 1, point mipfilter has color 0x%08x.\n", color);
3458     color = getPixelColor(device, 160, 120);
3459     ok(color == 0x0000ff00, "MaxMip 2, LOD 1, none mipfilter has color 0x%08x.\n", color);
3460
3461     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3462     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
3463
3464     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3465     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3466     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
3467     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3468     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
3469     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3470     IDirect3DTexture9_Release(texture);
3471 }
3472
3473 static void release_buffer_test(IDirect3DDevice9 *device)
3474 {
3475     IDirect3DVertexBuffer9 *vb = NULL;
3476     IDirect3DIndexBuffer9 *ib = NULL;
3477     HRESULT hr;
3478     BYTE *data;
3479     LONG ref;
3480
3481     static const struct vertex quad[] = {
3482         {-1.0,      -1.0,       0.1,        0xffff0000},
3483         {-1.0,       1.0,       0.1,        0xffff0000},
3484         { 1.0,       1.0,       0.1,        0xffff0000},
3485
3486         {-1.0,      -1.0,       0.1,        0xff00ff00},
3487         {-1.0,       1.0,       0.1,        0xff00ff00},
3488         { 1.0,       1.0,       0.1,        0xff00ff00}
3489     };
3490     short indices[] = {3, 4, 5};
3491
3492     /* Index and vertex buffers should always be creatable */
3493     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3494                                               D3DPOOL_MANAGED, &vb, NULL);
3495     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
3496     if(!vb) {
3497         skip("Failed to create a vertex buffer\n");
3498         return;
3499     }
3500     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, NULL);
3501     ok(hr == D3D_OK, "IDirect3DDevice9_CreateIndexBuffer failed with %08x\n", hr);
3502     if(!ib) {
3503         skip("Failed to create an index buffer\n");
3504         return;
3505     }
3506
3507     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), (void **) &data, 0);
3508     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
3509     memcpy(data, quad, sizeof(quad));
3510     hr = IDirect3DVertexBuffer9_Unlock(vb);
3511     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
3512
3513     hr = IDirect3DIndexBuffer9_Lock(ib, 0, sizeof(indices), (void **) &data, 0);
3514     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Lock failed with %08x\n", hr);
3515     memcpy(data, indices, sizeof(indices));
3516     hr = IDirect3DIndexBuffer9_Unlock(ib);
3517     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
3518
3519     hr = IDirect3DDevice9_SetIndices(device, ib);
3520     ok(hr == D3D_OK, "IDirect3DDevice9_SetIndices failed with %08x\n", hr);
3521     hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad[0]));
3522     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
3523     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
3524     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3525
3526     /* Now destroy the bound index buffer and draw again */
3527     ref = IDirect3DIndexBuffer9_Release(ib);
3528     ok(ref == 0, "Index Buffer reference count is %08d\n", ref);
3529
3530     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
3531     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
3532
3533     hr = IDirect3DDevice9_BeginScene(device);
3534     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3535     if(SUCCEEDED(hr))
3536     {
3537         /* Deliberately using minvertexindex = 0 and numVertices = 6 to prevent d3d from
3538          * making assumptions about the indices or vertices
3539          */
3540         hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 3, 3, 0, 1);
3541         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitive failed with %08x\n", hr);
3542         hr = IDirect3DDevice9_EndScene(device);
3543         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3544     }
3545
3546     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3547     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3548
3549     hr = IDirect3DDevice9_SetIndices(device, NULL);
3550     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
3551     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3552     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
3553
3554     /* Index buffer was already destroyed as part of the test */
3555     IDirect3DVertexBuffer9_Release(vb);
3556 }
3557
3558 static void float_texture_test(IDirect3DDevice9 *device)
3559 {
3560     IDirect3D9 *d3d = NULL;
3561     HRESULT hr;
3562     IDirect3DTexture9 *texture = NULL;
3563     D3DLOCKED_RECT lr;
3564     float *data;
3565     DWORD color;
3566     float quad[] = {
3567         -1.0,      -1.0,       0.1,     0.0,    0.0,
3568         -1.0,       1.0,       0.1,     0.0,    1.0,
3569          1.0,      -1.0,       0.1,     1.0,    0.0,
3570          1.0,       1.0,       0.1,     1.0,    1.0,
3571     };
3572
3573     memset(&lr, 0, sizeof(lr));
3574     IDirect3DDevice9_GetDirect3D(device, &d3d);
3575     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
3576                                      D3DRTYPE_TEXTURE, D3DFMT_R32F) != D3D_OK) {
3577         skip("D3DFMT_R32F textures not supported\n");
3578         goto out;
3579     }
3580
3581     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_R32F,
3582                                         D3DPOOL_MANAGED, &texture, NULL);
3583     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
3584     if(!texture) {
3585         skip("Failed to create R32F texture\n");
3586         goto out;
3587     }
3588
3589     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
3590     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %08x\n", hr);
3591     data = lr.pBits;
3592     *data = 0.0;
3593     hr = IDirect3DTexture9_UnlockRect(texture, 0);
3594     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %08x\n", hr);
3595
3596     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3597     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3598
3599     hr = IDirect3DDevice9_BeginScene(device);
3600     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3601     if(SUCCEEDED(hr))
3602     {
3603         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3604         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3605
3606         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
3607         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3608
3609         hr = IDirect3DDevice9_EndScene(device);
3610         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3611     }
3612     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3613     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3614
3615     color = getPixelColor(device, 240, 320);
3616     ok(color == 0x0000FFFF, "R32F with value 0.0 has color %08x, expected 0x0000FFFF\n", color);
3617
3618     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3619     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3620
3621 out:
3622     if(texture) IDirect3DTexture9_Release(texture);
3623     IDirect3D9_Release(d3d);
3624 }
3625
3626 static void g16r16_texture_test(IDirect3DDevice9 *device)
3627 {
3628     IDirect3D9 *d3d = NULL;
3629     HRESULT hr;
3630     IDirect3DTexture9 *texture = NULL;
3631     D3DLOCKED_RECT lr;
3632     DWORD *data;
3633     DWORD color;
3634     float quad[] = {
3635        -1.0,      -1.0,       0.1,     0.0,    0.0,
3636        -1.0,       1.0,       0.1,     0.0,    1.0,
3637         1.0,      -1.0,       0.1,     1.0,    0.0,
3638         1.0,       1.0,       0.1,     1.0,    1.0,
3639     };
3640
3641     memset(&lr, 0, sizeof(lr));
3642     IDirect3DDevice9_GetDirect3D(device, &d3d);
3643     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
3644        D3DRTYPE_TEXTURE, D3DFMT_G16R16) != D3D_OK) {
3645            skip("D3DFMT_G16R16 textures not supported\n");
3646            goto out;
3647     }
3648
3649     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_G16R16,
3650                                         D3DPOOL_MANAGED, &texture, NULL);
3651     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
3652     if(!texture) {
3653         skip("Failed to create D3DFMT_G16R16 texture\n");
3654         goto out;
3655     }
3656
3657     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
3658     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %08x\n", hr);
3659     data = lr.pBits;
3660     *data = 0x0f00f000;
3661     hr = IDirect3DTexture9_UnlockRect(texture, 0);
3662     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %08x\n", hr);
3663
3664     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3665     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3666
3667     hr = IDirect3DDevice9_BeginScene(device);
3668     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3669     if(SUCCEEDED(hr))
3670     {
3671         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3672         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3673
3674         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
3675         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3676
3677         hr = IDirect3DDevice9_EndScene(device);
3678         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3679     }
3680     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3681     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3682
3683     color = getPixelColor(device, 240, 320);
3684     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xf0, 0x0f, 0xff), 1),
3685        "D3DFMT_G16R16 with value 0x00ffff00 has color %08x, expected 0x00f00fff\n", color);
3686
3687     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3688     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3689
3690 out:
3691     if(texture) IDirect3DTexture9_Release(texture);
3692     IDirect3D9_Release(d3d);
3693 }
3694
3695 static void texture_transform_flags_test(IDirect3DDevice9 *device)
3696 {
3697     HRESULT hr;
3698     IDirect3D9 *d3d;
3699     D3DFORMAT fmt = D3DFMT_X8R8G8B8;
3700     D3DCAPS9 caps;
3701     IDirect3DTexture9 *texture = NULL;
3702     IDirect3DVolumeTexture9 *volume = NULL;
3703     unsigned int x, y, z;
3704     D3DLOCKED_RECT lr;
3705     D3DLOCKED_BOX lb;
3706     DWORD color;
3707     UINT w, h;
3708     IDirect3DVertexDeclaration9 *decl, *decl2, *decl3;
3709     float identity[16] = {1.0, 0.0, 0.0, 0.0,
3710                            0.0, 1.0, 0.0, 0.0,
3711                            0.0, 0.0, 1.0, 0.0,
3712                            0.0, 0.0, 0.0, 1.0};
3713     static const D3DVERTEXELEMENT9 decl_elements[] = {
3714         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3715         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3716         D3DDECL_END()
3717     };
3718     static const D3DVERTEXELEMENT9 decl_elements2[] = {
3719         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3720         {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3721         D3DDECL_END()
3722     };
3723     static const D3DVERTEXELEMENT9 decl_elements3[] = {
3724         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3725         {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3726         D3DDECL_END()
3727     };
3728     static const unsigned char proj_texdata[] = {0x00, 0x00, 0x00, 0x00,
3729                                                  0x00, 0xff, 0x00, 0x00,
3730                                                  0x00, 0x00, 0x00, 0x00,
3731                                                  0x00, 0x00, 0x00, 0x00};
3732
3733     memset(&lr, 0, sizeof(lr));
3734     memset(&lb, 0, sizeof(lb));
3735     IDirect3DDevice9_GetDirect3D(device, &d3d);
3736     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
3737                                      D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16) == D3D_OK) {
3738         fmt = D3DFMT_A16B16G16R16;
3739     }
3740     IDirect3D9_Release(d3d);
3741
3742     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
3743     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
3744     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements2, &decl2);
3745     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
3746     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements3, &decl3);
3747     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
3748     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, FALSE);
3749     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_SRGBTEXTURE) returned %08x\n", hr);
3750     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
3751     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MAGFILTER) returned %08x\n", hr);
3752     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
3753     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MINFILTER) returned %08x\n", hr);
3754     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
3755     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MIPFILTER) returned %08x\n", hr);
3756     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
3757     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSU) returned %08x\n", hr);
3758     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
3759     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSV) returned %08x\n", hr);
3760     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP);
3761     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSW) returned %08x\n", hr);
3762     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
3763     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState(D3DRS_LIGHTING) returned %08x\n", hr);
3764     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
3765     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3766
3767     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3768     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %08x\n", hr);
3769     w = min(1024, caps.MaxTextureWidth);
3770     h = min(1024, caps.MaxTextureHeight);
3771     hr = IDirect3DDevice9_CreateTexture(device, w, h, 1,
3772                                         0, fmt, D3DPOOL_MANAGED, &texture, NULL);
3773     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
3774     if(!texture) {
3775         skip("Failed to create the test texture\n");
3776         return;
3777     }
3778
3779     /* Unfortunately there is no easy way to set up a texture coordinate passthrough
3780      * in d3d fixed function pipeline, so create a texture that has a gradient from 0.0 to
3781      * 1.0 in red and green for the x and y coords
3782      */
3783     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
3784     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %08x\n", hr);
3785     for(y = 0; y < h; y++) {
3786         for(x = 0; x < w; x++) {
3787             double r_f = (double) y / (double) h;
3788             double g_f = (double) x / (double) w;
3789             if(fmt == D3DFMT_A16B16G16R16) {
3790                 unsigned short r, g;
3791                 unsigned short *dst = (unsigned short *) (((char *) lr.pBits) + y * lr.Pitch + x * 8);
3792                 r = (unsigned short) (r_f * 65536.0);
3793                 g = (unsigned short) (g_f * 65536.0);
3794                 dst[0] = r;
3795                 dst[1] = g;
3796                 dst[2] = 0;
3797                 dst[3] = 65535;
3798             } else {
3799                 unsigned char *dst = ((unsigned char *) lr.pBits) + y * lr.Pitch + x * 4;
3800                 unsigned char r = (unsigned char) (r_f * 255.0);
3801                 unsigned char g = (unsigned char) (g_f * 255.0);
3802                 dst[0] = 0;
3803                 dst[1] = g;
3804                 dst[2] = r;
3805                 dst[3] = 255;
3806             }
3807         }
3808     }
3809     hr = IDirect3DTexture9_UnlockRect(texture, 0);
3810     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect returned %08x\n", hr);
3811     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3812     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
3813
3814     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3815     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3816     hr = IDirect3DDevice9_BeginScene(device);
3817     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3818     if(SUCCEEDED(hr))
3819     {
3820         float quad1[] = {
3821             -1.0,      -1.0,       0.1,     1.0,    1.0,
3822             -1.0,       0.0,       0.1,     1.0,    1.0,
3823              0.0,      -1.0,       0.1,     1.0,    1.0,
3824              0.0,       0.0,       0.1,     1.0,    1.0,
3825         };
3826         float quad2[] = {
3827             -1.0,       0.0,       0.1,     1.0,    1.0,
3828             -1.0,       1.0,       0.1,     1.0,    1.0,
3829              0.0,       0.0,       0.1,     1.0,    1.0,
3830              0.0,       1.0,       0.1,     1.0,    1.0,
3831         };
3832         float quad3[] = {
3833              0.0,       0.0,       0.1,     0.5,    0.5,
3834              0.0,       1.0,       0.1,     0.5,    0.5,
3835              1.0,       0.0,       0.1,     0.5,    0.5,
3836              1.0,       1.0,       0.1,     0.5,    0.5,
3837         };
3838         float quad4[] = {
3839              320,       480,       0.1,     1.0,    0.0,    1.0,
3840              320,       240,       0.1,     1.0,    0.0,    1.0,
3841              640,       480,       0.1,     1.0,    0.0,    1.0,
3842              640,       240,       0.1,     1.0,    0.0,    1.0,
3843         };
3844         float mat[16] = {0.0, 0.0, 0.0, 0.0,
3845                           0.0, 0.0, 0.0, 0.0,
3846                           0.0, 0.0, 0.0, 0.0,
3847                           0.0, 0.0, 0.0, 0.0};
3848
3849         /* What happens with the texture matrix if D3DTSS_TEXTURETRANSFORMFLAGS is disabled? */
3850         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3851         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3852         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
3853         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3854
3855         /* What happens with transforms enabled? */
3856         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3857         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3858         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
3859         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3860
3861         /* What happens if 4 coords are used, but only 2 given ?*/
3862         mat[8] = 1.0;
3863         mat[13] = 1.0;
3864         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3865         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3866         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
3867         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3868         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
3869         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3870
3871         /* What happens with transformed geometry? This setup lead to 0/0 coords with untransformed
3872          * geometry. If the same applies to transformed vertices, the quad will be black, otherwise red,
3873          * due to the coords in the vertices. (turns out red, indeed)
3874          */
3875         memset(mat, 0, sizeof(mat));
3876         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3877         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3878         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_TEX1);
3879         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3880         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3881         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3882         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
3883         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3884
3885         hr = IDirect3DDevice9_EndScene(device);
3886         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3887     }
3888     color = getPixelColor(device, 160, 360);
3889     ok(color_match(color, 0x00FFFF00, 1), "quad 1 has color %08x, expected 0x00FFFF00\n", color);
3890     color = getPixelColor(device, 160, 120);
3891     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
3892     color = getPixelColor(device, 480, 120);
3893     ok(color_match(color, 0x0000FF00, 1), "quad 3 has color %08x, expected 0x0000FF00\n", color);
3894     color = getPixelColor(device, 480, 360);
3895     ok(color_match(color, 0x00FF0000, 1), "quad 4 has color %08x, expected 0x00FF0000\n", color);
3896     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3897     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3898
3899     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
3900     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3901
3902     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3903     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3904     hr = IDirect3DDevice9_BeginScene(device);
3905     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3906     if(SUCCEEDED(hr))
3907     {
3908         float quad1[] = {
3909             -1.0,      -1.0,       0.1,     0.8,    0.2,
3910             -1.0,       0.0,       0.1,     0.8,    0.2,
3911              0.0,      -1.0,       0.1,     0.8,    0.2,
3912              0.0,       0.0,       0.1,     0.8,    0.2,
3913         };
3914         float quad2[] = {
3915             -1.0,       0.0,       0.1,     0.5,    1.0,
3916             -1.0,       1.0,       0.1,     0.5,    1.0,
3917              0.0,       0.0,       0.1,     0.5,    1.0,
3918              0.0,       1.0,       0.1,     0.5,    1.0,
3919         };
3920         float quad3[] = {
3921              0.0,       0.0,       0.1,     0.5,    1.0,
3922              0.0,       1.0,       0.1,     0.5,    1.0,
3923              1.0,       0.0,       0.1,     0.5,    1.0,
3924              1.0,       1.0,       0.1,     0.5,    1.0,
3925         };
3926         float quad4[] = {
3927              0.0,      -1.0,       0.1,     0.8,    0.2,
3928              0.0,       0.0,       0.1,     0.8,    0.2,
3929              1.0,      -1.0,       0.1,     0.8,    0.2,
3930              1.0,       0.0,       0.1,     0.8,    0.2,
3931         };
3932         float mat[16] = {0.0, 0.0, 0.0, 0.0,
3933                           0.0, 0.0, 0.0, 0.0,
3934                           0.0, 1.0, 0.0, 0.0,
3935                           0.0, 0.0, 0.0, 0.0};
3936
3937         /* What happens to the default 1 in the 3rd coordinate if it is disabled?
3938          */
3939         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3940         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3941         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3942         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3943
3944         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
3945         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3946
3947         /* D3DTFF_COUNT1 does not work on Nvidia drivers. It behaves like D3DTTFF_DISABLE. On ATI drivers
3948          * it behaves like COUNT2 because normal textures require 2 coords
3949          */
3950         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
3951         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3952         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 5 * sizeof(float));
3953         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3954
3955         /* Just to be sure, the same as quad2 above */
3956         memset(mat, 0, sizeof(mat));
3957         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3958         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3959         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3960         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3961         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
3962         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3963
3964         /* Now, what happens to the 2nd coordinate(that is disabled in the matrix) if it is not
3965          * used? And what happens to the first?
3966          */
3967         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
3968         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3969         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
3970         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3971
3972         hr = IDirect3DDevice9_EndScene(device);
3973         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3974     }
3975     color = getPixelColor(device, 160, 360);
3976     ok(color_match(color, 0x00FF0000, 1), "quad 1 has color %08x, expected 0x00FF0000\n", color);
3977     color = getPixelColor(device, 160, 120);
3978     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
3979     color = getPixelColor(device, 480, 120);
3980     ok(color_match(color, 0x00ff8000, 1) || color == 0x00000000,
3981        "quad 3 has color %08x, expected 0x00ff8000\n", color);
3982     color = getPixelColor(device, 480, 360);
3983     ok(color_match(color, 0x0033cc00, 1) || color_match(color, 0x00FF0000, 1),
3984        "quad 4 has color %08x, expected 0x0033cc00\n", color);
3985     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3986     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3987
3988     IDirect3DTexture9_Release(texture);
3989
3990     /* Test projected textures, without any fancy matrices */
3991     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff203040, 0.0, 0);
3992     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3993     hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_L8, D3DPOOL_MANAGED, &texture, NULL);
3994     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
3995     hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &identity);
3996     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3997     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl3);
3998     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
3999
4000     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
4001     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %08x\n", hr);
4002     for(x = 0; x < 4; x++) {
4003         memcpy(((BYTE *) lr.pBits) + lr.Pitch * x, proj_texdata + 4 * x, 4 * sizeof(proj_texdata[0]));
4004     }
4005     hr = IDirect3DTexture9_UnlockRect(texture, 0);
4006     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %08x\n", hr);
4007     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
4008     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
4009
4010     hr = IDirect3DDevice9_BeginScene(device);
4011     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
4012     if(SUCCEEDED(hr))
4013     {
4014         const float proj_quads[] = {
4015            -1.0,   -1.0,    0.1,    0.0,    0.0,    4.0,    6.0,
4016             1.0,   -1.0,    0.1,    4.0,    0.0,    4.0,    6.0,
4017            -1.0,    0.0,    0.1,    0.0,    4.0,    4.0,    6.0,
4018             1.0,    0.0,    0.1,    4.0,    4.0,    4.0,    6.0,
4019            -1.0,    0.0,    0.1,    0.0,    0.0,    4.0,    6.0,
4020             1.0,    0.0,    0.1,    4.0,    0.0,    4.0,    6.0,
4021            -1.0,    1.0,    0.1,    0.0,    4.0,    4.0,    6.0,
4022             1.0,    1.0,    0.1,    4.0,    4.0,    4.0,    6.0,
4023         };
4024
4025         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4 | D3DTTFF_PROJECTED);
4026         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4027         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &proj_quads[0*7], 7 * sizeof(float));
4028         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
4029
4030         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3 | D3DTTFF_PROJECTED);
4031         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4032         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &proj_quads[4*7], 7 * sizeof(float));
4033         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
4034
4035         hr = IDirect3DDevice9_EndScene(device);
4036         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
4037     }
4038
4039     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4040     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
4041     IDirect3DTexture9_Release(texture);
4042
4043     color = getPixelColor(device, 158, 118);
4044     ok(color == 0x00000000, "proj: Pixel 158/118 has color 0x%08x, expected 0x00000000\n", color);
4045     color = getPixelColor(device, 162, 118);
4046     ok(color == 0x00000000, "proj: Pixel 162/118 has color 0x%08x, expected 0x00000000\n", color);
4047     color = getPixelColor(device, 158, 122);
4048     ok(color == 0x00000000, "proj: Pixel 158/122 has color 0x%08x, expected 0x00000000\n", color);
4049     color = getPixelColor(device, 162, 122);
4050     ok(color == 0x00FFFFFF, "proj: Pixel 162/122 has color 0x%08x, expected 0x00FFFFFF\n", color);
4051
4052     color = getPixelColor(device, 158, 178);
4053     ok(color == 0x00000000, "proj: Pixel 158/178 has color 0x%08x, expected 0x00000000\n", color);
4054     color = getPixelColor(device, 162, 178);
4055     ok(color == 0x00FFFFFF, "proj: Pixel 158/178 has color 0x%08x, expected 0x00FFFFFF\n", color);
4056     color = getPixelColor(device, 158, 182);
4057     ok(color == 0x00000000, "proj: Pixel 158/182 has color 0x%08x, expected 0x00000000\n", color);
4058     color = getPixelColor(device, 162, 182);
4059     ok(color == 0x00000000, "proj: Pixel 158/182 has color 0x%08x, expected 0x00000000\n", color);
4060
4061     color = getPixelColor(device, 318, 118);
4062     ok(color == 0x00000000, "proj: Pixel 318/118 has color 0x%08x, expected 0x00000000\n", color);
4063     color = getPixelColor(device, 322, 118);
4064     ok(color == 0x00000000, "proj: Pixel 322/118 has color 0x%08x, expected 0x00000000\n", color);
4065     color = getPixelColor(device, 318, 122);
4066     ok(color == 0x00FFFFFF, "proj: Pixel 318/122 has color 0x%08x, expected 0x00FFFFFF\n", color);
4067     color = getPixelColor(device, 322, 122);
4068     ok(color == 0x00000000, "proj: Pixel 322/122 has color 0x%08x, expected 0x00000000\n", color);
4069
4070     color = getPixelColor(device, 318, 178);
4071     ok(color == 0x00FFFFFF, "proj: Pixel 318/178 has color 0x%08x, expected 0x00FFFFFF\n", color);
4072     color = getPixelColor(device, 322, 178);
4073     ok(color == 0x00000000, "proj: Pixel 322/178 has color 0x%08x, expected 0x00000000\n", color);
4074     color = getPixelColor(device, 318, 182);
4075     ok(color == 0x00000000, "proj: Pixel 318/182 has color 0x%08x, expected 0x00000000\n", color);
4076     color = getPixelColor(device, 322, 182);
4077     ok(color == 0x00000000, "proj: Pixel 322/182 has color 0x%08x, expected 0x00000000\n", color);
4078
4079     color = getPixelColor(device, 238, 298);
4080     ok(color == 0x00000000, "proj: Pixel 238/298 has color 0x%08x, expected 0x00000000\n", color);
4081     color = getPixelColor(device, 242, 298);
4082     ok(color == 0x00000000, "proj: Pixel 242/298 has color 0x%08x, expected 0x00000000\n", color);
4083     color = getPixelColor(device, 238, 302);
4084     ok(color == 0x00000000, "proj: Pixel 238/302 has color 0x%08x, expected 0x00000000\n", color);
4085     color = getPixelColor(device, 242, 302);
4086     ok(color == 0x00FFFFFF, "proj: Pixel 242/302 has color 0x%08x, expected 0x00FFFFFF\n", color);
4087
4088     color = getPixelColor(device, 238, 388);
4089     ok(color == 0x00000000, "proj: Pixel 238/388 has color 0x%08x, expected 0x00000000\n", color);
4090     color = getPixelColor(device, 242, 388);
4091     ok(color == 0x00FFFFFF, "proj: Pixel 242/388 has color 0x%08x, expected 0x00FFFFFF\n", color);
4092     color = getPixelColor(device, 238, 392);
4093     ok(color == 0x00000000, "proj: Pixel 238/392 has color 0x%08x, expected 0x00000000\n", color);
4094     color = getPixelColor(device, 242, 392);
4095     ok(color == 0x00000000, "proj: Pixel 242/392 has color 0x%08x, expected 0x00000000\n", color);
4096
4097     color = getPixelColor(device, 478, 298);
4098     ok(color == 0x00000000, "proj: Pixel 478/298 has color 0x%08x, expected 0x00000000\n", color);
4099     color = getPixelColor(device, 482, 298);
4100     ok(color == 0x00000000, "proj: Pixel 482/298 has color 0x%08x, expected 0x00000000\n", color);
4101     color = getPixelColor(device, 478, 302);
4102     ok(color == 0x00FFFFFF, "proj: Pixel 478/302 has color 0x%08x, expected 0x00FFFFFF\n", color);
4103     color = getPixelColor(device, 482, 302);
4104     ok(color == 0x00000000, "proj: Pixel 482/302 has color 0x%08x, expected 0x00000000\n", color);
4105
4106     color = getPixelColor(device, 478, 388);
4107     ok(color == 0x00FFFFFF, "proj: Pixel 478/388 has color 0x%08x, expected 0x00FFFFFF\n", color);
4108     color = getPixelColor(device, 482, 388);
4109     ok(color == 0x00000000, "proj: Pixel 482/388 has color 0x%08x, expected 0x00000000\n", color);
4110     color = getPixelColor(device, 478, 392);
4111     ok(color == 0x00000000, "proj: Pixel 478/392 has color 0x%08x, expected 0x00000000\n", color);
4112     color = getPixelColor(device, 482, 392);
4113     ok(color == 0x00000000, "proj: Pixel 482/392 has color 0x%08x, expected 0x00000000\n", color);
4114
4115     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4116     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4117
4118     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff203040, 0.0, 0);
4119     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4120     /* Use a smaller volume texture than the biggest possible size for memory and performance reasons
4121      * Thus watch out if sampling from texels between 0 and 1.
4122      */
4123     hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 32, 1, 0, fmt, D3DPOOL_MANAGED, &volume, 0);
4124     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
4125        "IDirect3DDevice9_CreateVolumeTexture failed with %08x\n", hr);
4126     if(!volume) {
4127         skip("Failed to create a volume texture\n");
4128         goto out;
4129     }
4130
4131     hr = IDirect3DVolumeTexture9_LockBox(volume, 0, &lb, NULL, 0);
4132     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_LockBox failed with %08x\n", hr);
4133     for(z = 0; z < 32; z++) {
4134         for(y = 0; y < 32; y++) {
4135             for(x = 0; x < 32; x++) {
4136                 char size = (fmt == D3DFMT_A16B16G16R16 ? 8 : 4);
4137                 void *mem = ((char *)  lb.pBits) + y * lb.RowPitch + z * lb.SlicePitch + x * size;
4138                 float r_f = (float) x / 31.0;
4139                 float g_f = (float) y / 31.0;
4140                 float b_f = (float) z / 31.0;
4141
4142                 if(fmt == D3DFMT_A16B16G16R16) {
4143                     unsigned short *mem_s = mem;
4144                     mem_s[0]  = r_f * 65535.0;
4145                     mem_s[1]  = g_f * 65535.0;
4146                     mem_s[2]  = b_f * 65535.0;
4147                     mem_s[3]  = 65535;
4148                 } else {
4149                     unsigned char *mem_c = mem;
4150                     mem_c[0]  = b_f * 255.0;
4151                     mem_c[1]  = g_f * 255.0;
4152                     mem_c[2]  = r_f * 255.0;
4153                     mem_c[3]  = 255;
4154                 }
4155             }
4156         }
4157     }
4158     hr = IDirect3DVolumeTexture9_UnlockBox(volume, 0);
4159     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %08x\n", hr);
4160
4161     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) volume);
4162     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %08x\n", hr);
4163
4164     hr = IDirect3DDevice9_BeginScene(device);
4165     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
4166     if(SUCCEEDED(hr))
4167     {
4168         float quad1[] = {
4169             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
4170             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
4171              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
4172              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
4173         };
4174         float quad2[] = {
4175             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
4176             -1.0,       1.0,       0.1,     1.0,    1.0,    1.0,
4177              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
4178              0.0,       1.0,       0.1,     1.0,    1.0,    1.0
4179         };
4180         float quad3[] = {
4181              0.0,       0.0,       0.1,     0.0,    0.0,
4182              0.0,       1.0,       0.1,     0.0,    0.0,
4183              1.0,       0.0,       0.1,     0.0,    0.0,
4184              1.0,       1.0,       0.1,     0.0,    0.0
4185         };
4186         float quad4[] = {
4187              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
4188              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
4189              1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
4190              1.0,       0.0,       0.1,     1.0,    1.0,    1.0
4191         };
4192         float mat[16] = {1.0, 0.0, 0.0, 0.0,
4193                          0.0, 0.0, 1.0, 0.0,
4194                          0.0, 1.0, 0.0, 0.0,
4195                          0.0, 0.0, 0.0, 1.0};
4196         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
4197         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
4198
4199         /* Draw a quad with all 3 coords enabled. Nothing fancy. v and w are swapped, but have the same
4200          * values
4201          */
4202         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
4203         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
4204         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
4205         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4206         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
4207         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4208
4209         /* Now disable the w coordinate. Does that change the input, or the output. The coordinates
4210          * are swapped by the matrix. If it changes the input, the v coord will be missing(green),
4211          * otherwise the w will be missing(blue).
4212          * turns out that on nvidia cards the blue color is missing, so it is an output modification.
4213          * On ATI cards the COUNT2 is ignored, and it behaves in the same way as COUNT3.
4214          */
4215         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
4216         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4217         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
4218         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4219
4220         /* default values? Set up the identity matrix, pass in 2 vertex coords, and enable 3 */
4221         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
4222         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
4223         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
4224         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4225         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4226         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
4227         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
4228         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4229
4230         /* D3DTTFF_COUNT1. Set a NULL matrix, and count1, pass in all values as 1.0. Nvidia has count1 ==
4231          * disable. ATI extends it up to the amount of values needed for the volume texture
4232          */
4233         memset(mat, 0, sizeof(mat));
4234         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
4235         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
4236         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
4237         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4238         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
4239         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
4240         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
4241         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4242
4243         hr = IDirect3DDevice9_EndScene(device);
4244         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
4245     }
4246
4247     color = getPixelColor(device, 160, 360);
4248     ok(color == 0x00ffffff, "quad 1 has color %08x, expected 0x00ffffff\n", color);
4249     color = getPixelColor(device, 160, 120);
4250     ok(color == 0x00ffff00 /* NV*/ || color == 0x00ffffff /* ATI */,
4251        "quad 2 has color %08x, expected 0x00ffff00\n", color);
4252     color = getPixelColor(device, 480, 120);
4253     ok(color == 0x000000ff, "quad 3 has color %08x, expected 0x000000ff\n", color);
4254     color = getPixelColor(device, 480, 360);
4255     ok(color == 0x00ffffff || color == 0x0000ff00, "quad 4 has color %08x, expected 0x00ffffff\n", color);
4256
4257     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4258     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4259
4260     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff303030, 0.0, 0);
4261     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4262     hr = IDirect3DDevice9_BeginScene(device);
4263     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
4264     if(SUCCEEDED(hr))
4265     {
4266         float quad1[] = {
4267             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
4268             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
4269              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
4270              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
4271         };
4272         float quad2[] = {
4273             -1.0,       0.0,       0.1,
4274             -1.0,       1.0,       0.1,
4275              0.0,       0.0,       0.1,
4276              0.0,       1.0,       0.1,
4277         };
4278         float quad3[] = {
4279              0.0,       0.0,       0.1,     1.0,
4280              0.0,       1.0,       0.1,     1.0,
4281              1.0,       0.0,       0.1,     1.0,
4282              1.0,       1.0,       0.1,     1.0
4283         };
4284         float mat[16] =  {0.0, 0.0, 0.0, 0.0,
4285                            0.0, 0.0, 0.0, 0.0,
4286                            0.0, 0.0, 0.0, 0.0,
4287                            0.0, 1.0, 0.0, 0.0};
4288         float mat2[16] = {0.0, 0.0, 0.0, 1.0,
4289                            1.0, 0.0, 0.0, 0.0,
4290                            0.0, 1.0, 0.0, 0.0,
4291                            0.0, 0.0, 1.0, 0.0};
4292         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
4293         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
4294
4295         /* Default values? 4 coords used, 3 passed. What happens to the 4th?
4296          * Use COUNT3 because newer Nvidia drivers return black when there are more (output) coords
4297          * than being used by the texture(volume tex -> 3). Again, as shown in earlier test the COUNTx
4298          * affects the post-transformation output, so COUNT3 plus the matrix above is OK for testing the
4299          * 4th *input* coordinate.
4300          */
4301         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
4302         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
4303         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
4304         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4305         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
4306         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4307
4308         /* None passed */
4309         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
4310         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
4311         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4312         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
4313         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
4314         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4315
4316         /* 4 used, 1 passed */
4317         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl2);
4318         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
4319         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat2);
4320         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
4321         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 4 * sizeof(float));
4322         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4323
4324         hr = IDirect3DDevice9_EndScene(device);
4325         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
4326     }
4327     color = getPixelColor(device, 160, 360);
4328     ok(color == 0x0000ff00, "quad 1 has color %08x, expected 0x0000ff00\n", color);
4329     color = getPixelColor(device, 160, 120);
4330     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x00000000\n", color);
4331     color = getPixelColor(device, 480, 120);
4332     ok(color == 0x00ff0000, "quad 3 has color %08x, expected 0x00ff0000\n", color);
4333     /* Quad4: unused */
4334
4335     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4336     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4337
4338     IDirect3DVolumeTexture9_Release(volume);
4339
4340     out:
4341     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
4342     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
4343     IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
4344     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4345     hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &identity);
4346     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
4347     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4348     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
4349     IDirect3DVertexDeclaration9_Release(decl);
4350     IDirect3DVertexDeclaration9_Release(decl2);
4351     IDirect3DVertexDeclaration9_Release(decl3);
4352 }
4353
4354 static void texdepth_test(IDirect3DDevice9 *device)
4355 {
4356     IDirect3DPixelShader9 *shader;
4357     HRESULT hr;
4358     const float texdepth_test_data1[] = { 0.25,  2.0, 0.0, 0.0};
4359     const float texdepth_test_data2[] = { 0.25,  0.5, 0.0, 0.0};
4360     const float texdepth_test_data3[] = {-1.00,  0.1, 0.0, 0.0};
4361     const float texdepth_test_data4[] = {-0.25, -0.5, 0.0, 0.0};
4362     const float texdepth_test_data5[] = { 1.00, -0.1, 0.0, 0.0};
4363     const float texdepth_test_data6[] = { 1.00,  0.5, 0.0, 0.0};
4364     const float texdepth_test_data7[] = { 0.50,  0.0, 0.0, 0.0};
4365     DWORD shader_code[] = {
4366         0xffff0104,                                                                 /* ps_1_4               */
4367         0x00000051, 0xa00f0001, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000,     /* def c1, 0, 0, 1, 1   */
4368         0x00000001, 0x800f0005, 0xa0e40000,                                         /* mov r5, c0           */
4369         0x0000fffd,                                                                 /* phase                */
4370         0x00000057, 0x800f0005,                                                     /* texdepth r5          */
4371         0x00000001, 0x800f0000, 0xa0e40001,                                         /* mov r0, c1           */
4372         0x0000ffff                                                                  /* end                  */
4373     };
4374     DWORD color;
4375     float vertex[] = {
4376        -1.0,   -1.0,    0.0,
4377         1.0,   -1.0,    1.0,
4378        -1.0,    1.0,    0.0,
4379         1.0,    1.0,    1.0
4380     };
4381
4382     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
4383     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4384
4385     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffff00, 0.0, 0);
4386     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4387     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
4388     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
4389     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
4390     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
4391     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
4392     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
4393     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4394     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetFVF returned %#x.\n", hr);
4395
4396     /* Fill the depth buffer with a gradient */
4397     hr = IDirect3DDevice9_BeginScene(device);
4398     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4399     if(SUCCEEDED(hr))
4400     {
4401         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4402         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4403         hr = IDirect3DDevice9_EndScene(device);
4404         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4405     }
4406
4407     /* Now perform the actual tests. Same geometry, but with the shader */
4408     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
4409     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
4410     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
4411     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
4412     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4413     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4414
4415     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data1, 1);
4416     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4417     hr = IDirect3DDevice9_BeginScene(device);
4418     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4419     if(SUCCEEDED(hr))
4420     {
4421         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4422         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4423
4424         hr = IDirect3DDevice9_EndScene(device);
4425         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4426     }
4427
4428     color = getPixelColor(device, 158, 240);
4429     ok(color == 0x000000ff, "Pixel 158(25%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
4430     color = getPixelColor(device, 162, 240);
4431     ok(color == 0x00ffffff, "Pixel 158(25%% + 2 pixel) has color %08x, expected 0x00ffffff\n", color);
4432
4433     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4434     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4435
4436     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
4437     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
4438
4439     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data2, 1);
4440     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4441     hr = IDirect3DDevice9_BeginScene(device);
4442     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4443     if(SUCCEEDED(hr))
4444     {
4445         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4446         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4447
4448         hr = IDirect3DDevice9_EndScene(device);
4449         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4450     }
4451
4452     color = getPixelColor(device, 318, 240);
4453     ok(color == 0x000000ff, "Pixel 318(50%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
4454     color = getPixelColor(device, 322, 240);
4455     ok(color == 0x00ffff00, "Pixel 322(50%% + 2 pixel) has color %08x, expected 0x00ffff00\n", color);
4456
4457     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4458     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4459
4460     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
4461     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
4462
4463     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data3, 1);
4464     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4465     hr = IDirect3DDevice9_BeginScene(device);
4466     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4467     if(SUCCEEDED(hr))
4468     {
4469         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4470         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4471
4472         hr = IDirect3DDevice9_EndScene(device);
4473         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4474     }
4475
4476     color = getPixelColor(device, 1, 240);
4477     ok(color == 0x00ff0000, "Pixel 1(0%% + 2 pixel) has color %08x, expected 0x00ff0000\n", color);
4478
4479     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4480     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4481
4482     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
4483     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
4484
4485     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data4, 1);
4486     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4487     hr = IDirect3DDevice9_BeginScene(device);
4488     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4489     if(SUCCEEDED(hr))
4490     {
4491         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4492         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4493
4494         hr = IDirect3DDevice9_EndScene(device);
4495         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4496     }
4497     color = getPixelColor(device, 318, 240);
4498     ok(color == 0x000000ff, "Pixel 318(50%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
4499     color = getPixelColor(device, 322, 240);
4500     ok(color == 0x0000ff00, "Pixel 322(50%% + 2 pixel) has color %08x, expected 0x0000ff00\n", color);
4501
4502     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4503     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4504
4505     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
4506     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
4507
4508     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data5, 1);
4509     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4510     hr = IDirect3DDevice9_BeginScene(device);
4511     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4512     if(SUCCEEDED(hr))
4513     {
4514         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4515         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4516
4517         hr = IDirect3DDevice9_EndScene(device);
4518         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4519     }
4520
4521     color = getPixelColor(device, 1, 240);
4522     ok(color == 0x00ffff00, "Pixel 1(0%% + 2 pixel) has color %08x, expected 0x00ffff00\n", color);
4523
4524     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4525     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4526
4527     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
4528     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
4529
4530     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data6, 1);
4531     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4532     hr = IDirect3DDevice9_BeginScene(device);
4533     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4534     if(SUCCEEDED(hr))
4535     {
4536         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4537         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4538
4539         hr = IDirect3DDevice9_EndScene(device);
4540         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4541     }
4542
4543     color = getPixelColor(device, 638, 240);
4544     ok(color == 0x000000ff, "Pixel 638(100%% + 2 pixel) has color %08x, expected 0x000000ff\n", color);
4545
4546     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4547     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4548
4549     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
4550     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
4551
4552     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data7, 1);
4553     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4554     hr = IDirect3DDevice9_BeginScene(device);
4555     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4556     if(SUCCEEDED(hr))
4557     {
4558         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4559         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4560
4561         hr = IDirect3DDevice9_EndScene(device);
4562         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4563     }
4564
4565     color = getPixelColor(device, 638, 240);
4566     ok(color == 0x000000ff, "Pixel 638(100%% + 2 pixel) has color %08x, expected 0x000000ff\n", color);
4567
4568     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4569     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4570
4571     /* Cleanup */
4572     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4573     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4574     IDirect3DPixelShader9_Release(shader);
4575
4576     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
4577     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
4578     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
4579     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
4580 }
4581
4582 static void texkill_test(IDirect3DDevice9 *device)
4583 {
4584     IDirect3DPixelShader9 *shader;
4585     HRESULT hr;
4586     DWORD color;
4587
4588     const float vertex[] = {
4589     /*                          bottom  top    right    left */
4590         -1.0,   -1.0,   1.0,   -0.1,    0.9,    0.9,   -0.1,
4591          1.0,   -1.0,   0.0,    0.9,   -0.1,    0.9,   -0.1,
4592         -1.0,    1.0,   1.0,   -0.1,    0.9,   -0.1,    0.9,
4593          1.0,    1.0,   0.0,    0.9,   -0.1,   -0.1,    0.9,
4594     };
4595
4596     DWORD shader_code_11[] = {
4597     0xffff0101,                                                             /* ps_1_1                     */
4598     0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0 */
4599     0x00000041, 0xb00f0000,                                                 /* texkill t0                 */
4600     0x00000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                 */
4601     0x0000ffff                                                              /* end                        */
4602     };
4603     DWORD shader_code_20[] = {
4604     0xffff0200,                                                             /* ps_2_0                     */
4605     0x0200001f, 0x80000000, 0xb00f0000,                                     /* dcl t0                     */
4606     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c0, 0.0, 0.0, 1.0, 1.0 */
4607     0x01000041, 0xb00f0000,                                                 /* texkill t0                 */
4608     0x02000001, 0x800f0800, 0xa0e40000,                                     /* mov oC0, c0                */
4609     0x0000ffff                                                              /* end                        */
4610     };
4611
4612     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
4613     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4614     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader);
4615     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4616
4617     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4618     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4619     hr = IDirect3DDevice9_BeginScene(device);
4620     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4621     if(SUCCEEDED(hr))
4622     {
4623         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1);
4624         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
4625         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 7 * sizeof(float));
4626         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4627         hr = IDirect3DDevice9_EndScene(device);
4628         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4629     }
4630     color = getPixelColor(device, 63, 46);
4631     ok(color == 0x0000ff00, "Pixel 63/46 has color %08x, expected 0x0000ff00\n", color);
4632     color = getPixelColor(device, 66, 46);
4633     ok(color == 0x0000ff00, "Pixel 66/64 has color %08x, expected 0x0000ff00\n", color);
4634     color = getPixelColor(device, 63, 49);
4635     ok(color == 0x0000ff00, "Pixel 63/49 has color %08x, expected 0x0000ff00\n", color);
4636     color = getPixelColor(device, 66, 49);
4637     ok(color == 0x00ff0000, "Pixel 66/49 has color %08x, expected 0x00ff0000\n", color);
4638
4639     color = getPixelColor(device, 578, 46);
4640     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
4641     color = getPixelColor(device, 575, 46);
4642     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
4643     color = getPixelColor(device, 578, 49);
4644     ok(color == 0x0000ff00, "Pixel 578/49 has color %08x, expected 0x0000ff00\n", color);
4645     color = getPixelColor(device, 575, 49);
4646     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
4647
4648     color = getPixelColor(device, 63, 430);
4649     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
4650     color = getPixelColor(device, 63, 433);
4651     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
4652     color = getPixelColor(device, 66, 433);
4653     ok(color == 0x00ff0000, "Pixel 578/49 has color %08x, expected 0x00ff0000\n", color);
4654     color = getPixelColor(device, 66, 430);
4655     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
4656
4657     color = getPixelColor(device, 578, 430);
4658     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
4659     color = getPixelColor(device, 578, 433);
4660     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
4661     color = getPixelColor(device, 575, 433);
4662     ok(color == 0x00ff0000, "Pixel 578/49 has color %08x, expected 0x00ff0000\n", color);
4663     color = getPixelColor(device, 575, 430);
4664     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
4665
4666     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4667     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4668
4669     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4670     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4671     IDirect3DPixelShader9_Release(shader);
4672
4673     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
4674     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4675     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_20, &shader);
4676     if(FAILED(hr)) {
4677         skip("Failed to create 2.0 test shader, most likely not supported\n");
4678         return;
4679     }
4680
4681     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4682     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4683     hr = IDirect3DDevice9_BeginScene(device);
4684     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4685     if(SUCCEEDED(hr))
4686     {
4687         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 7 * sizeof(float));
4688         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4689         hr = IDirect3DDevice9_EndScene(device);
4690         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4691     }
4692
4693     color = getPixelColor(device, 63, 46);
4694     ok(color == 0x00ffff00, "Pixel 63/46 has color %08x, expected 0x00ffff00\n", color);
4695     color = getPixelColor(device, 66, 46);
4696     ok(color == 0x00ffff00, "Pixel 66/64 has color %08x, expected 0x00ffff00\n", color);
4697     color = getPixelColor(device, 63, 49);
4698     ok(color == 0x00ffff00, "Pixel 63/49 has color %08x, expected 0x00ffff00\n", color);
4699     color = getPixelColor(device, 66, 49);
4700     ok(color == 0x000000ff, "Pixel 66/49 has color %08x, expected 0x000000ff\n", color);
4701
4702     color = getPixelColor(device, 578, 46);
4703     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
4704     color = getPixelColor(device, 575, 46);
4705     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
4706     color = getPixelColor(device, 578, 49);
4707     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
4708     color = getPixelColor(device, 575, 49);
4709     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
4710
4711     color = getPixelColor(device, 63, 430);
4712     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
4713     color = getPixelColor(device, 63, 433);
4714     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
4715     color = getPixelColor(device, 66, 433);
4716     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
4717     color = getPixelColor(device, 66, 430);
4718     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
4719
4720     color = getPixelColor(device, 578, 430);
4721     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
4722     color = getPixelColor(device, 578, 433);
4723     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
4724     color = getPixelColor(device, 575, 433);
4725     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
4726     color = getPixelColor(device, 575, 430);
4727     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
4728
4729     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4730     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4731
4732     /* Cleanup */
4733     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4734     ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
4735     IDirect3DPixelShader9_Release(shader);
4736 }
4737
4738 static void x8l8v8u8_test(IDirect3DDevice9 *device)
4739 {
4740     IDirect3D9 *d3d9;
4741     HRESULT hr;
4742     IDirect3DTexture9 *texture;
4743     IDirect3DPixelShader9 *shader;
4744     IDirect3DPixelShader9 *shader2;
4745     D3DLOCKED_RECT lr;
4746     DWORD color;
4747     DWORD shader_code[] = {
4748         0xffff0101,                             /* ps_1_1       */
4749         0x00000042, 0xb00f0000,                 /* tex t0       */
4750         0x00000001, 0x800f0000, 0xb0e40000,     /* mov r0, t0   */
4751         0x0000ffff                              /* end          */
4752     };
4753     DWORD shader_code2[] = {
4754         0xffff0101,                             /* ps_1_1       */
4755         0x00000042, 0xb00f0000,                 /* tex t0       */
4756         0x00000001, 0x800f0000, 0xb0ff0000,     /* mov r0, t0.w */
4757         0x0000ffff                              /* end          */
4758     };
4759
4760     float quad[] = {
4761        -1.0,   -1.0,   0.1,     0.5,    0.5,
4762         1.0,   -1.0,   0.1,     0.5,    0.5,
4763        -1.0,    1.0,   0.1,     0.5,    0.5,
4764         1.0,    1.0,   0.1,     0.5,    0.5,
4765     };
4766
4767     memset(&lr, 0, sizeof(lr));
4768     IDirect3DDevice9_GetDirect3D(device, &d3d9);
4769     hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4770                                       0,  D3DRTYPE_TEXTURE, D3DFMT_X8L8V8U8);
4771     IDirect3D9_Release(d3d9);
4772     if(FAILED(hr)) {
4773         skip("No D3DFMT_X8L8V8U8 support\n");
4774         return;
4775     };
4776
4777     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
4778     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4779
4780     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_X8L8V8U8, D3DPOOL_MANAGED, &texture, NULL);
4781     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed (%08x)\n", hr);
4782     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
4783     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed (%08x)\n", hr);
4784     *((DWORD *) lr.pBits) = 0x11ca3141;
4785     hr = IDirect3DTexture9_UnlockRect(texture, 0);
4786     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed (%08x)\n", hr);
4787
4788     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
4789     ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr);
4790     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code2, &shader2);
4791     ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr);
4792
4793     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4794     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed (%08x)\n", hr);
4795     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4796     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4797     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
4798     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
4799
4800     hr = IDirect3DDevice9_BeginScene(device);
4801     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4802     if(SUCCEEDED(hr))
4803     {
4804         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
4805         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4806
4807         hr = IDirect3DDevice9_EndScene(device);
4808         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4809     }
4810     color = getPixelColor(device, 578, 430);
4811     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x82, 0x62, 0xca), 1),
4812        "D3DFMT_X8L8V8U8 = 0x112131ca returns color %08x, expected 0x008262ca\n", color);
4813     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4814     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4815
4816     hr = IDirect3DDevice9_SetPixelShader(device, shader2);
4817     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4818     hr = IDirect3DDevice9_BeginScene(device);
4819     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4820     if(SUCCEEDED(hr))
4821     {
4822         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
4823         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4824
4825         hr = IDirect3DDevice9_EndScene(device);
4826         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4827     }
4828     color = getPixelColor(device, 578, 430);
4829     ok(color == 0x00ffffff, "w component of D3DFMT_X8L8V8U8 = 0x11ca3141 returns color %08x\n", color);
4830     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4831     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4832
4833     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4834     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4835     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4836     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
4837     IDirect3DPixelShader9_Release(shader);
4838     IDirect3DPixelShader9_Release(shader2);
4839     IDirect3DTexture9_Release(texture);
4840 }
4841
4842 static void autogen_mipmap_test(IDirect3DDevice9 *device)
4843 {
4844     HRESULT hr;
4845     IDirect3D9 *d3d;
4846     IDirect3DTexture9 *texture = NULL;
4847     IDirect3DSurface9 *surface;
4848     DWORD color;
4849     const RECT r1 = {256, 256, 512, 512};
4850     const RECT r2 = {512, 256, 768, 512};
4851     const RECT r3 = {256, 512, 512, 768};
4852     const RECT r4 = {512, 512, 768, 768};
4853     unsigned int x, y;
4854     D3DLOCKED_RECT lr;
4855     memset(&lr, 0, sizeof(lr));
4856
4857     IDirect3DDevice9_GetDirect3D(device, &d3d);
4858     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4859        D3DUSAGE_AUTOGENMIPMAP,  D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8) != D3D_OK) {
4860         skip("No autogenmipmap support\n");
4861         IDirect3D9_Release(d3d);
4862         return;
4863     }
4864     IDirect3D9_Release(d3d);
4865
4866     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
4867     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4868
4869     /* Make the mipmap big, so that a smaller mipmap is used
4870      */
4871     hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 0, D3DUSAGE_AUTOGENMIPMAP,
4872                                         D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4873     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
4874
4875     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
4876     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel returned %08x\n", hr);
4877     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
4878     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
4879     for(y = 0; y < 1024; y++) {
4880         for(x = 0; x < 1024; x++) {
4881             DWORD *dst = (DWORD *) (((BYTE *) lr.pBits) + y * lr.Pitch + x * 4);
4882             POINT pt;
4883
4884             pt.x = x;
4885             pt.y = y;
4886             if(PtInRect(&r1, pt)) {
4887                 *dst = 0xffff0000;
4888             } else if(PtInRect(&r2, pt)) {
4889                 *dst = 0xff00ff00;
4890             } else if(PtInRect(&r3, pt)) {
4891                 *dst = 0xff0000ff;
4892             } else if(PtInRect(&r4, pt)) {
4893                 *dst = 0xff000000;
4894             } else {
4895                 *dst = 0xffffffff;
4896             }
4897         }
4898     }
4899     hr = IDirect3DSurface9_UnlockRect(surface);
4900     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect returned %08x\n", hr);
4901     IDirect3DSurface9_Release(surface);
4902
4903     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
4904     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
4905     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
4906     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
4907
4908     hr = IDirect3DDevice9_BeginScene(device);
4909     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4910     if(SUCCEEDED(hr)) {
4911         const float quad[] =  {
4912            -0.5,   -0.5,    0.1,    0.0,    0.0,
4913            -0.5,    0.5,    0.1,    0.0,    1.0,
4914             0.5,   -0.5,    0.1,    1.0,    0.0,
4915             0.5,    0.5,    0.1,    1.0,    1.0
4916         };
4917
4918         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4919         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
4920         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
4921         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4922         hr = IDirect3DDevice9_EndScene(device);
4923         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4924     }
4925     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4926     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
4927     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
4928     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
4929     IDirect3DTexture9_Release(texture);
4930
4931     color = getPixelColor(device, 200, 200);
4932     ok(color == 0x00ffffff, "pixel 200/200 has color %08x, expected 0x00ffffff\n", color);
4933     color = getPixelColor(device, 280, 200);
4934     ok(color == 0x000000ff, "pixel 280/200 has color %08x, expected 0x000000ff\n", color);
4935     color = getPixelColor(device, 360, 200);
4936     ok(color == 0x00000000, "pixel 360/200 has color %08x, expected 0x00000000\n", color);
4937     color = getPixelColor(device, 440, 200);
4938     ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
4939     color = getPixelColor(device, 200, 270);
4940     ok(color == 0x00ffffff, "pixel 200/270 has color %08x, expected 0x00ffffff\n", color);
4941     color = getPixelColor(device, 280, 270);
4942     ok(color == 0x00ff0000, "pixel 280/270 has color %08x, expected 0x00ff0000\n", color);
4943     color = getPixelColor(device, 360, 270);
4944     ok(color == 0x0000ff00, "pixel 360/270 has color %08x, expected 0x0000ff00\n", color);
4945     color = getPixelColor(device, 440, 270);
4946     ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
4947     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4948     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4949 }
4950
4951 static void test_constant_clamp_vs(IDirect3DDevice9 *device)
4952 {
4953     IDirect3DVertexShader9 *shader_11, *shader_11_2, *shader_20, *shader_20_2;
4954     IDirect3DVertexDeclaration9 *decl;
4955     HRESULT hr;
4956     DWORD color;
4957     DWORD shader_code_11[] =  {
4958         0xfffe0101,                                         /* vs_1_1           */
4959         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4960         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4961         0x00000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4962         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4963         0x0000ffff                                          /* end              */
4964     };
4965     DWORD shader_code_11_2[] =  {
4966         0xfffe0101,                                         /* vs_1_1           */
4967         0x00000051, 0xa00f0001, 0x3fa00000, 0xbf000000, 0xbfc00000, 0x3f800000, /* dcl ... */
4968         0x00000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000, /* dcl ... */
4969         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4970         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4971         0x00000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4972         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4973         0x0000ffff                                          /* end              */
4974     };
4975     DWORD shader_code_20[] =  {
4976         0xfffe0200,                                         /* vs_2_0           */
4977         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4978         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4979         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4980         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4981         0x0000ffff                                          /* end              */
4982     };
4983     DWORD shader_code_20_2[] =  {
4984         0xfffe0200,                                         /* vs_2_0           */
4985         0x05000051, 0xa00f0001, 0x3fa00000, 0xbf000000, 0xbfc00000, 0x3f800000,
4986         0x05000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000,
4987         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4988         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4989         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4990         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4991         0x0000ffff                                          /* end              */
4992     };
4993     static const D3DVERTEXELEMENT9 decl_elements[] = {
4994         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4995         D3DDECL_END()
4996     };
4997     float quad1[] = {
4998         -1.0,   -1.0,   0.1,
4999          0.0,   -1.0,   0.1,
5000         -1.0,    0.0,   0.1,
5001          0.0,    0.0,   0.1
5002     };
5003     float quad2[] = {
5004          0.0,   -1.0,   0.1,
5005          1.0,   -1.0,   0.1,
5006          0.0,    0.0,   0.1,
5007          1.0,    0.0,   0.1
5008     };
5009     float quad3[] = {
5010          0.0,    0.0,   0.1,
5011          1.0,    0.0,   0.1,
5012          0.0,    1.0,   0.1,
5013          1.0,    1.0,   0.1
5014     };
5015     float quad4[] = {
5016         -1.0,    0.0,   0.1,
5017          0.0,    0.0,   0.1,
5018         -1.0,    1.0,   0.1,
5019          0.0,    1.0,   0.1
5020     };
5021     float test_data_c1[4] = {  1.25, -0.50, -1.50, 1.0};
5022     float test_data_c2[4] = { -0.50,  1.25,  2.00, 1.0};
5023
5024     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
5025     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5026
5027     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_11, &shader_11);
5028     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5029     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_11_2, &shader_11_2);
5030     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5031     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_20, &shader_20);
5032     if(FAILED(hr)) shader_20 = NULL;
5033     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_20_2, &shader_20_2);
5034     if(FAILED(hr)) shader_20_2 = NULL;
5035     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
5036     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
5037
5038     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, test_data_c1, 1);
5039     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned %08x\n", hr);
5040     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 2, test_data_c2, 1);
5041     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned %08x\n", hr);
5042     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
5043     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
5044
5045     hr = IDirect3DDevice9_BeginScene(device);
5046     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5047     if(SUCCEEDED(hr))
5048     {
5049         hr = IDirect3DDevice9_SetVertexShader(device, shader_11);
5050         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5051         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 3 * sizeof(float));
5052         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5053
5054         hr = IDirect3DDevice9_SetVertexShader(device, shader_11_2);
5055         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5056         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
5057         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5058
5059         if(shader_20) {
5060             hr = IDirect3DDevice9_SetVertexShader(device, shader_20);
5061             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5062             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 3 * sizeof(float));
5063             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5064         }
5065
5066         if(shader_20_2) {
5067             hr = IDirect3DDevice9_SetVertexShader(device, shader_20_2);
5068             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5069             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 3 * sizeof(float));
5070             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5071         }
5072
5073         hr = IDirect3DDevice9_EndScene(device);
5074         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5075     }
5076
5077     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
5078     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5079     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
5080     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
5081
5082     color = getPixelColor(device, 160, 360);
5083     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0xbf, 0x80), 1),
5084        "quad 1 has color %08x, expected 0x00bfbf80\n", color);
5085     color = getPixelColor(device, 480, 360);
5086     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0xbf, 0x80), 1),
5087        "quad 2 has color %08x, expected 0x00bfbf80\n", color);
5088     if(shader_20) {
5089         color = getPixelColor(device, 480, 120);
5090         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0xbf, 0x80), 1),
5091            "quad 3 has color %08x, expected 0x00bfbf80\n", color);
5092     }
5093     if(shader_20_2) {
5094         color = getPixelColor(device, 160, 120);
5095         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0xbf, 0x80), 1),
5096            "quad 4 has color %08x, expected 0x00bfbf80\n", color);
5097     }
5098     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5099     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5100
5101     IDirect3DVertexDeclaration9_Release(decl);
5102     if(shader_20_2) IDirect3DVertexShader9_Release(shader_20_2);
5103     if(shader_20) IDirect3DVertexShader9_Release(shader_20);
5104     IDirect3DVertexShader9_Release(shader_11_2);
5105     IDirect3DVertexShader9_Release(shader_11);
5106 }
5107
5108 static void constant_clamp_ps_test(IDirect3DDevice9 *device)
5109 {
5110     IDirect3DPixelShader9 *shader_11, *shader_12, *shader_14, *shader_20;
5111     HRESULT hr;
5112     DWORD color;
5113     DWORD shader_code_11[] =  {
5114         0xffff0101,                                         /* ps_1_1           */
5115         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
5116         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
5117         0x0000ffff                                          /* end              */
5118     };
5119     DWORD shader_code_12[] =  {
5120         0xffff0102,                                         /* ps_1_2           */
5121         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
5122         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
5123         0x0000ffff                                          /* end              */
5124     };
5125     /* Skip 1.3 shaders because we have only 4 quads(ok, could make them smaller if needed).
5126      * 1.2 and 1.4 shaders behave the same, so it's unlikely that 1.3 shaders are different.
5127      * During development of this test, 1.3 shaders were verified too
5128      */
5129     DWORD shader_code_14[] =  {
5130         0xffff0104,                                         /* ps_1_4           */
5131         /* Try to make one constant local. It gets clamped too, although the binary contains
5132          * the bigger numbers
5133          */
5134         0x00000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000, /* def c2, -0.5, 1.25, 2, 1 */
5135         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
5136         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
5137         0x0000ffff                                          /* end              */
5138     };
5139     DWORD shader_code_20[] =  {
5140         0xffff0200,                                         /* ps_2_0           */
5141         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
5142         0x03000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
5143         0x02000001, 0x800f0800, 0x80e40000,                 /* mov oC0, r0      */
5144         0x0000ffff                                          /* end              */
5145     };
5146     float quad1[] = {
5147         -1.0,   -1.0,   0.1,
5148          0.0,   -1.0,   0.1,
5149         -1.0,    0.0,   0.1,
5150          0.0,    0.0,   0.1
5151     };
5152     float quad2[] = {
5153          0.0,   -1.0,   0.1,
5154          1.0,   -1.0,   0.1,
5155          0.0,    0.0,   0.1,
5156          1.0,    0.0,   0.1
5157     };
5158     float quad3[] = {
5159          0.0,    0.0,   0.1,
5160          1.0,    0.0,   0.1,
5161          0.0,    1.0,   0.1,
5162          1.0,    1.0,   0.1
5163     };
5164     float quad4[] = {
5165         -1.0,    0.0,   0.1,
5166          0.0,    0.0,   0.1,
5167         -1.0,    1.0,   0.1,
5168          0.0,    1.0,   0.1
5169     };
5170     float test_data_c1[4] = {  1.25, -0.50, -1.50, 1.0};
5171     float test_data_c2[4] = { -0.50,  1.25,  2.00, 1.0};
5172
5173     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
5174     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5175
5176     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader_11);
5177     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5178     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12, &shader_12);
5179     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5180     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14, &shader_14);
5181     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5182     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_20, &shader_20);
5183     if(FAILED(hr)) shader_20 = NULL;
5184
5185     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1, 1);
5186     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
5187     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2, 1);
5188     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
5189     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5190     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
5191
5192     hr = IDirect3DDevice9_BeginScene(device);
5193     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5194     if(SUCCEEDED(hr))
5195     {
5196         hr = IDirect3DDevice9_SetPixelShader(device, shader_11);
5197         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5198         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 3 * sizeof(float));
5199         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5200
5201         hr = IDirect3DDevice9_SetPixelShader(device, shader_12);
5202         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5203         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
5204         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5205
5206         hr = IDirect3DDevice9_SetPixelShader(device, shader_14);
5207         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5208         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 3 * sizeof(float));
5209         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5210
5211         if(shader_20) {
5212             hr = IDirect3DDevice9_SetPixelShader(device, shader_20);
5213             ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5214             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 3 * sizeof(float));
5215             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5216         }
5217
5218         hr = IDirect3DDevice9_EndScene(device);
5219         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5220     }
5221     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5222     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5223
5224     color = getPixelColor(device, 160, 360);
5225     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x80, 0x80, 0x00), 1),
5226        "quad 1 has color %08x, expected 0x00808000\n", color);
5227     color = getPixelColor(device, 480, 360);
5228     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x80, 0x80, 0x00), 1),
5229        "quad 2 has color %08x, expected 0x00808000\n", color);
5230     color = getPixelColor(device, 480, 120);
5231     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x80, 0x80, 0x00), 1),
5232        "quad 3 has color %08x, expected 0x00808000\n", color);
5233     if(shader_20) {
5234         color = getPixelColor(device, 160, 120);
5235         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0xbf, 0x80), 1),
5236            "quad 4 has color %08x, expected 0x00bfbf80\n", color);
5237     }
5238     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5239     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5240
5241     if(shader_20) IDirect3DPixelShader9_Release(shader_20);
5242     IDirect3DPixelShader9_Release(shader_14);
5243     IDirect3DPixelShader9_Release(shader_12);
5244     IDirect3DPixelShader9_Release(shader_11);
5245 }
5246
5247 static void dp2add_ps_test(IDirect3DDevice9 *device)
5248 {
5249     IDirect3DPixelShader9 *shader_dp2add = NULL;
5250     IDirect3DPixelShader9 *shader_dp2add_sat = NULL;
5251     HRESULT hr;
5252     DWORD color;
5253
5254     /* DP2ADD is defined as:  (src0.r * src1.r) + (src0.g * src1.g) + src2.
5255      * One D3D restriction of all shader instructions except SINCOS is that no more than 2
5256      * source tokens can be constants.  So, for this exercise, we move contents of c0 to
5257      * r0 first.
5258      * The result here for the r,g,b components should be roughly 0.5:
5259      *   (0.5 * 0.5) + (0.5 * 0.5) + 0.0 = 0.5 */
5260     static const DWORD shader_code_dp2add[] =  {
5261         0xffff0200,                                                             /* ps_2_0                       */
5262         0x05000051, 0xa00f0000, 0x3f000000, 0x3f000000, 0x3f800000, 0x00000000, /* def c0, 0.5, 0.5, 1.0, 0     */
5263
5264         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                   */
5265         0x0400005a, 0x80070000, 0x80000000, 0x80000000, 0x80ff0000,             /* dp2add r0.rgb, r0, r0, r0.a  */
5266
5267         0x02000001, 0x80080000, 0xa0aa0000,                                     /* mov r0.a, c0.b               */
5268         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
5269         0x0000ffff                                                              /* end                          */
5270     };
5271
5272     /* Test the _sat modifier, too.  Result here should be:
5273      *   DP2: (-0.5 * -0.5) + (-0.5 * -0.5) + 2.0 = 2.5
5274      *      _SAT: ==> 1.0
5275      *   ADD: (1.0 + -0.5) = 0.5
5276      */
5277     static const DWORD shader_code_dp2add_sat[] =  {
5278         0xffff0200,                                                             /* ps_2_0                           */
5279         0x05000051, 0xa00f0000, 0xbf000000, 0xbf000000, 0x3f800000, 0x40000000, /* def c0, -0.5, -0.5, 1.0, 2.0     */
5280
5281         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                       */
5282         0x0400005a, 0x80170000, 0x80000000, 0x80000000, 0x80ff0000,             /* dp2add_sat r0.rgb, r0, r0, r0.a  */
5283         0x03000002, 0x80070000, 0x80e40000, 0xa0000000,                         /* add r0.rgb, r0, c0.r             */
5284
5285         0x02000001, 0x80080000, 0xa0aa0000,                                     /* mov r0.a, c0.b                   */
5286         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                      */
5287         0x0000ffff                                                              /* end                              */
5288     };
5289
5290     const float quad[] = {
5291         -1.0,   -1.0,   0.1,
5292          1.0,   -1.0,   0.1,
5293         -1.0,    1.0,   0.1,
5294          1.0,    1.0,   0.1
5295     };
5296
5297
5298     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
5299     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5300
5301     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_dp2add, &shader_dp2add);
5302     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5303
5304     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_dp2add_sat, &shader_dp2add_sat);
5305     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5306
5307     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5308     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
5309
5310     if (shader_dp2add) {
5311
5312         hr = IDirect3DDevice9_SetPixelShader(device, shader_dp2add);
5313         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5314
5315         hr = IDirect3DDevice9_BeginScene(device);
5316         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5317         if(SUCCEEDED(hr))
5318         {
5319             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
5320             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5321
5322             hr = IDirect3DDevice9_EndScene(device);
5323             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5324         }
5325
5326         color = getPixelColor(device, 360, 240);
5327         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x7f, 0x7f, 0x7f), 1),
5328                 "dp2add pixel has color %08x, expected ~0x007f7f7f\n", color);
5329
5330         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5331         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5332
5333         IDirect3DPixelShader9_Release(shader_dp2add);
5334     } else {
5335         skip("dp2add shader creation failed\n");
5336     }
5337
5338     if (shader_dp2add_sat) {
5339
5340         hr = IDirect3DDevice9_SetPixelShader(device, shader_dp2add_sat);
5341         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5342
5343         hr = IDirect3DDevice9_BeginScene(device);
5344         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5345         if(SUCCEEDED(hr))
5346         {
5347             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
5348             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5349
5350             hr = IDirect3DDevice9_EndScene(device);
5351             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5352         }
5353
5354         color = getPixelColor(device, 360, 240);
5355         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x7f, 0x7f, 0x7f), 1),
5356                 "dp2add pixel has color %08x, expected ~0x007f7f7f\n", color);
5357
5358         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5359         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5360
5361         IDirect3DPixelShader9_Release(shader_dp2add_sat);
5362     } else {
5363         skip("dp2add shader creation failed\n");
5364     }
5365
5366     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5367     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5368 }
5369
5370 static void cnd_test(IDirect3DDevice9 *device)
5371 {
5372     IDirect3DPixelShader9 *shader_11, *shader_12, *shader_13, *shader_14;
5373     IDirect3DPixelShader9 *shader_11_coissue, *shader_12_coissue, *shader_13_coissue, *shader_14_coissue;
5374     HRESULT hr;
5375     DWORD color;
5376     /* ps 1.x shaders are rather picky with writemasks and source swizzles. The dp3 is
5377      * used to copy r0.r to all components of r1, then copy r1.a to c0.a. Essentially it
5378      * does a mov r0.a, r0.r, which isn't allowed as-is in 1.x pixel shaders.
5379      */
5380     DWORD shader_code_11[] =  {
5381         0xffff0101,                                                                 /* ps_1_1               */
5382         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
5383         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
5384         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, ???(t0)      */
5385         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3 r1, r0, c0       */
5386         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
5387         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
5388         0x0000ffff                                                                  /* end                  */
5389     };
5390     DWORD shader_code_12[] =  {
5391         0xffff0102,                                                                 /* ps_1_2               */
5392         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
5393         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
5394         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, t0           */
5395         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3 r1, r0, c0       */
5396         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
5397         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
5398         0x0000ffff                                                                  /* end                  */
5399     };
5400     DWORD shader_code_13[] =  {
5401         0xffff0103,                                                                 /* ps_1_3               */
5402         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
5403         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
5404         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, t0           */
5405         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3, r1, r0, c0      */
5406         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
5407         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
5408         0x0000ffff                                                                  /* end                  */
5409     };
5410     DWORD shader_code_14[] =  {
5411         0xffff0104,                                                                 /* ps_1_3               */
5412         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,     /* def c0, 0, 0, 0, 1   */
5413         0x00000040, 0x80070000, 0xb0e40000,                                         /* texcrd r0, t0        */
5414         0x00000001, 0x80080000, 0xa0ff0000,                                         /* mov r0.a, c0.a       */
5415         0x00000050, 0x800f0000, 0x80e40000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0, c1, c2   */
5416         0x0000ffff                                                                  /* end                  */
5417     };
5418
5419     /* Special fun: The coissue flag on cnd: Apparently cnd always selects the 2nd source,
5420      * as if the src0 comparison against 0.5 always evaluates to true. The coissue flag isn't
5421      * set by the compiler, it was added manually after compilation. Note that the COISSUE
5422      * flag on a color(.xyz) operation is only allowed after an alpha operation. DirectX doesn't
5423      * have proper docs, but GL_ATI_fragment_shader explains the pairing of color and alpha ops
5424      * well enough.
5425      *
5426      * The shader attempts to test the range [-1;1] against coissued cnd, which is a bit tricky.
5427      * The input from t0 is [0;1]. 0.5 is subtracted, then we have to multiply with 2. Since
5428      * constants are clamped to [-1;1], a 2.0 is constructed by adding c0.r(=1.0) to c0.r into r1.r,
5429      * then r1(2.0, 0.0, 0.0, 0.0) is passed to dp3(explained above).
5430      */
5431     DWORD shader_code_11_coissue[] =  {
5432         0xffff0101,                                                             /* ps_1_1                   */
5433         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
5434         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
5435         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
5436         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
5437         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
5438         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
5439         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
5440         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
5441         /* 0x40000000 = D3DSI_COISSUE */
5442         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
5443         0x0000ffff                                                              /* end                      */
5444     };
5445     DWORD shader_code_12_coissue[] =  {
5446         0xffff0102,                                                             /* ps_1_2                   */
5447         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
5448         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
5449         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
5450         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
5451         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
5452         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
5453         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
5454         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
5455         /* 0x40000000 = D3DSI_COISSUE */
5456         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
5457         0x0000ffff                                                              /* end                      */
5458     };
5459     DWORD shader_code_13_coissue[] =  {
5460         0xffff0103,                                                             /* ps_1_3                   */
5461         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
5462         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
5463         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
5464         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
5465         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
5466         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
5467         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
5468         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
5469         /* 0x40000000 = D3DSI_COISSUE */
5470         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
5471         0x0000ffff                                                              /* end                      */
5472     };
5473     /* ps_1_4 does not have a different cnd behavior, just pass the [0;1] texcrd result to cnd, it will
5474      * compare against 0.5
5475      */
5476     DWORD shader_code_14_coissue[] =  {
5477         0xffff0104,                                                             /* ps_1_4                   */
5478         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0, 0, 0, 1       */
5479         0x00000040, 0x80070000, 0xb0e40000,                                     /* texcrd r0, t0            */
5480         0x00000001, 0x80080000, 0xa0ff0000,                                     /* mov r0.a, c0.a           */
5481         /* 0x40000000 = D3DSI_COISSUE */
5482         0x40000050, 0x80070000, 0x80e40000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0, c1, c2   */
5483         0x0000ffff                                                              /* end                      */
5484     };
5485     float quad1[] = {
5486         -1.0,   -1.0,   0.1,     0.0,    0.0,    1.0,
5487          0.0,   -1.0,   0.1,     1.0,    0.0,    1.0,
5488         -1.0,    0.0,   0.1,     0.0,    1.0,    0.0,
5489          0.0,    0.0,   0.1,     1.0,    1.0,    0.0
5490     };
5491     float quad2[] = {
5492          0.0,   -1.0,   0.1,     0.0,    0.0,    1.0,
5493          1.0,   -1.0,   0.1,     1.0,    0.0,    1.0,
5494          0.0,    0.0,   0.1,     0.0,    1.0,    0.0,
5495          1.0,    0.0,   0.1,     1.0,    1.0,    0.0
5496     };
5497     float quad3[] = {
5498          0.0,    0.0,   0.1,     0.0,    0.0,    1.0,
5499          1.0,    0.0,   0.1,     1.0,    0.0,    1.0,
5500          0.0,    1.0,   0.1,     0.0,    1.0,    0.0,
5501          1.0,    1.0,   0.1,     1.0,    1.0,    0.0
5502     };
5503     float quad4[] = {
5504         -1.0,    0.0,   0.1,     0.0,    0.0,    1.0,
5505          0.0,    0.0,   0.1,     1.0,    0.0,    1.0,
5506         -1.0,    1.0,   0.1,     0.0,    1.0,    0.0,
5507          0.0,    1.0,   0.1,     1.0,    1.0,    0.0
5508     };
5509     float test_data_c1[4] = {  0.0, 0.0, 0.0, 0.0};
5510     float test_data_c2[4] = {  1.0, 1.0, 1.0, 1.0};
5511     float test_data_c1_coi[4] = {  0.0, 1.0, 0.0, 0.0};
5512     float test_data_c2_coi[4] = {  1.0, 0.0, 1.0, 1.0};
5513
5514     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
5515     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5516
5517     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader_11);
5518     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5519     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12, &shader_12);
5520     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5521     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_13, &shader_13);
5522     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5523     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14, &shader_14);
5524     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5525     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11_coissue, &shader_11_coissue);
5526     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5527     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12_coissue, &shader_12_coissue);
5528     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5529     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_13_coissue, &shader_13_coissue);
5530     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5531     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14_coissue, &shader_14_coissue);
5532     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5533
5534     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1, 1);
5535     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
5536     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2, 1);
5537     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
5538     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
5539     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
5540
5541     hr = IDirect3DDevice9_BeginScene(device);
5542     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5543     if(SUCCEEDED(hr))
5544     {
5545         hr = IDirect3DDevice9_SetPixelShader(device, shader_11);
5546         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5547         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
5548         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5549
5550         hr = IDirect3DDevice9_SetPixelShader(device, shader_12);
5551         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5552         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
5553         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5554
5555         hr = IDirect3DDevice9_SetPixelShader(device, shader_13);
5556         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5557         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 6 * sizeof(float));
5558         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5559
5560         hr = IDirect3DDevice9_SetPixelShader(device, shader_14);
5561         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5562         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
5563         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5564
5565         hr = IDirect3DDevice9_EndScene(device);
5566         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5567     }
5568
5569     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5570     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5571
5572     /* This is the 1.4 test. Each component(r, g, b) is tested separately against 0.5 */
5573     color = getPixelColor(device, 158, 118);
5574     ok(color == 0x00ff00ff, "pixel 158, 118 has color %08x, expected 0x00ff00ff\n", color);
5575     color = getPixelColor(device, 162, 118);
5576     ok(color == 0x000000ff, "pixel 162, 118 has color %08x, expected 0x000000ff\n", color);
5577     color = getPixelColor(device, 158, 122);
5578     ok(color == 0x00ffffff, "pixel 162, 122 has color %08x, expected 0x00ffffff\n", color);
5579     color = getPixelColor(device, 162, 122);
5580     ok(color == 0x0000ffff, "pixel 162, 122 has color %08x, expected 0x0000ffff\n", color);
5581
5582     /* 1.1 shader. All 3 components get set, based on the .w comparison */
5583     color = getPixelColor(device, 158, 358);
5584     ok(color == 0x00ffffff, "pixel 158, 358 has color %08x, expected 0x00ffffff\n", color);
5585     color = getPixelColor(device, 162, 358);
5586     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
5587         "pixel 162, 358 has color %08x, expected 0x00000000\n", color);
5588     color = getPixelColor(device, 158, 362);
5589     ok(color == 0x00ffffff, "pixel 158, 362 has color %08x, expected 0x00ffffff\n", color);
5590     color = getPixelColor(device, 162, 362);
5591     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
5592         "pixel 162, 362 has color %08x, expected 0x00000000\n", color);
5593
5594     /* 1.2 shader */
5595     color = getPixelColor(device, 478, 358);
5596     ok(color == 0x00ffffff, "pixel 478, 358 has color %08x, expected 0x00ffffff\n", color);
5597     color = getPixelColor(device, 482, 358);
5598     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
5599         "pixel 482, 358 has color %08x, expected 0x00000000\n", color);
5600     color = getPixelColor(device, 478, 362);
5601     ok(color == 0x00ffffff, "pixel 478, 362 has color %08x, expected 0x00ffffff\n", color);
5602     color = getPixelColor(device, 482, 362);
5603     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
5604         "pixel 482, 362 has color %08x, expected 0x00000000\n", color);
5605
5606     /* 1.3 shader */
5607     color = getPixelColor(device, 478, 118);
5608     ok(color == 0x00ffffff, "pixel 478, 118 has color %08x, expected 0x00ffffff\n", color);
5609     color = getPixelColor(device, 482, 118);
5610     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
5611         "pixel 482, 118 has color %08x, expected 0x00000000\n", color);
5612     color = getPixelColor(device, 478, 122);
5613     ok(color == 0x00ffffff, "pixel 478, 122 has color %08x, expected 0x00ffffff\n", color);
5614     color = getPixelColor(device, 482, 122);
5615     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
5616         "pixel 482, 122 has color %08x, expected 0x00000000\n", color);
5617
5618     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5619     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5620
5621     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
5622     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5623     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1_coi, 1);
5624     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
5625     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2_coi, 1);
5626     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
5627
5628     hr = IDirect3DDevice9_BeginScene(device);
5629     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5630     if(SUCCEEDED(hr))
5631     {
5632         hr = IDirect3DDevice9_SetPixelShader(device, shader_11_coissue);
5633         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5634         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
5635         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5636
5637         hr = IDirect3DDevice9_SetPixelShader(device, shader_12_coissue);
5638         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5639         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
5640         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5641
5642         hr = IDirect3DDevice9_SetPixelShader(device, shader_13_coissue);
5643         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5644         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 6 * sizeof(float));
5645         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5646
5647         hr = IDirect3DDevice9_SetPixelShader(device, shader_14_coissue);
5648         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5649         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
5650         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5651
5652         hr = IDirect3DDevice9_EndScene(device);
5653         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5654     }
5655
5656     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5657     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5658
5659     /* This is the 1.4 test. The coissue doesn't change the behavior here, but keep in mind
5660      * that we swapped the values in c1 and c2 to make the other tests return some color
5661      */
5662     color = getPixelColor(device, 158, 118);
5663     ok(color == 0x00ffffff, "pixel 158, 118 has color %08x, expected 0x00ffffff\n", color);
5664     color = getPixelColor(device, 162, 118);
5665     ok(color == 0x0000ffff, "pixel 162, 118 has color %08x, expected 0x0000ffff\n", color);
5666     color = getPixelColor(device, 158, 122);
5667     ok(color == 0x00ff00ff, "pixel 162, 122 has color %08x, expected 0x00ff00ff\n", color);
5668     color = getPixelColor(device, 162, 122);
5669     ok(color == 0x000000ff, "pixel 162, 122 has color %08x, expected 0x000000ff\n", color);
5670
5671     /* 1.1 shader. coissue flag changed the semantic of cnd, c1 is always selected
5672      * (The Win7 nvidia driver always selects c2)
5673      */
5674     color = getPixelColor(device, 158, 358);
5675     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5676         "pixel 158, 358 has color %08x, expected 0x0000ff00\n", color);
5677     color = getPixelColor(device, 162, 358);
5678     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5679         "pixel 162, 358 has color %08x, expected 0x0000ff00\n", color);
5680     color = getPixelColor(device, 158, 362);
5681     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5682         "pixel 158, 362 has color %08x, expected 0x0000ff00\n", color);
5683     color = getPixelColor(device, 162, 362);
5684     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5685         "pixel 162, 362 has color %08x, expected 0x0000ff00\n", color);
5686
5687     /* 1.2 shader */
5688     color = getPixelColor(device, 478, 358);
5689     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5690         "pixel 478, 358 has color %08x, expected 0x0000ff00\n", color);
5691     color = getPixelColor(device, 482, 358);
5692     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5693         "pixel 482, 358 has color %08x, expected 0x0000ff00\n", color);
5694     color = getPixelColor(device, 478, 362);
5695     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5696         "pixel 478, 362 has color %08x, expected 0x0000ff00\n", color);
5697     color = getPixelColor(device, 482, 362);
5698     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5699         "pixel 482, 362 has color %08x, expected 0x0000ff00\n", color);
5700
5701     /* 1.3 shader */
5702     color = getPixelColor(device, 478, 118);
5703     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5704         "pixel 478, 118 has color %08x, expected 0x0000ff00\n", color);
5705     color = getPixelColor(device, 482, 118);
5706     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5707         "pixel 482, 118 has color %08x, expected 0x0000ff00\n", color);
5708     color = getPixelColor(device, 478, 122);
5709     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5710         "pixel 478, 122 has color %08x, expected 0x0000ff00\n", color);
5711     color = getPixelColor(device, 482, 122);
5712     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5713         "pixel 482, 122 has color %08x, expected 0x0000ff00\n", color);
5714
5715     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5716     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5717
5718     IDirect3DPixelShader9_Release(shader_14_coissue);
5719     IDirect3DPixelShader9_Release(shader_13_coissue);
5720     IDirect3DPixelShader9_Release(shader_12_coissue);
5721     IDirect3DPixelShader9_Release(shader_11_coissue);
5722     IDirect3DPixelShader9_Release(shader_14);
5723     IDirect3DPixelShader9_Release(shader_13);
5724     IDirect3DPixelShader9_Release(shader_12);
5725     IDirect3DPixelShader9_Release(shader_11);
5726 }
5727
5728 static void nested_loop_test(IDirect3DDevice9 *device) {
5729     const DWORD shader_code[] = {
5730         0xffff0300,                                                             /* ps_3_0               */
5731         0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0, 0, 0, 1   */
5732         0x05000051, 0xa00f0001, 0x3d000000, 0x00000000, 0x00000000, 0x00000000, /* def c1, 1/32, 0, 0, 0*/
5733         0x05000030, 0xf00f0000, 0x00000004, 0x00000000, 0x00000002, 0x00000000, /* defi i0, 4, 0, 2, 0  */
5734         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0           */
5735         0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0          */
5736         0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0          */
5737         0x03000002, 0x800f0000, 0x80e40000, 0xa0e40001,                         /* add r0, r0, c1       */
5738         0x0000001d,                                                             /* endloop              */
5739         0x0000001d,                                                             /* endloop              */
5740         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0          */
5741         0x0000ffff                                                              /* end                  */
5742     };
5743     const DWORD vshader_code[] = {
5744         0xfffe0300,                                                             /* vs_3_0               */
5745         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0      */
5746         0x0200001f, 0x80000000, 0xe00f0000,                                     /* dcl_position o0      */
5747         0x02000001, 0xe00f0000, 0x90e40000,                                     /* mov o0, v0           */
5748         0x0000ffff                                                              /* end                  */
5749     };
5750     IDirect3DPixelShader9 *shader;
5751     IDirect3DVertexShader9 *vshader;
5752     HRESULT hr;
5753     DWORD color;
5754     const float quad[] = {
5755         -1.0,   -1.0,   0.1,
5756          1.0,   -1.0,   0.1,
5757         -1.0,    1.0,   0.1,
5758          1.0,    1.0,   0.1
5759     };
5760
5761     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
5762     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed with %08x\n", hr);
5763     hr = IDirect3DDevice9_SetPixelShader(device, shader);
5764     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with %08x\n", hr);
5765     hr = IDirect3DDevice9_CreateVertexShader(device, vshader_code, &vshader);
5766     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader failed with %08x\n", hr);
5767     hr = IDirect3DDevice9_SetVertexShader(device, vshader);
5768     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with %08x\n", hr);
5769     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5770     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
5771     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 0.0, 0);
5772     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5773
5774     hr = IDirect3DDevice9_BeginScene(device);
5775     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5776     if(SUCCEEDED(hr))
5777     {
5778         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
5779         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5780         hr = IDirect3DDevice9_EndScene(device);
5781         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5782     }
5783
5784     color = getPixelColor(device, 360, 240);
5785     ok(color == 0x007f0000 || color == 0x00800000 || color == 0x00810000,
5786        "Nested loop test returned color 0x%08x, expected 0x00800000\n", color);
5787
5788     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5789     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5790
5791     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5792     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with %08x\n", hr);
5793     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
5794     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with %08x\n", hr);
5795     IDirect3DPixelShader9_Release(shader);
5796     IDirect3DVertexShader9_Release(vshader);
5797 }
5798
5799 struct varying_test_struct
5800 {
5801     const DWORD             *shader_code;
5802     IDirect3DPixelShader9   *shader;
5803     DWORD                   color, color_rhw;
5804     const char              *name;
5805     BOOL                    todo, todo_rhw;
5806 };
5807
5808 struct hugeVertex
5809 {
5810     float pos_x,        pos_y,      pos_z,      rhw;
5811     float weight_1,     weight_2,   weight_3,   weight_4;
5812     float index_1,      index_2,    index_3,    index_4;
5813     float normal_1,     normal_2,   normal_3,   normal_4;
5814     float fog_1,        fog_2,      fog_3,      fog_4;
5815     float texcoord_1,   texcoord_2, texcoord_3, texcoord_4;
5816     float tangent_1,    tangent_2,  tangent_3,  tangent_4;
5817     float binormal_1,   binormal_2, binormal_3, binormal_4;
5818     float depth_1,      depth_2,    depth_3,    depth_4;
5819     DWORD diffuse, specular;
5820 };
5821
5822 static void pretransformed_varying_test(IDirect3DDevice9 *device) {
5823     /* dcl_position: fails to compile */
5824     const DWORD blendweight_code[] = {
5825         0xffff0300,                             /* ps_3_0                   */
5826         0x0200001f, 0x80000001, 0x900f0000,     /* dcl_blendweight, v0      */
5827         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5828         0x0000ffff                              /* end                      */
5829     };
5830     const DWORD blendindices_code[] = {
5831         0xffff0300,                             /* ps_3_0                   */
5832         0x0200001f, 0x80000002, 0x900f0000,     /* dcl_blendindices, v0     */
5833         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5834         0x0000ffff                              /* end                      */
5835     };
5836     const DWORD normal_code[] = {
5837         0xffff0300,                             /* ps_3_0                   */
5838         0x0200001f, 0x80000003, 0x900f0000,     /* dcl_normal, v0           */
5839         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5840         0x0000ffff                              /* end                      */
5841     };
5842     /* psize: fails? */
5843     const DWORD texcoord0_code[] = {
5844         0xffff0300,                             /* ps_3_0                   */
5845         0x0200001f, 0x80000005, 0x900f0000,     /* dcl_texcoord0, v0        */
5846         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5847         0x0000ffff                              /* end                      */
5848     };
5849     const DWORD tangent_code[] = {
5850         0xffff0300,                             /* ps_3_0                   */
5851         0x0200001f, 0x80000006, 0x900f0000,     /* dcl_tangent, v0          */
5852         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5853         0x0000ffff                              /* end                      */
5854     };
5855     const DWORD binormal_code[] = {
5856         0xffff0300,                             /* ps_3_0                   */
5857         0x0200001f, 0x80000007, 0x900f0000,     /* dcl_binormal, v0         */
5858         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5859         0x0000ffff                              /* end                      */
5860     };
5861     /* tessfactor: fails */
5862     /* positiont: fails */
5863     const DWORD color_code[] = {
5864         0xffff0300,                             /* ps_3_0                   */
5865         0x0200001f, 0x8000000a, 0x900f0000,     /* dcl_color0, v0           */
5866         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5867         0x0000ffff                              /* end                      */
5868     };
5869     const DWORD fog_code[] = {
5870         0xffff0300,                             /* ps_3_0                   */
5871         0x0200001f, 0x8000000b, 0x900f0000,     /* dcl_fog, v0              */
5872         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5873         0x0000ffff                              /* end                      */
5874     };
5875     const DWORD depth_code[] = {
5876         0xffff0300,                             /* ps_3_0                   */
5877         0x0200001f, 0x8000000c, 0x900f0000,     /* dcl_depth, v0            */
5878         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5879         0x0000ffff                              /* end                      */
5880     };
5881     const DWORD specular_code[] = {
5882         0xffff0300,                             /* ps_3_0                   */
5883         0x0200001f, 0x8001000a, 0x900f0000,     /* dcl_color1, v0           */
5884         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5885         0x0000ffff                              /* end                      */
5886     };
5887     /* sample: fails */
5888
5889     struct varying_test_struct tests[] = {
5890        {blendweight_code,       NULL,       0x00000000,     0x00191919,     "blendweight"   ,   FALSE,  TRUE  },
5891        {blendindices_code,      NULL,       0x00000000,     0x00000000,     "blendindices"  ,   FALSE,  FALSE },
5892        {normal_code,            NULL,       0x00000000,     0x004c4c4c,     "normal"        ,   FALSE,  TRUE  },
5893        /* Why does dx not forward the texcoord? */
5894        {texcoord0_code,         NULL,       0x00000000,     0x00808c8c,     "texcoord0"     ,   FALSE,  FALSE },
5895        {tangent_code,           NULL,       0x00000000,     0x00999999,     "tangent"       ,   FALSE,  TRUE  },
5896        {binormal_code,          NULL,       0x00000000,     0x00b2b2b2,     "binormal"      ,   FALSE,  TRUE  },
5897        {color_code,             NULL,       0x00e6e6e6,     0x00e6e6e6,     "color"         ,   FALSE,  FALSE },
5898        {fog_code,               NULL,       0x00000000,     0x00666666,     "fog"           ,   FALSE,  TRUE  },
5899        {depth_code,             NULL,       0x00000000,     0x00cccccc,     "depth"         ,   FALSE,  TRUE  },
5900        {specular_code,          NULL,       0x004488ff,     0x004488ff,     "specular"      ,   FALSE,  FALSE }
5901     };
5902     /* Declare a monster vertex type :-) */
5903     static const D3DVERTEXELEMENT9 decl_elements[] = {
5904         {0,   0,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT,      0},
5905         {0,  16,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT,    0},
5906         {0,  32,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES,   0},
5907         {0,  48,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,         0},
5908         {0,  64,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_FOG,            0},
5909         {0,  80,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
5910         {0,  96,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT,        0},
5911         {0, 112,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL,       0},
5912         {0, 128,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_DEPTH,          0},
5913         {0, 144,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
5914         {0, 148,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          1},
5915         D3DDECL_END()
5916     };
5917     struct hugeVertex data[4] = {
5918         {
5919             -1.0,   -1.0,   0.1,    1.0,
5920              0.1,    0.1,   0.1,    0.1,
5921              0.2,    0.2,   0.2,    0.2,
5922              0.3,    0.3,   0.3,    0.3,
5923              0.4,    0.4,   0.4,    0.4,
5924              0.50,   0.55,  0.55,   0.55,
5925              0.6,    0.6,   0.6,    0.7,
5926              0.7,    0.7,   0.7,    0.6,
5927              0.8,    0.8,   0.8,    0.8,
5928              0xe6e6e6e6, /* 0.9 * 256 */
5929              0x224488ff  /* Nothing special */
5930         },
5931         {
5932              1.0,   -1.0,   0.1,    1.0,
5933              0.1,    0.1,   0.1,    0.1,
5934              0.2,    0.2,   0.2,    0.2,
5935              0.3,    0.3,   0.3,    0.3,
5936              0.4,    0.4,   0.4,    0.4,
5937              0.50,   0.55,  0.55,   0.55,
5938              0.6,    0.6,   0.6,    0.7,
5939              0.7,    0.7,   0.7,    0.6,
5940              0.8,    0.8,   0.8,    0.8,
5941              0xe6e6e6e6, /* 0.9 * 256 */
5942              0x224488ff /* Nothing special */
5943         },
5944         {
5945             -1.0,    1.0,   0.1,    1.0,
5946              0.1,    0.1,   0.1,    0.1,
5947              0.2,    0.2,   0.2,    0.2,
5948              0.3,    0.3,   0.3,    0.3,
5949              0.4,    0.4,   0.4,    0.4,
5950              0.50,   0.55,  0.55,   0.55,
5951              0.6,    0.6,   0.6,    0.7,
5952              0.7,    0.7,   0.7,    0.6,
5953              0.8,    0.8,   0.8,    0.8,
5954              0xe6e6e6e6, /* 0.9 * 256 */
5955              0x224488ff /* Nothing special */
5956         },
5957         {
5958              1.0,    1.0,   0.1,    1.0,
5959              0.1,    0.1,   0.1,    0.1,
5960              0.2,    0.2,   0.2,    0.2,
5961              0.3,    0.3,   0.3,    0.3,
5962              0.4,    0.4,   0.4,    0.4,
5963              0.50,   0.55,  0.55,   0.55,
5964              0.6,    0.6,   0.6,    0.7,
5965              0.7,    0.7,   0.7,    0.6,
5966              0.8,    0.8,   0.8,    0.8,
5967              0xe6e6e6e6, /* 0.9 * 256 */
5968              0x224488ff /* Nothing special */
5969         },
5970     };
5971     struct hugeVertex data2[4];
5972     IDirect3DVertexDeclaration9 *decl;
5973     HRESULT hr;
5974     unsigned int i;
5975     DWORD color, r, g, b, r_e, g_e, b_e;
5976
5977     memcpy(data2, data, sizeof(data2));
5978     data2[0].pos_x = 0;     data2[0].pos_y = 0;
5979     data2[1].pos_x = 640;   data2[1].pos_y = 0;
5980     data2[2].pos_x = 0;     data2[2].pos_y = 480;
5981     data2[3].pos_x = 640;   data2[3].pos_y = 480;
5982
5983     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
5984     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
5985     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
5986     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
5987
5988     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
5989     {
5990         hr = IDirect3DDevice9_CreatePixelShader(device, tests[i].shader_code, &tests[i].shader);
5991         ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed for shader %s, hr = %08x\n",
5992            tests[i].name, hr);
5993     }
5994
5995     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
5996     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
5997     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
5998     {
5999         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
6000         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
6001
6002         IDirect3DDevice9_SetPixelShader(device, tests[i].shader);
6003         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
6004
6005         hr = IDirect3DDevice9_BeginScene(device);
6006         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6007         if(SUCCEEDED(hr))
6008         {
6009             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, data2, sizeof(data2[0]));
6010             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6011             hr = IDirect3DDevice9_EndScene(device);
6012             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6013         }
6014
6015         color = getPixelColor(device, 360, 240);
6016         r = color & 0x00ff0000 >> 16;
6017         g = color & 0x0000ff00 >>  8;
6018         b = color & 0x000000ff;
6019         r_e = tests[i].color_rhw & 0x00ff0000 >> 16;
6020         g_e = tests[i].color_rhw & 0x0000ff00 >>  8;
6021         b_e = tests[i].color_rhw & 0x000000ff;
6022
6023         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6024         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6025
6026         if(tests[i].todo_rhw) {
6027             /* This isn't a weekend's job to fix, ignore the problem for now. Needs a replacement
6028              * pipeline
6029              */
6030             todo_wine ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
6031                          "Test %s returned color 0x%08x, expected 0x%08x(todo)\n",
6032                          tests[i].name, color, tests[i].color_rhw);
6033         } else {
6034             ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
6035                "Test %s returned color 0x%08x, expected 0x%08x\n",
6036                tests[i].name, color, tests[i].color_rhw);
6037         }
6038     }
6039
6040     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
6041     {
6042         IDirect3DPixelShader9_Release(tests[i].shader);
6043     }
6044
6045     IDirect3DVertexDeclaration9_Release(decl);
6046 }
6047
6048 static void test_compare_instructions(IDirect3DDevice9 *device)
6049 {
6050     DWORD shader_sge_vec_code[] = {
6051         0xfffe0101,                                         /* vs_1_1                   */
6052         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
6053         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
6054         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
6055         0x0000000d, 0xd00f0000, 0x80e40000, 0xa0e40001,     /* sge oD0, r0, c1          */
6056         0x0000ffff                                          /* end                      */
6057     };
6058     DWORD shader_slt_vec_code[] = {
6059         0xfffe0101,                                         /* vs_1_1                   */
6060         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
6061         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
6062         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
6063         0x0000000c, 0xd00f0000, 0x80e40000, 0xa0e40001,     /* slt oD0, r0, c1          */
6064         0x0000ffff                                          /* end                      */
6065     };
6066     DWORD shader_sge_scalar_code[] = {
6067         0xfffe0101,                                         /* vs_1_1                   */
6068         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
6069         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
6070         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
6071         0x0000000d, 0xd0010000, 0x80000000, 0xa0550001,     /* slt oD0.r, r0.r, c1.b    */
6072         0x0000000d, 0xd0020000, 0x80550000, 0xa0aa0001,     /* slt oD0.g, r0.g, c1.r    */
6073         0x0000000d, 0xd0040000, 0x80aa0000, 0xa0000001,     /* slt oD0.b, r0.b, c1.g    */
6074         0x0000ffff                                          /* end                      */
6075     };
6076     DWORD shader_slt_scalar_code[] = {
6077         0xfffe0101,                                         /* vs_1_1                   */
6078         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
6079         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
6080         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
6081         0x0000000c, 0xd0010000, 0x80000000, 0xa0aa0001,     /* slt oD0.r, r0.r, c1.b    */
6082         0x0000000c, 0xd0020000, 0x80550000, 0xa0000001,     /* slt oD0.g, r0.g, c1.r    */
6083         0x0000000c, 0xd0040000, 0x80aa0000, 0xa0550001,     /* slt oD0.b, r0.b, c1.g    */
6084         0x0000ffff                                          /* end                      */
6085     };
6086     IDirect3DVertexShader9 *shader_sge_vec;
6087     IDirect3DVertexShader9 *shader_slt_vec;
6088     IDirect3DVertexShader9 *shader_sge_scalar;
6089     IDirect3DVertexShader9 *shader_slt_scalar;
6090     HRESULT hr, color;
6091     float quad1[] =  {
6092         -1.0,   -1.0,   0.1,
6093          0.0,   -1.0,   0.1,
6094         -1.0,    0.0,   0.1,
6095          0.0,    0.0,   0.1
6096     };
6097     float quad2[] =  {
6098          0.0,   -1.0,   0.1,
6099          1.0,   -1.0,   0.1,
6100          0.0,    0.0,   0.1,
6101          1.0,    0.0,   0.1
6102     };
6103     float quad3[] =  {
6104         -1.0,    0.0,   0.1,
6105          0.0,    0.0,   0.1,
6106         -1.0,    1.0,   0.1,
6107          0.0,    1.0,   0.1
6108     };
6109     float quad4[] =  {
6110          0.0,    0.0,   0.1,
6111          1.0,    0.0,   0.1,
6112          0.0,    1.0,   0.1,
6113          1.0,    1.0,   0.1
6114     };
6115     const float const0[4] = {0.8, 0.2, 0.2, 0.2};
6116     const float const1[4] = {0.2, 0.8, 0.2, 0.2};
6117
6118     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
6119     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
6120
6121     hr = IDirect3DDevice9_CreateVertexShader(device, shader_sge_vec_code, &shader_sge_vec);
6122     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6123     hr = IDirect3DDevice9_CreateVertexShader(device, shader_slt_vec_code, &shader_slt_vec);
6124     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6125     hr = IDirect3DDevice9_CreateVertexShader(device, shader_sge_scalar_code, &shader_sge_scalar);
6126     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6127     hr = IDirect3DDevice9_CreateVertexShader(device, shader_slt_scalar_code, &shader_slt_scalar);
6128     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6129     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, const0, 1);
6130     ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
6131     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, const1, 1);
6132     ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
6133     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
6134     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetFVF failed (%08x)\n", hr);
6135
6136     hr = IDirect3DDevice9_BeginScene(device);
6137     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6138     if(SUCCEEDED(hr))
6139     {
6140         hr = IDirect3DDevice9_SetVertexShader(device, shader_sge_vec);
6141         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6142         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 3);
6143         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6144
6145         hr = IDirect3DDevice9_SetVertexShader(device, shader_slt_vec);
6146         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6147         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2,  quad2, sizeof(float) * 3);
6148         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6149
6150         hr = IDirect3DDevice9_SetVertexShader(device, shader_sge_scalar);
6151         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6152         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 3);
6153         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6154
6155         hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, const0, 1);
6156         ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
6157
6158         hr = IDirect3DDevice9_SetVertexShader(device, shader_slt_scalar);
6159         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6160         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 3);
6161         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6162
6163         hr = IDirect3DDevice9_EndScene(device);
6164         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6165     }
6166
6167     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
6168     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6169
6170     color = getPixelColor(device, 160, 360);
6171     ok(color == 0x00FF00FF, "Compare test: Quad 1(sge vec) returned color 0x%08x, expected 0x00FF00FF\n", color);
6172     color = getPixelColor(device, 480, 360);
6173     ok(color == 0x0000FF00, "Compare test: Quad 2(slt vec) returned color 0x%08x, expected 0x0000FF00\n", color);
6174     color = getPixelColor(device, 160, 120);
6175     ok(color == 0x00FFFFFF, "Compare test: Quad 3(sge scalar) returned color 0x%08x, expected 0x00FFFFFF\n", color);
6176     color = getPixelColor(device, 480, 160);
6177     ok(color == 0x000000ff, "Compare test: Quad 4(slt scalar) returned color 0x%08x, expected 0x000000ff\n", color);
6178
6179     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6180     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6181
6182     IDirect3DVertexShader9_Release(shader_sge_vec);
6183     IDirect3DVertexShader9_Release(shader_slt_vec);
6184     IDirect3DVertexShader9_Release(shader_sge_scalar);
6185     IDirect3DVertexShader9_Release(shader_slt_scalar);
6186 }
6187
6188 static void test_vshader_input(IDirect3DDevice9 *device)
6189 {
6190     static const DWORD swapped_shader_code_3[] =
6191     {
6192         0xfffe0300,                                         /* vs_3_0               */
6193         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
6194         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
6195         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6196         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
6197         0x0200001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
6198         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
6199         0x02000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
6200         0x03000002, 0xe00f0001, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
6201         0x0000ffff                                          /* end                  */
6202     };
6203     static const DWORD swapped_shader_code_1[] =
6204     {
6205         0xfffe0101,                                         /* vs_1_1               */
6206         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6207         0x0000001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
6208         0x0000001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
6209         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov o0, v0           */
6210         0x00000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
6211         0x00000002, 0xd00f0000, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
6212         0x0000ffff                                          /* end                  */
6213     };
6214     static const DWORD swapped_shader_code_2[] =
6215     {
6216         0xfffe0200,                                         /* vs_2_0               */
6217         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6218         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
6219         0x0200001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
6220         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov o0, v0           */
6221         0x02000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
6222         0x03000002, 0xd00f0000, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
6223         0x0000ffff                                          /* end                  */
6224     };
6225     static const DWORD texcoord_color_shader_code_3[] =
6226     {
6227         0xfffe0300,                                         /* vs_3_0               */
6228         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
6229         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
6230         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6231         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
6232         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
6233         0x02000001, 0xe00f0001, 0x90e40001,                 /* mov o1, v1           */
6234         0x0000ffff                                          /* end                  */
6235     };
6236     static const DWORD texcoord_color_shader_code_2[] =
6237     {
6238         0xfffe0200,                                         /* vs_2_0               */
6239         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6240         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
6241         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
6242         0x02000001, 0xd00f0000, 0x90e40001,                 /* mov oD0, v1          */
6243         0x0000ffff                                          /* end                  */
6244     };
6245     static const DWORD texcoord_color_shader_code_1[] =
6246     {
6247         0xfffe0101,                                         /* vs_1_1               */
6248         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6249         0x0000001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
6250         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
6251         0x00000001, 0xd00f0000, 0x90e40001,                 /* mov oD0, v1          */
6252         0x0000ffff                                          /* end                  */
6253     };
6254     static const DWORD color_color_shader_code_3[] =
6255     {
6256         0xfffe0300,                                         /* vs_3_0               */
6257         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
6258         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
6259         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6260         0x0200001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
6261         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
6262         0x03000005, 0xe00f0001, 0xa0e40000, 0x90e40001,     /* mul o1, c0, v1       */
6263         0x0000ffff                                          /* end                  */
6264     };
6265     static const DWORD color_color_shader_code_2[] =
6266     {
6267         0xfffe0200,                                         /* vs_2_0               */
6268         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6269         0x0200001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
6270         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
6271         0x03000005, 0xd00f0000, 0xa0e40000, 0x90e40001,     /* mul oD0, c0, v1      */
6272         0x0000ffff                                          /* end                  */
6273     };
6274     static const DWORD color_color_shader_code_1[] =
6275     {
6276         0xfffe0101,                                         /* vs_1_1               */
6277         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6278         0x0000001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
6279         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
6280         0x00000005, 0xd00f0000, 0xa0e40000, 0x90e40001,     /* mul oD0, c0, v1      */
6281         0x0000ffff                                          /* end                  */
6282     };
6283     static const DWORD ps3_code[] =
6284     {
6285         0xffff0300,                                         /* ps_3_0               */
6286         0x0200001f, 0x8000000a, 0x900f0000,                 /* dcl_color0 v0        */
6287         0x02000001, 0x800f0800, 0x90e40000,                 /* mov oC0, v0          */
6288         0x0000ffff                                          /* end                  */
6289     };
6290     IDirect3DVertexShader9 *swapped_shader, *texcoord_color_shader, *color_color_shader;
6291     IDirect3DPixelShader9 *ps;
6292     HRESULT hr;
6293     DWORD color;
6294     float quad1[] =  {
6295         -1.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6296          0.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6297         -1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6298          0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6299     };
6300     float quad2[] =  {
6301          0.0,   -1.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6302          1.0,   -1.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6303          0.0,    0.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6304          1.0,    0.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6305     };
6306     float quad3[] =  {
6307         -1.0,    0.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    1.0,    -1.0,   0.0,    0.0,
6308          0.0,    0.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    1.0,     0.0,   0.0,    0.0,
6309         -1.0,    1.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    0.0,    -1.0,   1.0,    0.0,
6310          0.0,    1.0,   0.1,   -1.0,    0.0,    0.0,    0.0,   -1.0,     0.0,   0.0,    0.0,
6311     };
6312     float quad4[] =  {
6313          0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6314          1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6315          0.0,    1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6316          1.0,    1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6317     };
6318     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd[] = {
6319         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6320         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6321         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
6322         D3DDECL_END()
6323     };
6324     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd_rightorder[] = {
6325         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6326         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
6327         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6328         D3DDECL_END()
6329     };
6330     static const D3DVERTEXELEMENT9 decl_elements_onetexcrd[] = {
6331         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6332         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6333         D3DDECL_END()
6334     };
6335     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd_wrongidx[] = {
6336         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6337         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
6338         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       2},
6339         D3DDECL_END()
6340     };
6341     static const D3DVERTEXELEMENT9 decl_elements_texcoord_color[] = {
6342         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6343         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6344         D3DDECL_END()
6345     };
6346     static const D3DVERTEXELEMENT9 decl_elements_color_color[] = {
6347         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6348         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6349         D3DDECL_END()
6350     };
6351     static const D3DVERTEXELEMENT9 decl_elements_color_ubyte[] = {
6352         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6353         {0,  12,  D3DDECLTYPE_UBYTE4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6354         D3DDECL_END()
6355     };
6356     static const D3DVERTEXELEMENT9 decl_elements_color_float[] = {
6357         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6358         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6359         D3DDECL_END()
6360     };
6361     IDirect3DVertexDeclaration9 *decl_twotexcrd, *decl_onetexcrd, *decl_twotex_wrongidx, *decl_twotexcrd_rightorder;
6362     IDirect3DVertexDeclaration9 *decl_texcoord_color, *decl_color_color, *decl_color_ubyte, *decl_color_float;
6363     unsigned int i;
6364     float normalize[4] = {1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0};
6365     float no_normalize[4] = {1.0, 1.0, 1.0, 1.0};
6366
6367     struct vertex quad1_color[] =  {
6368        {-1.0,   -1.0,   0.1,    0x00ff8040},
6369        { 0.0,   -1.0,   0.1,    0x00ff8040},
6370        {-1.0,    0.0,   0.1,    0x00ff8040},
6371        { 0.0,    0.0,   0.1,    0x00ff8040}
6372     };
6373     struct vertex quad2_color[] =  {
6374        { 0.0,   -1.0,   0.1,    0x00ff8040},
6375        { 1.0,   -1.0,   0.1,    0x00ff8040},
6376        { 0.0,    0.0,   0.1,    0x00ff8040},
6377        { 1.0,    0.0,   0.1,    0x00ff8040}
6378     };
6379     struct vertex quad3_color[] =  {
6380        {-1.0,    0.0,   0.1,    0x00ff8040},
6381        { 0.0,    0.0,   0.1,    0x00ff8040},
6382        {-1.0,    1.0,   0.1,    0x00ff8040},
6383        { 0.0,    1.0,   0.1,    0x00ff8040}
6384     };
6385     float quad4_color[] =  {
6386          0.0,    0.0,   0.1,    1.0,    1.0,    0.0,    0.0,
6387          1.0,    0.0,   0.1,    1.0,    1.0,    0.0,    1.0,
6388          0.0,    1.0,   0.1,    1.0,    1.0,    0.0,    0.0,
6389          1.0,    1.0,   0.1,    1.0,    1.0,    0.0,    1.0,
6390     };
6391
6392     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd, &decl_twotexcrd);
6393     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6394     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_onetexcrd, &decl_onetexcrd);
6395     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6396     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd_wrongidx, &decl_twotex_wrongidx);
6397     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6398     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd_rightorder, &decl_twotexcrd_rightorder);
6399     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6400
6401     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_texcoord_color, &decl_texcoord_color);
6402     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6403     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_color, &decl_color_color);
6404     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6405     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_ubyte, &decl_color_ubyte);
6406     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6407     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_float, &decl_color_float);
6408     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6409
6410     hr = IDirect3DDevice9_CreatePixelShader(device, ps3_code, &ps);
6411     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
6412
6413     for(i = 1; i <= 3; i++) {
6414         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
6415         ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
6416         if(i == 3) {
6417             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_3, &swapped_shader);
6418             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6419             hr = IDirect3DDevice9_SetPixelShader(device, ps);
6420             ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
6421         } else if(i == 2){
6422             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_2, &swapped_shader);
6423             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6424         } else if(i == 1) {
6425             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_1, &swapped_shader);
6426             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6427         }
6428
6429         hr = IDirect3DDevice9_BeginScene(device);
6430         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6431         if(SUCCEEDED(hr))
6432         {
6433             hr = IDirect3DDevice9_SetVertexShader(device, swapped_shader);
6434             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6435
6436             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd);
6437             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6438             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 11);
6439             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6440
6441             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_onetexcrd);
6442             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6443             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(float) * 11);
6444             if(i == 3 || i == 2) {
6445                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
6446             } else if(i == 1) {
6447                 /* Succeeds or fails, depending on SW or HW vertex processing */
6448                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x), i = 1\n", hr);
6449             }
6450
6451             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd_rightorder);
6452             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6453             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 11);
6454             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6455
6456             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotex_wrongidx);
6457             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6458             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 11);
6459             if(i == 3 || i == 2) {
6460                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
6461             } else if(i == 1) {
6462                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = 1\n", hr);
6463             }
6464
6465             hr = IDirect3DDevice9_EndScene(device);
6466             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6467         }
6468
6469         if(i == 3 || i == 2) {
6470             color = getPixelColor(device, 160, 360);
6471             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x80), 1),
6472                "Input test: Quad 1(2crd) returned color 0x%08x, expected 0x00FFFF80\n", color);
6473
6474             /* The last value of the read but undefined stream is used, it is 0x00. The defined input is vec4(1, 0, 0, 0) */
6475             color = getPixelColor(device, 480, 360);
6476             ok(color == 0x00FFFF00 || color ==0x00FF0000,
6477                "Input test: Quad 2(1crd) returned color 0x%08x, expected 0x00FFFF00\n", color);
6478             color = getPixelColor(device, 160, 120);
6479             /* Same as above, accept both the last used value and 0.0 for the undefined streams */
6480             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x80), 1) || color == D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00),
6481                "Input test: Quad 3(2crd-wrongidx) returned color 0x%08x, expected 0x00FF0080\n", color);
6482
6483             color = getPixelColor(device, 480, 160);
6484             ok(color == 0x00000000, "Input test: Quad 4(2crd-rightorder) returned color 0x%08x, expected 0x00000000\n", color);
6485         } else if(i == 1) {
6486             color = getPixelColor(device, 160, 360);
6487             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x80), 1),
6488                "Input test: Quad 1(2crd) returned color 0x%08x, expected 0x00FFFF80\n", color);
6489             color = getPixelColor(device, 480, 360);
6490             /* Accept the clear color as well in this case, since SW VP returns an error */
6491             ok(color == 0x00FFFF00 || color == 0x00FF0000, "Input test: Quad 2(1crd) returned color 0x%08x, expected 0x00FFFF00\n", color);
6492             color = getPixelColor(device, 160, 120);
6493             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x80), 1) || color == D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00),
6494                "Input test: Quad 3(2crd-wrongidx) returned color 0x%08x, expected 0x00FF0080\n", color);
6495             color = getPixelColor(device, 480, 160);
6496             ok(color == 0x00000000, "Input test: Quad 4(2crd-rightorder) returned color 0x%08x, expected 0x00000000\n", color);
6497         }
6498
6499         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6500         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6501
6502         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff808080, 0.0, 0);
6503         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
6504
6505         /* Now find out if the whole streams are re-read, or just the last active value for the
6506          * vertices is used.
6507          */
6508         hr = IDirect3DDevice9_BeginScene(device);
6509         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6510         if(SUCCEEDED(hr))
6511         {
6512             float quad1_modified[] =  {
6513                 -1.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,   -1.0,     0.0,   0.0,    0.0,
6514                  0.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.0,    0.0,
6515                 -1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,     0.0,  -1.0,    0.0,
6516                  0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,   -1.0,    -1.0,  -1.0,    0.0,
6517             };
6518             float quad2_modified[] =  {
6519                  0.0,   -1.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6520                  1.0,   -1.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6521                  0.0,    0.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6522                  1.0,    0.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6523             };
6524
6525             hr = IDirect3DDevice9_SetVertexShader(device, swapped_shader);
6526             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6527
6528             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd);
6529             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6530             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 3, quad1_modified, sizeof(float) * 11);
6531             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6532
6533             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_onetexcrd);
6534             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6535             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2_modified, sizeof(float) * 11);
6536             if(i == 3 || i == 2) {
6537                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
6538             } else if(i == 1) {
6539                 /* Succeeds or fails, depending on SW or HW vertex processing */
6540                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x), i = 1\n", hr);
6541             }
6542
6543             hr = IDirect3DDevice9_EndScene(device);
6544             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6545         }
6546
6547         color = getPixelColor(device, 480, 350);
6548         /* vs_1_1 may fail, accept the clear color. Some drivers also set the undefined streams to 0, accept that
6549          * as well.
6550          *
6551          * NOTE: This test fails on the reference rasterizer. In the refrast, the 4 vertices have different colors,
6552          * i.e., the whole old stream is read, and not just the last used attribute. Some games require that this
6553          * does *not* happen, otherwise they can crash because of a read from a bad pointer, so do not accept the
6554          * refrast's result.
6555          *
6556          * A test app for this behavior is Half Life 2 Episode 2 in dxlevel 95, and related games(Portal, TF2).
6557          */
6558         ok(color == 0x000000FF || color == 0x00808080 || color == 0x00000000,
6559            "Input test: Quad 2(different colors) returned color 0x%08x, expected 0x000000FF, 0x00808080 or 0x00000000\n", color);
6560
6561         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6562         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6563
6564         IDirect3DDevice9_SetVertexShader(device, NULL);
6565         IDirect3DDevice9_SetPixelShader(device, NULL);
6566         IDirect3DDevice9_SetVertexDeclaration(device, NULL);
6567
6568         IDirect3DVertexShader9_Release(swapped_shader);
6569     }
6570
6571     for(i = 1; i <= 3; i++) {
6572         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
6573         ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
6574         if(i == 3) {
6575             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_3, &texcoord_color_shader);
6576             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6577             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_3, &color_color_shader);
6578             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6579             hr = IDirect3DDevice9_SetPixelShader(device, ps);
6580             ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
6581         } else if(i == 2){
6582             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_2, &texcoord_color_shader);
6583             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6584             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_2, &color_color_shader);
6585             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6586         } else if(i == 1) {
6587             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_1, &texcoord_color_shader);
6588             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6589             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_1, &color_color_shader);
6590             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6591         }
6592
6593         hr = IDirect3DDevice9_BeginScene(device);
6594         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6595         if(SUCCEEDED(hr))
6596         {
6597             hr = IDirect3DDevice9_SetVertexShader(device, texcoord_color_shader);
6598             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6599             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_texcoord_color);
6600             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6601             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1_color, sizeof(quad1_color[0]));
6602             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6603
6604             hr = IDirect3DDevice9_SetVertexShader(device, color_color_shader);
6605             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6606
6607             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, normalize, 1);
6608             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6609             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_ubyte);
6610             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6611             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2_color, sizeof(quad2_color[0]));
6612             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6613
6614             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, no_normalize, 1);
6615             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6616             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_color);
6617             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6618             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3_color, sizeof(quad3_color[0]));
6619             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6620
6621             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_float);
6622             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6623             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4_color, sizeof(float) * 7);
6624             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6625
6626             hr = IDirect3DDevice9_EndScene(device);
6627             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6628         }
6629         IDirect3DDevice9_SetVertexShader(device, NULL);
6630         IDirect3DDevice9_SetVertexDeclaration(device, NULL);
6631         IDirect3DDevice9_SetPixelShader(device, NULL);
6632
6633         color = getPixelColor(device, 160, 360);
6634         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x80, 0x40), 1),
6635            "Input test: Quad 1(color-texcoord) returned color 0x%08x, expected 0x00ff8040\n", color);
6636         color = getPixelColor(device, 480, 360);
6637         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x40, 0x80, 0xff), 1),
6638            "Input test: Quad 2(color-ubyte) returned color 0x%08x, expected 0x004080ff\n", color);
6639         color = getPixelColor(device, 160, 120);
6640         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x80, 0x40), 1),
6641            "Input test: Quad 3(color-color) returned color 0x%08x, expected 0x00ff8040\n", color);
6642         color = getPixelColor(device, 480, 160);
6643         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00), 1),
6644            "Input test: Quad 4(color-float) returned color 0x%08x, expected 0x00FFFF00\n", color);
6645
6646         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6647         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6648
6649         IDirect3DVertexShader9_Release(texcoord_color_shader);
6650         IDirect3DVertexShader9_Release(color_color_shader);
6651     }
6652
6653     IDirect3DVertexDeclaration9_Release(decl_twotexcrd);
6654     IDirect3DVertexDeclaration9_Release(decl_onetexcrd);
6655     IDirect3DVertexDeclaration9_Release(decl_twotex_wrongidx);
6656     IDirect3DVertexDeclaration9_Release(decl_twotexcrd_rightorder);
6657
6658     IDirect3DVertexDeclaration9_Release(decl_texcoord_color);
6659     IDirect3DVertexDeclaration9_Release(decl_color_color);
6660     IDirect3DVertexDeclaration9_Release(decl_color_ubyte);
6661     IDirect3DVertexDeclaration9_Release(decl_color_float);
6662
6663     IDirect3DPixelShader9_Release(ps);
6664 }
6665
6666 static void srgbtexture_test(IDirect3DDevice9 *device)
6667 {
6668     /* Fill a texture with 0x7f (~ .5), and then turn on the D3DSAMP_SRGBTEXTURE
6669      * texture stage state to render a quad using that texture.  The resulting
6670      * color components should be 0x36 (~ 0.21), per this formula:
6671      *    linear_color = ((srgb_color + 0.055) / 1.055) ^ 2.4
6672      * This is true where srgb_color > 0.04045.
6673      */
6674     IDirect3D9 *d3d = NULL;
6675     HRESULT hr;
6676     LPDIRECT3DTEXTURE9 texture = NULL;
6677     LPDIRECT3DSURFACE9 surface = NULL;
6678     D3DLOCKED_RECT lr;
6679     DWORD color;
6680     float quad[] = {
6681         -1.0,       1.0,       0.0,     0.0,    0.0,
6682          1.0,       1.0,       0.0,     1.0,    0.0,
6683         -1.0,      -1.0,       0.0,     0.0,    1.0,
6684          1.0,      -1.0,       0.0,     1.0,    1.0,
6685     };
6686
6687
6688     memset(&lr, 0, sizeof(lr));
6689     IDirect3DDevice9_GetDirect3D(device, &d3d);
6690     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6691                                     D3DUSAGE_QUERY_SRGBREAD, D3DRTYPE_TEXTURE,
6692                                     D3DFMT_A8R8G8B8) != D3D_OK) {
6693         skip("D3DFMT_A8R8G8B8 textures with SRGBREAD not supported\n");
6694         goto out;
6695     }
6696
6697     hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0,
6698                                         D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
6699                                         &texture, NULL);
6700     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
6701     if(!texture) {
6702         skip("Failed to create A8R8G8B8 texture with SRGBREAD\n");
6703         goto out;
6704     }
6705     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
6706     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
6707
6708     fill_surface(surface, 0xff7f7f7f);
6709     IDirect3DSurface9_Release(surface);
6710
6711     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
6712     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6713     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
6714     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
6715
6716     hr = IDirect3DDevice9_BeginScene(device);
6717     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
6718     if(SUCCEEDED(hr))
6719     {
6720         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, TRUE);
6721         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
6722
6723         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
6724         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
6725
6726
6727         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
6728         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with %08x\n", hr);
6729
6730         hr = IDirect3DDevice9_EndScene(device);
6731         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
6732     }
6733
6734     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6735     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
6736     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, FALSE);
6737     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
6738
6739     color = getPixelColor(device, 320, 240);
6740     ok(color == 0x00363636 || color == 0x00373737, "srgb quad has color %08x, expected 0x00363636\n", color);
6741
6742     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6743     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6744
6745 out:
6746     if(texture) IDirect3DTexture9_Release(texture);
6747     IDirect3D9_Release(d3d);
6748 }
6749
6750 static void shademode_test(IDirect3DDevice9 *device)
6751 {
6752     /* Render a quad and try all of the different fixed function shading models. */
6753     HRESULT hr;
6754     DWORD color0, color1;
6755     DWORD color0_gouraud = 0, color1_gouraud = 0;
6756     DWORD shademode = D3DSHADE_FLAT;
6757     DWORD primtype = D3DPT_TRIANGLESTRIP;
6758     LPVOID data = NULL;
6759     LPDIRECT3DVERTEXBUFFER9 vb_strip = NULL;
6760     LPDIRECT3DVERTEXBUFFER9 vb_list = NULL;
6761     UINT i, j;
6762     struct vertex quad_strip[] =
6763     {
6764         {-1.0f, -1.0f,  0.0f, 0xffff0000  },
6765         {-1.0f,  1.0f,  0.0f, 0xff00ff00  },
6766         { 1.0f, -1.0f,  0.0f, 0xff0000ff  },
6767         { 1.0f,  1.0f,  0.0f, 0xffffffff  }
6768     };
6769     struct vertex quad_list[] =
6770     {
6771         {-1.0f, -1.0f,  0.0f, 0xffff0000  },
6772         {-1.0f,  1.0f,  0.0f, 0xff00ff00  },
6773         { 1.0f, -1.0f,  0.0f, 0xff0000ff  },
6774
6775         {-1.0f,  1.0f,  0.0f, 0xff00ff00  },
6776         { 1.0f, -1.0f,  0.0f, 0xff0000ff  },
6777         { 1.0f,  1.0f,  0.0f, 0xffffffff  }
6778     };
6779
6780     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad_strip),
6781                                              0, 0, D3DPOOL_MANAGED, &vb_strip, NULL);
6782     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
6783     if (FAILED(hr)) goto bail;
6784
6785     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad_list),
6786                                              0, 0, D3DPOOL_MANAGED, &vb_list, NULL);
6787     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
6788     if (FAILED(hr)) goto bail;
6789
6790     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
6791     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6792
6793     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
6794     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
6795
6796     hr = IDirect3DVertexBuffer9_Lock(vb_strip, 0, sizeof(quad_strip), &data, 0);
6797     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
6798     memcpy(data, quad_strip, sizeof(quad_strip));
6799     hr = IDirect3DVertexBuffer9_Unlock(vb_strip);
6800     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
6801
6802     hr = IDirect3DVertexBuffer9_Lock(vb_list, 0, sizeof(quad_list), &data, 0);
6803     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
6804     memcpy(data, quad_list, sizeof(quad_list));
6805     hr = IDirect3DVertexBuffer9_Unlock(vb_list);
6806     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
6807
6808     /* Try it first with a TRIANGLESTRIP.  Do it with different geometry because
6809      * the color fixups we have to do for FLAT shading will be dependent on that. */
6810     hr = IDirect3DDevice9_SetStreamSource(device, 0, vb_strip, 0, sizeof(quad_strip[0]));
6811     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
6812
6813     /* First loop uses a TRIANGLESTRIP geometry, 2nd uses a TRIANGLELIST */
6814     for (j=0; j<2; j++) {
6815
6816         /* Inner loop just changes the D3DRS_SHADEMODE */
6817         for (i=0; i<3; i++) {
6818             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
6819             ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
6820
6821             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SHADEMODE, shademode);
6822             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6823
6824             hr = IDirect3DDevice9_BeginScene(device);
6825             ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
6826             if(SUCCEEDED(hr))
6827             {
6828                 hr = IDirect3DDevice9_DrawPrimitive(device, primtype, 0, 2);
6829                 ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed with %08x\n", hr);
6830
6831                 hr = IDirect3DDevice9_EndScene(device);
6832                 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
6833             }
6834
6835             /* Sample two spots from the output */
6836             color0 = getPixelColor(device, 100, 100); /* Inside first triangle */
6837             color1 = getPixelColor(device, 500, 350); /* Inside second triangle */
6838             switch(shademode) {
6839                 case D3DSHADE_FLAT:
6840                     /* Should take the color of the first vertex of each triangle */
6841                     if (0)
6842                     {
6843                         /* This test depends on EXT_provoking_vertex being
6844                          * available. This extension is currently (20090810)
6845                          * not common enough to let the test fail if it isn't
6846                          * present. */
6847                         ok(color0 == 0x00ff0000, "FLAT shading has color0 %08x, expected 0x00ff0000\n", color0);
6848                         ok(color1 == 0x0000ff00, "FLAT shading has color1 %08x, expected 0x0000ff00\n", color1);
6849                     }
6850                     shademode = D3DSHADE_GOURAUD;
6851                     break;
6852                 case D3DSHADE_GOURAUD:
6853                     /* Should be an interpolated blend */
6854
6855                     ok(color_match(color0, D3DCOLOR_ARGB(0x00, 0x0d, 0xca, 0x28), 2),
6856                        "GOURAUD shading has color0 %08x, expected 0x00dca28\n", color0);
6857                     ok(color_match(color1, D3DCOLOR_ARGB(0x00, 0x0d, 0x45, 0xc7), 2),
6858                        "GOURAUD shading has color1 %08x, expected 0x000d45c7\n", color1);
6859
6860                     color0_gouraud = color0;
6861                     color1_gouraud = color1;
6862
6863                     shademode = D3DSHADE_PHONG;
6864                     break;
6865                 case D3DSHADE_PHONG:
6866                     /* Should be the same as GOURAUD, since no hardware implements this */
6867                     ok(color_match(color0, D3DCOLOR_ARGB(0x00, 0x0d, 0xca, 0x28), 2),
6868                        "PHONG shading has color0 %08x, expected 0x000dca28\n", color0);
6869                     ok(color_match(color1, D3DCOLOR_ARGB(0x00, 0x0d, 0x45, 0xc7), 2),
6870                        "PHONG shading has color1 %08x, expected 0x000d45c7\n", color1);
6871
6872                     ok(color0 == color0_gouraud, "difference between GOURAUD and PHONG shading detected: %08x %08x\n",
6873                             color0_gouraud, color0);
6874                     ok(color1 == color1_gouraud, "difference between GOURAUD and PHONG shading detected: %08x %08x\n",
6875                             color1_gouraud, color1);
6876                     break;
6877             }
6878         }
6879
6880         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6881         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6882
6883         /* Now, do it all over again with a TRIANGLELIST */
6884         hr = IDirect3DDevice9_SetStreamSource(device, 0, vb_list, 0, sizeof(quad_list[0]));
6885         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
6886         primtype = D3DPT_TRIANGLELIST;
6887         shademode = D3DSHADE_FLAT;
6888     }
6889
6890 bail:
6891     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
6892     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
6893     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
6894     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6895
6896     if (vb_strip)
6897         IDirect3DVertexBuffer9_Release(vb_strip);
6898     if (vb_list)
6899         IDirect3DVertexBuffer9_Release(vb_list);
6900 }
6901
6902 static void alpha_test(IDirect3DDevice9 *device)
6903 {
6904     HRESULT hr;
6905     IDirect3DTexture9 *offscreenTexture;
6906     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
6907     DWORD color;
6908
6909     struct vertex quad1[] =
6910     {
6911         {-1.0f, -1.0f,   0.1f,                          0x4000ff00},
6912         {-1.0f,  0.0f,   0.1f,                          0x4000ff00},
6913         { 1.0f, -1.0f,   0.1f,                          0x4000ff00},
6914         { 1.0f,  0.0f,   0.1f,                          0x4000ff00},
6915     };
6916     struct vertex quad2[] =
6917     {
6918         {-1.0f,  0.0f,   0.1f,                          0xc00000ff},
6919         {-1.0f,  1.0f,   0.1f,                          0xc00000ff},
6920         { 1.0f,  0.0f,   0.1f,                          0xc00000ff},
6921         { 1.0f,  1.0f,   0.1f,                          0xc00000ff},
6922     };
6923     static const float composite_quad[][5] = {
6924         { 0.0f, -1.0f, 0.1f, 0.0f, 1.0f},
6925         { 0.0f,  1.0f, 0.1f, 0.0f, 0.0f},
6926         { 1.0f, -1.0f, 0.1f, 1.0f, 1.0f},
6927         { 1.0f,  1.0f, 0.1f, 1.0f, 0.0f},
6928     };
6929
6930     /* Clear the render target with alpha = 0.5 */
6931     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
6932     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
6933
6934     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
6935     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr);
6936
6937     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
6938     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
6939     if(!backbuffer) {
6940         goto out;
6941     }
6942
6943     hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
6944     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %08x\n", hr);
6945     if(!offscreen) {
6946         goto out;
6947     }
6948
6949     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
6950     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr);
6951
6952     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
6953     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
6954     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
6955     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
6956     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
6957     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
6958     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
6959     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
6960     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
6961     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6962
6963     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
6964     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6965     if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
6966
6967         /* Draw two quads, one with src alpha blending, one with dest alpha blending. */
6968         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
6969         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6970         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
6971         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6972         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
6973         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6974
6975         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
6976         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6977         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
6978         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6979         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
6980         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6981
6982         /* Switch to the offscreen buffer, and redo the testing. The offscreen render target
6983          * doesn't have an alpha channel. DESTALPHA and INVDESTALPHA "don't work" on render
6984          * targets without alpha channel, they give essentially ZERO and ONE blend factors. */
6985         hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
6986         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
6987         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
6988         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
6989
6990         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
6991         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6992         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
6993         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6994         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
6995         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6996
6997         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
6998         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6999         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
7000         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
7001         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
7002         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7003
7004         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
7005         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
7006
7007         /* Render the offscreen texture onto the frame buffer to be able to compare it regularly.
7008          * Disable alpha blending for the final composition
7009          */
7010         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
7011         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
7012         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7013         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr);
7014
7015         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
7016         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr = %08x\n", hr);
7017         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, composite_quad, sizeof(float) * 5);
7018         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7019         hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7020         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr = %08x\n", hr);
7021
7022         hr = IDirect3DDevice9_EndScene(device);
7023         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
7024     }
7025
7026     color = getPixelColor(device, 160, 360);
7027     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1),
7028        "SRCALPHA on frame buffer returned color %08x, expected 0x00bf4000\n", color);
7029
7030     color = getPixelColor(device, 160, 120);
7031     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x7f, 0x00, 0x80), 2),
7032        "DSTALPHA on frame buffer returned color %08x, expected 0x007f0080\n", color);
7033
7034     color = getPixelColor(device, 480, 360);
7035     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1),
7036        "SRCALPHA on texture returned color %08x, expected 0x00bf4000\n", color);
7037
7038     color = getPixelColor(device, 480, 120);
7039     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xff), 1),
7040        "DSTALPHA on texture returned color %08x, expected 0x000000ff\n", color);
7041
7042     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7043
7044     out:
7045     /* restore things */
7046     if(backbuffer) {
7047         IDirect3DSurface9_Release(backbuffer);
7048     }
7049     if(offscreenTexture) {
7050         IDirect3DTexture9_Release(offscreenTexture);
7051     }
7052     if(offscreen) {
7053         IDirect3DSurface9_Release(offscreen);
7054     }
7055 }
7056
7057 struct vertex_shortcolor {
7058     float x, y, z;
7059     unsigned short r, g, b, a;
7060 };
7061 struct vertex_floatcolor {
7062     float x, y, z;
7063     float r, g, b, a;
7064 };
7065
7066 static void fixed_function_decl_test(IDirect3DDevice9 *device)
7067 {
7068     HRESULT hr;
7069     BOOL s_ok, ub_ok, f_ok;
7070     DWORD color, size, i;
7071     void *data;
7072     static const D3DVERTEXELEMENT9 decl_elements_d3dcolor[] = {
7073         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7074         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7075         D3DDECL_END()
7076     };
7077     static const D3DVERTEXELEMENT9 decl_elements_d3dcolor_2streams[] = {
7078         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7079         {1,   0,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7080         D3DDECL_END()
7081     };
7082     static const D3DVERTEXELEMENT9 decl_elements_ubyte4n[] = {
7083         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7084         {0,  12,  D3DDECLTYPE_UBYTE4N,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7085         D3DDECL_END()
7086     };
7087     static const D3DVERTEXELEMENT9 decl_elements_ubyte4n_2streams[] = {
7088         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7089         {1,   0,  D3DDECLTYPE_UBYTE4N,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7090         D3DDECL_END()
7091     };
7092     static const D3DVERTEXELEMENT9 decl_elements_short4[] = {
7093         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7094         {0,  12,  D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7095         D3DDECL_END()
7096     };
7097     static const D3DVERTEXELEMENT9 decl_elements_float[] = {
7098         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7099         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7100         D3DDECL_END()
7101     };
7102     static const D3DVERTEXELEMENT9 decl_elements_positiont[] = {
7103         {0,   0,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT,      0},
7104         {0,  16,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7105         D3DDECL_END()
7106     };
7107     IDirect3DVertexDeclaration9 *dcl_float = NULL, *dcl_short = NULL, *dcl_ubyte = NULL, *dcl_color = NULL;
7108     IDirect3DVertexDeclaration9 *dcl_color_2 = NULL, *dcl_ubyte_2 = NULL, *dcl_positiont;
7109     IDirect3DVertexBuffer9 *vb, *vb2;
7110     struct vertex quad1[] =                             /* D3DCOLOR */
7111     {
7112         {-1.0f, -1.0f,   0.1f,                          0x00ffff00},
7113         {-1.0f,  0.0f,   0.1f,                          0x00ffff00},
7114         { 0.0f, -1.0f,   0.1f,                          0x00ffff00},
7115         { 0.0f,  0.0f,   0.1f,                          0x00ffff00},
7116     };
7117     struct vertex quad2[] =                             /* UBYTE4N */
7118     {
7119         {-1.0f,  0.0f,   0.1f,                          0x00ffff00},
7120         {-1.0f,  1.0f,   0.1f,                          0x00ffff00},
7121         { 0.0f,  0.0f,   0.1f,                          0x00ffff00},
7122         { 0.0f,  1.0f,   0.1f,                          0x00ffff00},
7123     };
7124     struct vertex_shortcolor quad3[] =                  /* short */
7125     {
7126         { 0.0f, -1.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
7127         { 0.0f,  0.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
7128         { 1.0f, -1.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
7129         { 1.0f,  0.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
7130     };
7131     struct vertex_floatcolor quad4[] =
7132     {
7133         { 0.0f,  0.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
7134         { 0.0f,  1.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
7135         { 1.0f,  0.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
7136         { 1.0f,  1.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
7137     };
7138     DWORD colors[] = {
7139         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7140         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7141         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7142         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7143         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7144         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7145         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7146         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7147         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7148         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7149         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7150         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7151         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7152         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7153         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7154         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7155     };
7156     float quads[] = {
7157         -1.0,   -1.0,     0.1,
7158         -1.0,    0.0,     0.1,
7159          0.0,   -1.0,     0.1,
7160          0.0,    0.0,     0.1,
7161
7162          0.0,   -1.0,     0.1,
7163          0.0,    0.0,     0.1,
7164          1.0,   -1.0,     0.1,
7165          1.0,    0.0,     0.1,
7166
7167          0.0,    0.0,     0.1,
7168          0.0,    1.0,     0.1,
7169          1.0,    0.0,     0.1,
7170          1.0,    1.0,     0.1,
7171
7172         -1.0,    0.0,     0.1,
7173         -1.0,    1.0,     0.1,
7174          0.0,    0.0,     0.1,
7175          0.0,    1.0,     0.1
7176     };
7177     struct tvertex quad_transformed[] = {
7178        {  90,    110,     0.1,      2.0,        0x00ffff00},
7179        { 570,    110,     0.1,      2.0,        0x00ffff00},
7180        {  90,    300,     0.1,      2.0,        0x00ffff00},
7181        { 570,    300,     0.1,      2.0,        0x00ffff00}
7182     };
7183     D3DCAPS9 caps;
7184
7185     memset(&caps, 0, sizeof(caps));
7186     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7187     ok(hr == D3D_OK, "GetDeviceCaps failed, hr = %08x\n", hr);
7188
7189     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
7190     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
7191
7192     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_d3dcolor, &dcl_color);
7193     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7194     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_short4, &dcl_short);
7195     ok(SUCCEEDED(hr) || hr == E_FAIL, "CreateVertexDeclaration failed (%08x)\n", hr);
7196     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_float, &dcl_float);
7197     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7198     if(caps.DeclTypes & D3DDTCAPS_UBYTE4N) {
7199         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_ubyte4n_2streams, &dcl_ubyte_2);
7200         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7201         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_ubyte4n, &dcl_ubyte);
7202         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7203     } else {
7204         trace("D3DDTCAPS_UBYTE4N not supported\n");
7205         dcl_ubyte_2 = NULL;
7206         dcl_ubyte = NULL;
7207     }
7208     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_d3dcolor_2streams, &dcl_color_2);
7209     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7210     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_positiont, &dcl_positiont);
7211     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7212
7213     size = max(sizeof(quad1), max(sizeof(quad2), max(sizeof(quad3), max(sizeof(quad4), sizeof(quads)))));
7214     hr = IDirect3DDevice9_CreateVertexBuffer(device, size,
7215                                              0, 0, D3DPOOL_MANAGED, &vb, NULL);
7216     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
7217
7218     hr = IDirect3DDevice9_BeginScene(device);
7219     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
7220     f_ok = FALSE; s_ok = FALSE; ub_ok = FALSE;
7221     if(SUCCEEDED(hr)) {
7222         if(dcl_color) {
7223             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color);
7224             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7225             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
7226             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7227         }
7228
7229         /* Tests with non-standard fixed function types fail on the refrast. The ATI driver partially
7230          * accepts them, the nvidia driver accepts them all. All those differences even though we're
7231          * using software vertex processing. Doh!
7232          */
7233         if(dcl_ubyte) {
7234             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte);
7235             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7236             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
7237             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7238             ub_ok = SUCCEEDED(hr);
7239         }
7240
7241         if(dcl_short) {
7242             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_short);
7243             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7244             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(quad3[0]));
7245             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7246             s_ok = SUCCEEDED(hr);
7247         }
7248
7249         if(dcl_float) {
7250             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_float);
7251             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7252             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(quad4[0]));
7253             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7254             f_ok = SUCCEEDED(hr);
7255         }
7256
7257         hr = IDirect3DDevice9_EndScene(device);
7258         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr = %#08x\n", hr);
7259     }
7260
7261     if(dcl_short) {
7262         color = getPixelColor(device, 480, 360);
7263         ok(color == 0x000000ff || !s_ok,
7264            "D3DDECLTYPE_USHORT4N returned color %08x, expected 0x000000ff\n", color);
7265     }
7266     if(dcl_ubyte) {
7267         color = getPixelColor(device, 160, 120);
7268         ok(color == 0x0000ffff || !ub_ok,
7269            "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x0000ffff\n", color);
7270     }
7271     if(dcl_color) {
7272         color = getPixelColor(device, 160, 360);
7273         ok(color == 0x00ffff00,
7274            "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ffff00\n", color);
7275     }
7276     if(dcl_float) {
7277         color = getPixelColor(device, 480, 120);
7278         ok(color == 0x00ff0000 || !f_ok,
7279            "D3DDECLTYPE_FLOAT4 returned color %08x, expected 0x00ff0000\n", color);
7280     }
7281     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7282
7283     /* The following test with vertex buffers doesn't serve to find out new information from windows.
7284      * It is a plain regression test because wined3d uses different codepaths for attribute conversion
7285      * with vertex buffers. It makes sure that the vertex buffer one works, while the above tests
7286      * whether the immediate mode code works
7287      */
7288     f_ok = FALSE; s_ok = FALSE; ub_ok = FALSE;
7289     hr = IDirect3DDevice9_BeginScene(device);
7290     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
7291     if(SUCCEEDED(hr)) {
7292         if(dcl_color) {
7293             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad1), &data, 0);
7294             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7295             memcpy(data, quad1, sizeof(quad1));
7296             hr = IDirect3DVertexBuffer9_Unlock(vb);
7297             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7298             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color);
7299             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7300             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad1[0]));
7301             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7302             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7303             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7304         }
7305
7306         if(dcl_ubyte) {
7307             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad2), &data, 0);
7308             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7309             memcpy(data, quad2, sizeof(quad2));
7310             hr = IDirect3DVertexBuffer9_Unlock(vb);
7311             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7312             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte);
7313             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7314             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad2[0]));
7315             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7316             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7317             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7318                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7319             ub_ok = SUCCEEDED(hr);
7320         }
7321
7322         if(dcl_short) {
7323             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad3), &data, 0);
7324             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7325             memcpy(data, quad3, sizeof(quad3));
7326             hr = IDirect3DVertexBuffer9_Unlock(vb);
7327             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7328             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_short);
7329             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7330             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad3[0]));
7331             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7332             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7333             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7334                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7335             s_ok = SUCCEEDED(hr);
7336         }
7337
7338         if(dcl_float) {
7339             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad4), &data, 0);
7340             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7341             memcpy(data, quad4, sizeof(quad4));
7342             hr = IDirect3DVertexBuffer9_Unlock(vb);
7343             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7344             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_float);
7345             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7346             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad4[0]));
7347             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7348             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7349             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7350                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7351             f_ok = SUCCEEDED(hr);
7352         }
7353
7354         hr = IDirect3DDevice9_EndScene(device);
7355         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr = %#08x\n", hr);
7356     }
7357
7358     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
7359     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7360     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
7361     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7362
7363     if(dcl_short) {
7364         color = getPixelColor(device, 480, 360);
7365         ok(color == 0x000000ff || !s_ok,
7366            "D3DDECLTYPE_USHORT4N returned color %08x, expected 0x000000ff\n", color);
7367     }
7368     if(dcl_ubyte) {
7369         color = getPixelColor(device, 160, 120);
7370         ok(color == 0x0000ffff || !ub_ok,
7371            "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x0000ffff\n", color);
7372     }
7373     if(dcl_color) {
7374         color = getPixelColor(device, 160, 360);
7375         ok(color == 0x00ffff00,
7376            "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ffff00\n", color);
7377     }
7378     if(dcl_float) {
7379         color = getPixelColor(device, 480, 120);
7380         ok(color == 0x00ff0000 || !f_ok,
7381            "D3DDECLTYPE_FLOAT4 returned color %08x, expected 0x00ff0000\n", color);
7382     }
7383     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7384
7385     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
7386     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
7387
7388     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad_transformed), &data, 0);
7389     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7390     memcpy(data, quad_transformed, sizeof(quad_transformed));
7391     hr = IDirect3DVertexBuffer9_Unlock(vb);
7392     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7393
7394     hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_positiont);
7395     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7396
7397     hr = IDirect3DDevice9_BeginScene(device);
7398     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7399     if(SUCCEEDED(hr)) {
7400         hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad_transformed[0]));
7401         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7402         hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7403         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7404
7405         hr = IDirect3DDevice9_EndScene(device);
7406         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7407     }
7408
7409     color = getPixelColor(device, 88, 108);
7410     ok(color == 0x000000ff,
7411        "pixel 88/108 has color %08x, expected 0x000000ff\n", color);
7412     color = getPixelColor(device, 92, 108);
7413     ok(color == 0x000000ff,
7414        "pixel 92/108 has color %08x, expected 0x000000ff\n", color);
7415     color = getPixelColor(device, 88, 112);
7416     ok(color == 0x000000ff,
7417        "pixel 88/112 has color %08x, expected 0x000000ff\n", color);
7418     color = getPixelColor(device, 92, 112);
7419     ok(color == 0x00ffff00,
7420        "pixel 92/112 has color %08x, expected 0x00ffff00\n", color);
7421
7422     color = getPixelColor(device, 568, 108);
7423     ok(color == 0x000000ff,
7424        "pixel 568/108 has color %08x, expected 0x000000ff\n", color);
7425     color = getPixelColor(device, 572, 108);
7426     ok(color == 0x000000ff,
7427        "pixel 572/108 has color %08x, expected 0x000000ff\n", color);
7428     color = getPixelColor(device, 568, 112);
7429     ok(color == 0x00ffff00,
7430        "pixel 568/112 has color %08x, expected 0x00ffff00\n", color);
7431     color = getPixelColor(device, 572, 112);
7432     ok(color == 0x000000ff,
7433        "pixel 572/112 has color %08x, expected 0x000000ff\n", color);
7434
7435     color = getPixelColor(device, 88, 298);
7436     ok(color == 0x000000ff,
7437        "pixel 88/298 has color %08x, expected 0x000000ff\n", color);
7438     color = getPixelColor(device, 92, 298);
7439     ok(color == 0x00ffff00,
7440        "pixel 92/298 has color %08x, expected 0x00ffff00\n", color);
7441     color = getPixelColor(device, 88, 302);
7442     ok(color == 0x000000ff,
7443        "pixel 88/302 has color %08x, expected 0x000000ff\n", color);
7444     color = getPixelColor(device, 92, 302);
7445     ok(color == 0x000000ff,
7446        "pixel 92/302 has color %08x, expected 0x000000ff\n", color);
7447
7448     color = getPixelColor(device, 568, 298);
7449     ok(color == 0x00ffff00,
7450        "pixel 568/298 has color %08x, expected 0x00ffff00\n", color);
7451     color = getPixelColor(device, 572, 298);
7452     ok(color == 0x000000ff,
7453        "pixel 572/298 has color %08x, expected 0x000000ff\n", color);
7454     color = getPixelColor(device, 568, 302);
7455     ok(color == 0x000000ff,
7456        "pixel 568/302 has color %08x, expected 0x000000ff\n", color);
7457     color = getPixelColor(device, 572, 302);
7458     ok(color == 0x000000ff,
7459        "pixel 572/302 has color %08x, expected 0x000000ff\n", color);
7460
7461     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7462
7463     /* This test is pointless without those two declarations: */
7464     if((!dcl_color_2) || (!dcl_ubyte_2)) {
7465         skip("color-ubyte switching test declarations aren't supported\n");
7466         goto out;
7467     }
7468
7469     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quads), &data, 0);
7470     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7471     memcpy(data, quads, sizeof(quads));
7472     hr = IDirect3DVertexBuffer9_Unlock(vb);
7473     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7474     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(colors),
7475                                              0, 0, D3DPOOL_MANAGED, &vb2, NULL);
7476     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
7477     hr = IDirect3DVertexBuffer9_Lock(vb2, 0, sizeof(colors), &data, 0);
7478     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7479     memcpy(data, colors, sizeof(colors));
7480     hr = IDirect3DVertexBuffer9_Unlock(vb2);
7481     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7482
7483     for(i = 0; i < 2; i++) {
7484         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
7485         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
7486
7487         hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(float) * 3);
7488         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7489         if(i == 0) {
7490             hr = IDirect3DDevice9_SetStreamSource(device, 1, vb2, 0, sizeof(DWORD) * 4);
7491         } else {
7492             hr = IDirect3DDevice9_SetStreamSource(device, 1, vb2, 8, sizeof(DWORD) * 4);
7493         }
7494         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7495
7496         hr = IDirect3DDevice9_BeginScene(device);
7497         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
7498         ub_ok = FALSE;
7499         if(SUCCEEDED(hr)) {
7500             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2);
7501             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7502             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7503             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7504                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7505             ub_ok = SUCCEEDED(hr);
7506
7507             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color_2);
7508             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7509             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 4, 2);
7510             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7511
7512             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2);
7513             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7514             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 8, 2);
7515             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7516                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7517             ub_ok = (SUCCEEDED(hr) && ub_ok);
7518
7519             hr = IDirect3DDevice9_EndScene(device);
7520             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
7521         }
7522
7523         if(i == 0) {
7524             color = getPixelColor(device, 480, 360);
7525             ok(color == 0x00ff0000,
7526                "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ff0000\n", color);
7527             color = getPixelColor(device, 160, 120);
7528             ok(color == 0x00ffffff,
7529                 "Unused quad returned color %08x, expected 0x00ffffff\n", color);
7530             color = getPixelColor(device, 160, 360);
7531             ok(color == 0x000000ff || !ub_ok,
7532                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x000000ff\n", color);
7533             color = getPixelColor(device, 480, 120);
7534             ok(color == 0x000000ff || !ub_ok,
7535                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x000000ff\n", color);
7536         } else {
7537             color = getPixelColor(device, 480, 360);
7538             ok(color == 0x000000ff,
7539                "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x000000ff\n", color);
7540             color = getPixelColor(device, 160, 120);
7541             ok(color == 0x00ffffff,
7542                "Unused quad returned color %08x, expected 0x00ffffff\n", color);
7543             color = getPixelColor(device, 160, 360);
7544             ok(color == 0x00ff0000 || !ub_ok,
7545                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x00ff0000\n", color);
7546             color = getPixelColor(device, 480, 120);
7547             ok(color == 0x00ff0000 || !ub_ok,
7548                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x00ff0000\n", color);
7549         }
7550         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7551     }
7552
7553     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
7554     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7555     hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
7556     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7557     IDirect3DVertexBuffer9_Release(vb2);
7558
7559     out:
7560     IDirect3DVertexBuffer9_Release(vb);
7561     if(dcl_float) IDirect3DVertexDeclaration9_Release(dcl_float);
7562     if(dcl_short) IDirect3DVertexDeclaration9_Release(dcl_short);
7563     if(dcl_ubyte) IDirect3DVertexDeclaration9_Release(dcl_ubyte);
7564     if(dcl_color) IDirect3DVertexDeclaration9_Release(dcl_color);
7565     if(dcl_color_2) IDirect3DVertexDeclaration9_Release(dcl_color_2);
7566     if(dcl_ubyte_2) IDirect3DVertexDeclaration9_Release(dcl_ubyte_2);
7567     if(dcl_positiont) IDirect3DVertexDeclaration9_Release(dcl_positiont);
7568 }
7569
7570 struct vertex_float16color {
7571     float x, y, z;
7572     DWORD c1, c2;
7573 };
7574
7575 static void test_vshader_float16(IDirect3DDevice9 *device)
7576 {
7577     HRESULT hr;
7578     DWORD color;
7579     void *data;
7580     static const D3DVERTEXELEMENT9 decl_elements[] = {
7581         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7582         {0,  12,  D3DDECLTYPE_FLOAT16_4,D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7583         D3DDECL_END()
7584     };
7585     IDirect3DVertexDeclaration9 *vdecl = NULL;
7586     IDirect3DVertexBuffer9 *buffer = NULL;
7587     IDirect3DVertexShader9 *shader;
7588     DWORD shader_code[] = {
7589         0xfffe0101, 0x0000001f, 0x80000000, 0x900f0000, 0x0000001f, 0x8000000a,
7590         0x900f0001, 0x00000001, 0xc00f0000, 0x90e40000, 0x00000001, 0xd00f0000,
7591         0x90e40001, 0x0000ffff
7592     };
7593     struct vertex_float16color quad[] = {
7594         { -1.0,   -1.0,     0.1,        0x3c000000, 0x00000000 }, /* green */
7595         { -1.0,    0.0,     0.1,        0x3c000000, 0x00000000 },
7596         {  0.0,   -1.0,     0.1,        0x3c000000, 0x00000000 },
7597         {  0.0,    0.0,     0.1,        0x3c000000, 0x00000000 },
7598
7599         {  0.0,   -1.0,     0.1,        0x00003c00, 0x00000000 }, /* red */
7600         {  0.0,    0.0,     0.1,        0x00003c00, 0x00000000 },
7601         {  1.0,   -1.0,     0.1,        0x00003c00, 0x00000000 },
7602         {  1.0,    0.0,     0.1,        0x00003c00, 0x00000000 },
7603
7604         {  0.0,    0.0,     0.1,        0x00000000, 0x00003c00 }, /* blue */
7605         {  0.0,    1.0,     0.1,        0x00000000, 0x00003c00 },
7606         {  1.0,    0.0,     0.1,        0x00000000, 0x00003c00 },
7607         {  1.0,    1.0,     0.1,        0x00000000, 0x00003c00 },
7608
7609         { -1.0,    0.0,     0.1,        0x00000000, 0x3c000000 }, /* alpha */
7610         { -1.0,    1.0,     0.1,        0x00000000, 0x3c000000 },
7611         {  0.0,    0.0,     0.1,        0x00000000, 0x3c000000 },
7612         {  0.0,    1.0,     0.1,        0x00000000, 0x3c000000 },
7613     };
7614
7615     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff102030, 0.0, 0);
7616     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7617
7618     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vdecl);
7619     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed hr=%08x\n", hr);
7620     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
7621     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexShader failed hr=%08x\n", hr);
7622     hr = IDirect3DDevice9_SetVertexShader(device, shader);
7623     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
7624
7625     hr = IDirect3DDevice9_BeginScene(device);
7626     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
7627     if(SUCCEEDED(hr)) {
7628         hr = IDirect3DDevice9_SetVertexDeclaration(device, vdecl);
7629         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%08x\n", hr);
7630         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad +  0, sizeof(quad[0]));
7631         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7632         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad +  4, sizeof(quad[0]));
7633         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7634         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad +  8, sizeof(quad[0]));
7635         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7636         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad + 12, sizeof(quad[0]));
7637         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7638
7639         hr = IDirect3DDevice9_EndScene(device);
7640         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%08x\n", hr);
7641     }
7642     color = getPixelColor(device, 480, 360);
7643     ok(color == 0x00ff0000,
7644        "Input 0x00003c00, 0x00000000 returned color %08x, expected 0x00ff0000\n", color);
7645     color = getPixelColor(device, 160, 120);
7646     ok(color == 0x00000000,
7647        "Input 0x00000000, 0x3c000000 returned color %08x, expected 0x00000000\n", color);
7648     color = getPixelColor(device, 160, 360);
7649     ok(color == 0x0000ff00,
7650        "Input 0x3c000000, 0x00000000 returned color %08x, expected 0x0000ff00\n", color);
7651     color = getPixelColor(device, 480, 120);
7652     ok(color == 0x000000ff,
7653        "Input 0x00000000, 0x00003c00 returned color %08x, expected 0x000000ff\n", color);
7654     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7655
7656     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff102030, 0.0, 0);
7657     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7658
7659     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0,
7660                                              D3DPOOL_MANAGED, &buffer, NULL);
7661     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexBuffer failed, hr=%08x\n", hr);
7662     hr = IDirect3DVertexBuffer9_Lock(buffer, 0, sizeof(quad), &data, 0);
7663     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed, hr=%08x\n", hr);
7664     memcpy(data, quad, sizeof(quad));
7665     hr = IDirect3DVertexBuffer9_Unlock(buffer);
7666     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed, hr=%08x\n", hr);
7667     hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(quad[0]));
7668     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed, hr=%08x\n", hr);
7669
7670     hr = IDirect3DDevice9_BeginScene(device);
7671     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
7672     if(SUCCEEDED(hr)) {
7673             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,  0, 2);
7674             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7675             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,  4, 2);
7676             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7677             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,  8, 2);
7678             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7679             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 12, 2);
7680             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7681
7682             hr = IDirect3DDevice9_EndScene(device);
7683             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%08x\n", hr);
7684     }
7685
7686     color = getPixelColor(device, 480, 360);
7687     ok(color == 0x00ff0000,
7688        "Input 0x00003c00, 0x00000000 returned color %08x, expected 0x00ff0000\n", color);
7689     color = getPixelColor(device, 160, 120);
7690     ok(color == 0x00000000,
7691        "Input 0x00000000, 0x3c000000 returned color %08x, expected 0x00000000\n", color);
7692     color = getPixelColor(device, 160, 360);
7693     ok(color == 0x0000ff00,
7694        "Input 0x3c000000, 0x00000000 returned color %08x, expected 0x0000ff00\n", color);
7695     color = getPixelColor(device, 480, 120);
7696     ok(color == 0x000000ff,
7697        "Input 0x00000000, 0x00003c00 returned color %08x, expected 0x000000ff\n", color);
7698     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7699
7700     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
7701     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed, hr=%08x\n", hr);
7702     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
7703     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%08x\n", hr);
7704     IDirect3DDevice9_SetVertexShader(device, NULL);
7705     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
7706
7707     IDirect3DVertexDeclaration9_Release(vdecl);
7708     IDirect3DVertexShader9_Release(shader);
7709     IDirect3DVertexBuffer9_Release(buffer);
7710 }
7711
7712 static void conditional_np2_repeat_test(IDirect3DDevice9 *device)
7713 {
7714     D3DCAPS9 caps;
7715     IDirect3DTexture9 *texture;
7716     HRESULT hr;
7717     D3DLOCKED_RECT rect;
7718     unsigned int x, y;
7719     DWORD *dst, color;
7720     const float quad[] = {
7721         -1.0,   -1.0,   0.1,   -0.2,   -0.2,
7722          1.0,   -1.0,   0.1,    1.2,   -0.2,
7723         -1.0,    1.0,   0.1,   -0.2,    1.2,
7724          1.0,    1.0,   0.1,    1.2,    1.2
7725     };
7726     memset(&caps, 0, sizeof(caps));
7727
7728     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7729     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%08x\n", hr);
7730     if(!(caps.TextureCaps & D3DPTEXTURECAPS_POW2)) {
7731         /* NP2 conditional requires the POW2 flag. Check that while we're at it */
7732         ok((caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) == 0,
7733            "Card has conditional NP2 support without power of two restriction set\n");
7734         skip("Card has unconditional pow2 support, skipping conditional NP2 tests\n");
7735         return;
7736     } else if(!(caps.TextureCaps & D3DPTEXTURECAPS_POW2)) {
7737         skip("No conditional NP2 support, skipping conditional NP2 tests\n");
7738         return;
7739     }
7740
7741     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
7742     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7743
7744     hr = IDirect3DDevice9_CreateTexture(device, 10, 10, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7745     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed hr=%08x\n", hr);
7746
7747     memset(&rect, 0, sizeof(rect));
7748     hr = IDirect3DTexture9_LockRect(texture, 0, &rect, NULL, 0);
7749     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed hr=%08x\n", hr);
7750     for(y = 0; y < 10; y++) {
7751         for(x = 0; x < 10; x++) {
7752             dst = (DWORD *) ((BYTE *) rect.pBits + y * rect.Pitch + x * sizeof(DWORD));
7753             if(x == 0 || x == 9 || y == 0 || y == 9) {
7754                 *dst = 0x00ff0000;
7755             } else {
7756                 *dst = 0x000000ff;
7757             }
7758         }
7759     }
7760     hr = IDirect3DTexture9_UnlockRect(texture, 0);
7761     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed hr=%08x\n", hr);
7762
7763     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
7764     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
7765     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
7766     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed hr=%08x\n", hr);
7767     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
7768     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed hr=%08x\n", hr);
7769     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7770     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%08x\n", hr);
7771
7772     hr = IDirect3DDevice9_BeginScene(device);
7773     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
7774     if(SUCCEEDED(hr)) {
7775         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
7776         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7777
7778         hr = IDirect3DDevice9_EndScene(device);
7779         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
7780     }
7781
7782     color = getPixelColor(device,    1,  1);
7783     ok(color == 0x00ff0000, "NP2: Pixel   1,  1 has color %08x, expected 0x00ff0000\n", color);
7784     color = getPixelColor(device, 639, 479);
7785     ok(color == 0x00ff0000, "NP2: Pixel 639, 479 has color %08x, expected 0x00ff0000\n", color);
7786
7787     color = getPixelColor(device, 135, 101);
7788     ok(color == 0x00ff0000, "NP2: Pixel 135, 101 has color %08x, expected 0x00ff0000\n", color);
7789     color = getPixelColor(device, 140, 101);
7790     ok(color == 0x00ff0000, "NP2: Pixel 140, 101 has color %08x, expected 0x00ff0000\n", color);
7791     color = getPixelColor(device, 135, 105);
7792     ok(color == 0x00ff0000, "NP2: Pixel 135, 105 has color %08x, expected 0x00ff0000\n", color);
7793     color = getPixelColor(device, 140, 105);
7794     ok(color == 0x000000ff, "NP2: Pixel 140, 105 has color %08x, expected 0x000000ff\n", color);
7795
7796     color = getPixelColor(device, 135, 376);
7797     ok(color == 0x00ff0000, "NP2: Pixel 135, 376 has color %08x, expected 0x00ff0000\n", color);
7798     color = getPixelColor(device, 140, 376);
7799     ok(color == 0x000000ff, "NP2: Pixel 140, 376 has color %08x, expected 0x000000ff\n", color);
7800     color = getPixelColor(device, 135, 379);
7801     ok(color == 0x00ff0000, "NP2: Pixel 135, 379 has color %08x, expected 0x00ff0000\n", color);
7802     color = getPixelColor(device, 140, 379);
7803     ok(color == 0x00ff0000, "NP2: Pixel 140, 379 has color %08x, expected 0x00ff0000\n", color);
7804
7805     color = getPixelColor(device, 500, 101);
7806     ok(color == 0x00ff0000, "NP2: Pixel 500, 101 has color %08x, expected 0x00ff0000\n", color);
7807     color = getPixelColor(device, 504, 101);
7808     ok(color == 0x00ff0000, "NP2: Pixel 504, 101 has color %08x, expected 0x00ff0000\n", color);
7809     color = getPixelColor(device, 500, 105);
7810     ok(color == 0x000000ff, "NP2: Pixel 500, 105 has color %08x, expected 0x000000ff\n", color);
7811     color = getPixelColor(device, 504, 105);
7812     ok(color == 0x00ff0000, "NP2: Pixel 504, 105 has color %08x, expected 0x00ff0000\n", color);
7813
7814     color = getPixelColor(device, 500, 376);
7815     ok(color == 0x000000ff, "NP2: Pixel 500, 376 has color %08x, expected 0x000000ff\n", color);
7816     color = getPixelColor(device, 504, 376);
7817     ok(color == 0x00ff0000, "NP2: Pixel 504, 376 has color %08x, expected 0x00ff0000\n", color);
7818     color = getPixelColor(device, 500, 380);
7819     ok(color == 0x00ff0000, "NP2: Pixel 500, 380 has color %08x, expected 0x00ff0000\n", color);
7820     color = getPixelColor(device, 504, 380);
7821     ok(color == 0x00ff0000, "NP2: Pixel 504, 380 has color %08x, expected 0x00ff0000\n", color);
7822
7823     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7824
7825     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7826     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
7827     IDirect3DTexture9_Release(texture);
7828 }
7829
7830 static void vFace_register_test(IDirect3DDevice9 *device)
7831 {
7832     HRESULT hr;
7833     DWORD color;
7834     const DWORD shader_code[] = {
7835         0xffff0300,                                                             /* ps_3_0                     */
7836         0x05000051, 0xa00f0000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c0, 0.0, 1.0, 0.0, 0.0 */
7837         0x05000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1, 1.0, 0.0, 0.0, 0.0 */
7838         0x0200001f, 0x80000000, 0x900f1001,                                     /* dcl vFace                  */
7839         0x02000001, 0x800f0001, 0xa0e40001,                                     /* mov r1, c1                 */
7840         0x04000058, 0x800f0000, 0x90e41001, 0xa0e40000, 0x80e40001,             /* cmp r0, vFace, c0, r1      */
7841         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                */
7842         0x0000ffff                                                              /* END                        */
7843     };
7844     const DWORD vshader_code[] = {
7845         0xfffe0300,                                                             /* vs_3_0               */
7846         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0      */
7847         0x0200001f, 0x80000000, 0xe00f0000,                                     /* dcl_position o0      */
7848         0x02000001, 0xe00f0000, 0x90e40000,                                     /* mov o0, v0           */
7849         0x0000ffff                                                              /* end                  */
7850     };
7851     IDirect3DPixelShader9 *shader;
7852     IDirect3DVertexShader9 *vshader;
7853     IDirect3DTexture9 *texture;
7854     IDirect3DSurface9 *surface, *backbuffer;
7855     const float quad[] = {
7856         -1.0,   -1.0,   0.1,
7857          1.0,   -1.0,   0.1,
7858         -1.0,    0.0,   0.1,
7859
7860          1.0,   -1.0,   0.1,
7861          1.0,    0.0,   0.1,
7862         -1.0,    0.0,   0.1,
7863
7864         -1.0,    0.0,   0.1,
7865         -1.0,    1.0,   0.1,
7866          1.0,    0.0,   0.1,
7867
7868          1.0,    0.0,   0.1,
7869         -1.0,    1.0,   0.1,
7870          1.0,    1.0,   0.1,
7871     };
7872     const float blit[] = {
7873          0.0,   -1.0,   0.1,    0.0,    0.0,
7874          1.0,   -1.0,   0.1,    1.0,    0.0,
7875          0.0,    1.0,   0.1,    0.0,    1.0,
7876          1.0,    1.0,   0.1,    1.0,    1.0,
7877     };
7878
7879     hr = IDirect3DDevice9_CreateVertexShader(device, vshader_code, &vshader);
7880     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader failed hr=%08x\n", hr);
7881     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
7882     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed hr=%08x\n", hr);
7883     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7884     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed hr=%08x\n", hr);
7885     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7886     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed hr=%08x\n", hr);
7887     hr = IDirect3DDevice9_SetPixelShader(device, shader);
7888     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
7889     hr = IDirect3DDevice9_SetVertexShader(device, vshader);
7890     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
7891     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
7892     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
7893     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7894     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed hr=%08x\n", hr);
7895
7896     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
7897     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7898
7899     hr = IDirect3DDevice9_BeginScene(device);
7900     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
7901     if(SUCCEEDED(hr)) {
7902         /* First, draw to the texture and the back buffer to test both offscreen and onscreen cases */
7903         hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
7904         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
7905         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
7906         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7907         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 4, quad, sizeof(float) * 3);
7908         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7909         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
7910         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
7911         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 4, quad, sizeof(float) * 3);
7912         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7913
7914         /* Blit the texture onto the back buffer to make it visible */
7915         hr = IDirect3DDevice9_SetVertexShader(device, NULL);
7916         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed, hr=%08x\n", hr);
7917         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
7918         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed, hr=%08x\n", hr);
7919         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
7920         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
7921         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
7922         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed, hr=%08x\n", hr);
7923         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
7924         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed, hr=%08x\n", hr);
7925         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7926         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
7927
7928         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, blit, sizeof(float) * 5);
7929         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7930
7931         hr = IDirect3DDevice9_EndScene(device);
7932         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
7933     }
7934
7935     color = getPixelColor(device, 160, 360);
7936     ok(color == 0x00ff0000, "vFace: Onscreen rendered front facing quad has color 0x%08x, expected 0x00ff0000\n", color);
7937     color = getPixelColor(device, 160, 120);
7938     ok(color == 0x0000ff00, "vFace: Onscreen rendered back facing quad has color 0x%08x, expected 0x0000ff00\n", color);
7939     color = getPixelColor(device, 480, 360);
7940     ok(color == 0x0000ff00, "vFace: Offscreen rendered back facing quad has color 0x%08x, expected 0x0000ff00\n", color);
7941     color = getPixelColor(device, 480, 120);
7942     ok(color == 0x00ff0000, "vFace: Offscreen rendered front facing quad has color 0x%08x, expected 0x00ff0000\n", color);
7943     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7944
7945     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
7946     IDirect3DDevice9_SetTexture(device, 0, NULL);
7947     IDirect3DPixelShader9_Release(shader);
7948     IDirect3DVertexShader9_Release(vshader);
7949     IDirect3DSurface9_Release(surface);
7950     IDirect3DSurface9_Release(backbuffer);
7951     IDirect3DTexture9_Release(texture);
7952 }
7953
7954 static void fixed_function_bumpmap_test(IDirect3DDevice9 *device)
7955 {
7956     HRESULT hr;
7957     DWORD color;
7958     int i;
7959     D3DCAPS9 caps;
7960     BOOL L6V5U5_supported = FALSE;
7961     IDirect3DTexture9 *tex1, *tex2;
7962     D3DLOCKED_RECT locked_rect;
7963
7964     static const float quad[][7] = {
7965         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f},
7966         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f},
7967         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 1.0f, 0.0f},
7968         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 1.0f, 1.0f},
7969     };
7970
7971     static const D3DVERTEXELEMENT9 decl_elements[] = {
7972         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7973         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
7974         {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
7975         D3DDECL_END()
7976     };
7977
7978     /* use asymmetric matrix to test loading */
7979     float bumpenvmat[4] = {0.0,0.5,-0.5,0.0};
7980     float scale, offset;
7981
7982     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
7983     IDirect3DTexture9           *texture            = NULL;
7984
7985     memset(&caps, 0, sizeof(caps));
7986     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7987     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%08x\n", hr);
7988     if(!(caps.TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAP)) {
7989         skip("D3DTEXOPCAPS_BUMPENVMAP not set, skipping bumpmap tests\n");
7990         return;
7991     } else {
7992         /* This check is disabled, some Windows drivers do not handle D3DUSAGE_QUERY_LEGACYBUMPMAP properly.
7993          * They report that it is not supported, but after that bump mapping works properly. So just test
7994          * if the format is generally supported, and check the BUMPENVMAP flag
7995          */
7996         IDirect3D9 *d3d9;
7997
7998         IDirect3DDevice9_GetDirect3D(device, &d3d9);
7999         hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
8000                                           D3DRTYPE_TEXTURE, D3DFMT_L6V5U5);
8001         L6V5U5_supported = SUCCEEDED(hr);
8002         hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
8003                                           D3DRTYPE_TEXTURE, D3DFMT_V8U8);
8004         IDirect3D9_Release(d3d9);
8005         if(FAILED(hr)) {
8006             skip("D3DFMT_V8U8 not supported for legacy bump mapping\n");
8007             return;
8008         }
8009     }
8010
8011     /* Generate the textures */
8012     generate_bumpmap_textures(device);
8013
8014     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
8015     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8016     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
8017     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8018     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
8019     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8020     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
8021     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8022
8023     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BUMPENVMAP);
8024     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8025     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
8026     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8027     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_CURRENT );
8028     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8029
8030     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
8031     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8032     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
8033     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8034     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
8035     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8036
8037     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
8038     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8039
8040     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
8041     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
8042
8043     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
8044     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
8045
8046
8047     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
8048     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
8049     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
8050     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
8051
8052     hr = IDirect3DDevice9_BeginScene(device);
8053     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
8054
8055     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
8056     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
8057
8058     hr = IDirect3DDevice9_EndScene(device);
8059     ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
8060
8061     /* on MacOS(10.5.4, radeon X1600), the white dots are have color 0x00fbfbfb rather than 0x00ffffff. This is
8062      * kinda strange since no calculations are done on the sampled colors, only on the texture coordinates.
8063      * But since testing the color match is not the purpose of the test don't be too picky
8064      */
8065     color = getPixelColor(device, 320-32, 240);
8066     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
8067     color = getPixelColor(device, 320+32, 240);
8068     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
8069     color = getPixelColor(device, 320, 240-32);
8070     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
8071     color = getPixelColor(device, 320, 240+32);
8072     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
8073     color = getPixelColor(device, 320, 240);
8074     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
8075     color = getPixelColor(device, 320+32, 240+32);
8076     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
8077     color = getPixelColor(device, 320-32, 240+32);
8078     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
8079     color = getPixelColor(device, 320+32, 240-32);
8080     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
8081     color = getPixelColor(device, 320-32, 240-32);
8082     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
8083     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8084     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
8085
8086     for(i = 0; i < 2; i++) {
8087         hr = IDirect3DDevice9_GetTexture(device, i, (IDirect3DBaseTexture9 **) &texture);
8088         ok(SUCCEEDED(hr), "IDirect3DDevice9_GetTexture failed (0x%08x)\n", hr);
8089         IDirect3DTexture9_Release(texture); /* For the GetTexture */
8090         hr = IDirect3DDevice9_SetTexture(device, i, NULL);
8091         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
8092         IDirect3DTexture9_Release(texture); /* To destroy it */
8093     }
8094
8095     if(!(caps.TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAPLUMINANCE)) {
8096         skip("D3DTOP_BUMPENVMAPLUMINANCE not supported, skipping\n");
8097         goto cleanup;
8098     }
8099     if(L6V5U5_supported == FALSE) {
8100         skip("L6V5U5_supported not supported, skipping D3DTOP_BUMPENVMAPLUMINANCE test\n");
8101         goto cleanup;
8102     }
8103
8104     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0, 0x8);
8105     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
8106     /* This test only tests the luminance part. The bumpmapping part was already tested above and
8107      * would only make this test more complicated
8108      */
8109     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_L6V5U5, D3DPOOL_MANAGED, &tex1, NULL);
8110     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
8111     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &tex2, NULL);
8112     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
8113
8114     memset(&locked_rect, 0, sizeof(locked_rect));
8115     hr = IDirect3DTexture9_LockRect(tex1, 0, &locked_rect, NULL, 0);
8116     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
8117     *((DWORD *)locked_rect.pBits) = 0x4000; /* L = 0.25, V = 0.0, U = 0.0 */
8118     hr = IDirect3DTexture9_UnlockRect(tex1, 0);
8119     ok(SUCCEEDED(hr), "UnlockRect failed with 0x%08x\n", hr);
8120
8121     memset(&locked_rect, 0, sizeof(locked_rect));
8122     hr = IDirect3DTexture9_LockRect(tex2, 0, &locked_rect, NULL, 0);
8123     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
8124     *((DWORD *)locked_rect.pBits) = 0x00ff80c0;
8125     hr = IDirect3DTexture9_UnlockRect(tex2, 0);
8126     ok(SUCCEEDED(hr), "UnlockRect failed with 0x%08x\n", hr);
8127
8128     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex1);
8129     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
8130     hr = IDirect3DDevice9_SetTexture(device, 1, (IDirect3DBaseTexture9 *) tex2);
8131     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
8132
8133     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BUMPENVMAPLUMINANCE);
8134     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8135     scale = 2.0;
8136     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLSCALE, *((DWORD *)&scale));
8137     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8138     offset = 0.1;
8139     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLOFFSET, *((DWORD *)&offset));
8140     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8141
8142     hr = IDirect3DDevice9_BeginScene(device);
8143     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
8144     if(SUCCEEDED(hr)) {
8145         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
8146         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
8147         hr = IDirect3DDevice9_EndScene(device);
8148         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
8149     }
8150
8151     color = getPixelColor(device, 320, 240);
8152     /* red:   1.0  * (0.25 * 2.0 + 0.1) = 1.0  * 0.6 = 0.6  = 0x99
8153      * green: 0.5  * (0.25 * 2.0 + 0.1) = 0.5  * 0.6 = 0.3  = 0x4c
8154      * green: 0.75 * (0.25 * 2.0 + 0.1) = 0.75 * 0.6 = 0.45 = 0x72
8155      */
8156     ok(color_match(color, 0x00994c72, 5), "bumpmap failed: Got color 0x%08x, expected 0x00994c72.\n", color);
8157     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8158     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
8159
8160     /* Check a result scale factor > 1.0 */
8161     scale = 10;
8162     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLSCALE, *((DWORD *)&scale));
8163     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8164     offset = 10;
8165     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLOFFSET, *((DWORD *)&offset));
8166     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8167
8168     hr = IDirect3DDevice9_BeginScene(device);
8169     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
8170     if(SUCCEEDED(hr)) {
8171         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
8172         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
8173         hr = IDirect3DDevice9_EndScene(device);
8174         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
8175     }
8176     color = getPixelColor(device, 320, 240);
8177     ok(color_match(color, 0x00ff80c0, 1), "bumpmap failed: Got color 0x%08x, expected 0x00ff80c0.\n", color);
8178     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8179     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
8180
8181     /* Check clamping in the scale factor calculation */
8182     scale = 1000;
8183     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLSCALE, *((DWORD *)&scale));
8184     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8185     offset = -1;
8186     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLOFFSET, *((DWORD *)&offset));
8187     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8188
8189     hr = IDirect3DDevice9_BeginScene(device);
8190     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
8191     if(SUCCEEDED(hr)) {
8192         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
8193         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
8194         hr = IDirect3DDevice9_EndScene(device);
8195         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
8196     }
8197     color = getPixelColor(device, 320, 240);
8198     ok(color_match(color, 0x00ff80c0, 1), "bumpmap failed: Got color 0x%08x, expected 0x00ff80c0.\n", color);
8199     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8200     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
8201
8202     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
8203     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
8204     hr = IDirect3DDevice9_SetTexture(device, 1, NULL);
8205     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
8206
8207     IDirect3DTexture9_Release(tex1);
8208     IDirect3DTexture9_Release(tex2);
8209
8210 cleanup:
8211     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
8212     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8213     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
8214     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8215
8216     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
8217     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
8218     IDirect3DVertexDeclaration9_Release(vertex_declaration);
8219 }
8220
8221 static void stencil_cull_test(IDirect3DDevice9 *device) {
8222     HRESULT hr;
8223     IDirect3DSurface9 *depthstencil = NULL;
8224     D3DSURFACE_DESC desc;
8225     float quad1[] = {
8226         -1.0,   -1.0,   0.1,
8227          0.0,   -1.0,   0.1,
8228         -1.0,    0.0,   0.1,
8229          0.0,    0.0,   0.1,
8230     };
8231     float quad2[] = {
8232          0.0,   -1.0,   0.1,
8233          1.0,   -1.0,   0.1,
8234          0.0,    0.0,   0.1,
8235          1.0,    0.0,   0.1,
8236     };
8237     float quad3[] = {
8238         0.0,    0.0,   0.1,
8239         1.0,    0.0,   0.1,
8240         0.0,    1.0,   0.1,
8241         1.0,    1.0,   0.1,
8242     };
8243     float quad4[] = {
8244         -1.0,    0.0,   0.1,
8245          0.0,    0.0,   0.1,
8246         -1.0,    1.0,   0.1,
8247          0.0,    1.0,   0.1,
8248     };
8249     struct vertex painter[] = {
8250        {-1.0,   -1.0,   0.0,    0x00000000},
8251        { 1.0,   -1.0,   0.0,    0x00000000},
8252        {-1.0,    1.0,   0.0,    0x00000000},
8253        { 1.0,    1.0,   0.0,    0x00000000},
8254     };
8255     WORD indices_cw[]  = {0, 1, 3};
8256     WORD indices_ccw[] = {0, 2, 3};
8257     unsigned int i;
8258     DWORD color;
8259
8260     IDirect3DDevice9_GetDepthStencilSurface(device, &depthstencil);
8261     if(depthstencil == NULL) {
8262         skip("No depth stencil buffer\n");
8263         return;
8264     }
8265     hr = IDirect3DSurface9_GetDesc(depthstencil, &desc);
8266     ok(hr == D3D_OK, "IDirect3DSurface9_GetDesc failed with %08x\n", hr);
8267     IDirect3DSurface9_Release(depthstencil);
8268     if(desc.Format != D3DFMT_D24S8 && desc.Format != D3DFMT_D24X4S4) {
8269         skip("No 4 or 8 bit stencil surface\n");
8270         return;
8271     }
8272
8273     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_STENCIL, 0x00ff0000, 0.0, 0x8);
8274     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
8275     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8276
8277     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILFAIL, D3DSTENCILOP_INCR);
8278     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8279     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR);
8280     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8281     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
8282     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8283     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILREF, 0x3);
8284     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8285
8286     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_REPLACE);
8287     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8288     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_DECR);
8289     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8290     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CCW_STENCILPASS, D3DSTENCILOP_INCR);
8291     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8292
8293     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, TRUE);
8294     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8295     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TWOSIDEDSTENCILMODE, FALSE);
8296     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8297
8298     /* First pass: Fill the stencil buffer with some values... */
8299     hr = IDirect3DDevice9_BeginScene(device);
8300     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
8301     if(SUCCEEDED(hr))
8302     {
8303         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_CW);
8304         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8305         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8306                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad1, sizeof(float) * 3);
8307         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8308         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8309                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad1, sizeof(float) * 3);
8310         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8311
8312         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TWOSIDEDSTENCILMODE, TRUE);
8313         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8314         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
8315         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8316         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8317                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad2, sizeof(float) * 3);
8318         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8319         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8320                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad2, sizeof(float) * 3);
8321         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8322
8323         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_CW);
8324         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8325         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8326                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad3, sizeof(float) * 3);
8327         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8328         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8329                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad3, sizeof(float) * 3);
8330         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8331
8332         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_CCW);
8333         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8334         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8335                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad4, sizeof(float) * 3);
8336         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8337         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8338                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad4, sizeof(float) * 3);
8339         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8340
8341         hr = IDirect3DDevice9_EndScene(device);
8342         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
8343     }
8344
8345     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8346     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
8347     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8348     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
8349     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8350     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
8351     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8352     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TWOSIDEDSTENCILMODE, FALSE);
8353     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8354     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
8355     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8356     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILFUNC, D3DCMP_EQUAL);
8357     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8358
8359     /* 2nd pass: Make the stencil values visible */
8360     hr = IDirect3DDevice9_BeginScene(device);
8361     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
8362     if(SUCCEEDED(hr))
8363     {
8364         IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
8365         for(i = 0; i < 16; i++) {
8366             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILREF, i);
8367             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8368
8369             painter[0].diffuse = (i * 16); /* Creates shades of blue */
8370             painter[1].diffuse = (i * 16);
8371             painter[2].diffuse = (i * 16);
8372             painter[3].diffuse = (i * 16);
8373             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, painter, sizeof(painter[0]));
8374             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
8375         }
8376         hr = IDirect3DDevice9_EndScene(device);
8377         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
8378     }
8379
8380     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
8381     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8382
8383     color = getPixelColor(device, 160, 420);
8384     ok(color == 0x00000030, "CCW triangle, twoside FALSE, cull cw, replace, has color 0x%08x, expected 0x00000030\n", color);
8385     color = getPixelColor(device, 160, 300);
8386     ok(color == 0x00000080, "CW triangle, twoside FALSE, cull cw, culled, has color 0x%08x, expected 0x00000080\n", color);
8387
8388     color = getPixelColor(device, 480, 420);
8389     ok(color == 0x00000090, "CCW triangle, twoside TRUE, cull off, incr, has color 0x%08x, expected 0x00000090\n", color);
8390     color = getPixelColor(device, 480, 300);
8391     ok(color == 0x00000030, "CW triangle, twoside TRUE, cull off, replace, has color 0x%08x, expected 0x00000030\n", color);
8392
8393     color = getPixelColor(device, 160, 180);
8394     ok(color == 0x00000080, "CCW triangle, twoside TRUE, cull ccw, culled, has color 0x%08x, expected 0x00000080\n", color);
8395     color = getPixelColor(device, 160, 60);
8396     ok(color == 0x00000030, "CW triangle, twoside TRUE, cull ccw, replace, has color 0x%08x, expected 0x00000030\n", color);
8397
8398     color = getPixelColor(device, 480, 180);
8399     ok(color == 0x00000090, "CCW triangle, twoside TRUE, cull cw, incr, has color 0x%08x, expected 0x00000090\n", color);
8400     color = getPixelColor(device, 480, 60);
8401     ok(color == 0x00000080, "CW triangle, twoside TRUE, cull cw, culled, has color 0x%08x, expected 0x00000080\n", color);
8402
8403     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8404     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
8405 }
8406
8407 static void vpos_register_test(IDirect3DDevice9 *device)
8408 {
8409     HRESULT hr;
8410     DWORD color;
8411     const DWORD shader_code[] = {
8412     0xffff0300,                                                             /* ps_3_0                     */
8413     0x0200001f, 0x80000000, 0x90031000,                                     /* dcl vPos.xy                */
8414     0x03000002, 0x80030000, 0x90541000, 0xa1fe0000,                         /* sub r0.xy, vPos.xy, c0.zw  */
8415     0x02000001, 0x800f0001, 0xa0e40000,                                     /* mov r1, c0                 */
8416     0x02000001, 0x80080002, 0xa0550000,                                     /* mov r2.a, c0.y             */
8417     0x02000001, 0x80010002, 0xa0550000,                                     /* mov r2.r, c0.y             */
8418     0x04000058, 0x80020002, 0x80000000, 0x80000001, 0x80550001,             /* cmp r2.g, r0.x, r1.x, r1.y */
8419     0x04000058, 0x80040002, 0x80550000, 0x80000001, 0x80550001,             /* cmp r2.b, r0.y, r1.x, r1.y */
8420     0x02000001, 0x800f0800, 0x80e40002,                                     /* mov oC0, r2                */
8421     0x0000ffff                                                              /* end                        */
8422     };
8423     const DWORD shader_frac_code[] = {
8424     0xffff0300,                                                             /* ps_3_0                     */
8425     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0 */
8426     0x0200001f, 0x80000000, 0x90031000,                                     /* dcl vPos.xy                */
8427     0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                 */
8428     0x02000013, 0x80030000, 0x90541000,                                     /* frc r0.xy, vPos.xy         */
8429     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                */
8430     0x0000ffff                                                              /* end                        */
8431     };
8432     const DWORD vshader_code[] = {
8433         0xfffe0300,                                                             /* vs_3_0               */
8434         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0      */
8435         0x0200001f, 0x80000000, 0xe00f0000,                                     /* dcl_position o0      */
8436         0x02000001, 0xe00f0000, 0x90e40000,                                     /* mov o0, v0           */
8437         0x0000ffff                                                              /* end                  */
8438     };
8439     IDirect3DVertexShader9 *vshader;
8440     IDirect3DPixelShader9 *shader, *shader_frac;
8441     IDirect3DSurface9 *surface = NULL, *backbuffer;
8442     const float quad[] = {
8443         -1.0,   -1.0,   0.1,    0.0,    0.0,
8444          1.0,   -1.0,   0.1,    1.0,    0.0,
8445         -1.0,    1.0,   0.1,    0.0,    1.0,
8446          1.0,    1.0,   0.1,    1.0,    1.0,
8447     };
8448     D3DLOCKED_RECT lr;
8449     float constant[4] = {1.0, 0.0, 320, 240};
8450     DWORD *pos;
8451
8452     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
8453     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8454     hr = IDirect3DDevice9_CreateVertexShader(device, vshader_code, &vshader);
8455     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader failed hr=%08x\n", hr);
8456     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
8457     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed hr=%08x\n", hr);
8458     hr = IDirect3DDevice9_CreatePixelShader(device, shader_frac_code, &shader_frac);
8459     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed hr=%08x\n", hr);
8460     hr = IDirect3DDevice9_SetPixelShader(device, shader);
8461     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
8462     hr = IDirect3DDevice9_SetVertexShader(device, vshader);
8463     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
8464     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8465     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
8466     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
8467     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed hr=%08x\n", hr);
8468
8469     hr = IDirect3DDevice9_BeginScene(device);
8470     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8471     if(SUCCEEDED(hr)) {
8472         hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, constant, 1);
8473         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF failed hr=%08x\n", hr);
8474         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
8475         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8476         hr = IDirect3DDevice9_EndScene(device);
8477         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8478     }
8479
8480     /* This has to be pixel exact */
8481     color = getPixelColor(device, 319, 239);
8482     ok(color == 0x00000000, "vPos: Pixel 319,239 has color 0x%08x, expected 0x00000000\n", color);
8483     color = getPixelColor(device, 320, 239);
8484     ok(color == 0x0000ff00, "vPos: Pixel 320,239 has color 0x%08x, expected 0x0000ff00\n", color);
8485     color = getPixelColor(device, 319, 240);
8486     ok(color == 0x000000ff, "vPos: Pixel 319,240 has color 0x%08x, expected 0x000000ff\n", color);
8487     color = getPixelColor(device, 320, 240);
8488     ok(color == 0x0000ffff, "vPos: Pixel 320,240 has color 0x%08x, expected 0x0000ffff\n", color);
8489     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8490
8491     hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, D3DFMT_X8R8G8B8, 0, 0, TRUE,
8492                                              &surface, NULL);
8493     ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed hr=%08x\n", hr);
8494     hr = IDirect3DDevice9_BeginScene(device);
8495     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8496     if(SUCCEEDED(hr)) {
8497         constant[2] = 16; constant[3] = 16;
8498         hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, constant, 1);
8499         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF failed hr=%08x\n", hr);
8500         hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
8501         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8502         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
8503         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8504         hr = IDirect3DDevice9_EndScene(device);
8505         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8506     }
8507     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, D3DLOCK_READONLY);
8508     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr=%08x\n", hr);
8509
8510     pos = (DWORD *) (((BYTE *) lr.pBits) + 14 * lr.Pitch + 14 * sizeof(DWORD));
8511     color = *pos & 0x00ffffff;
8512     ok(color == 0x00000000, "Pixel 14/14 has color 0x%08x, expected 0x00000000\n", color);
8513     pos = (DWORD *) (((BYTE *) lr.pBits) + 14 * lr.Pitch + 18 * sizeof(DWORD));
8514     color = *pos & 0x00ffffff;
8515     ok(color == 0x0000ff00, "Pixel 14/18 has color 0x%08x, expected 0x0000ff00\n", color);
8516     pos = (DWORD *) (((BYTE *) lr.pBits) + 18 * lr.Pitch + 14 * sizeof(DWORD));
8517     color = *pos & 0x00ffffff;
8518     ok(color == 0x000000ff, "Pixel 18/14 has color 0x%08x, expected 0x000000ff\n", color);
8519     pos = (DWORD *) (((BYTE *) lr.pBits) + 18 * lr.Pitch + 18 * sizeof(DWORD));
8520     color = *pos & 0x00ffffff;
8521     ok(color == 0x0000ffff, "Pixel 18/18 has color 0x%08x, expected 0x0000ffff\n", color);
8522
8523     hr = IDirect3DSurface9_UnlockRect(surface);
8524     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr=%08x\n", hr);
8525
8526     /* Test the fraction value of vPos. This is tested with the offscreen target and not the backbuffer to
8527      * have full control over the multisampling setting inside this test
8528      */
8529     hr = IDirect3DDevice9_SetPixelShader(device, shader_frac);
8530     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
8531     hr = IDirect3DDevice9_BeginScene(device);
8532     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8533     if(SUCCEEDED(hr)) {
8534         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
8535         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8536         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
8537         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8538         hr = IDirect3DDevice9_EndScene(device);
8539         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8540     }
8541     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
8542     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8543
8544     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, D3DLOCK_READONLY);
8545     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr=%08x\n", hr);
8546
8547     pos = (DWORD *) (((BYTE *) lr.pBits) + 14 * lr.Pitch + 14 * sizeof(DWORD));
8548     color = *pos & 0x00ffffff;
8549     ok(color == 0x00000000, "vPos fraction test has color 0x%08x, expected 0x00000000\n", color);
8550
8551     hr = IDirect3DSurface9_UnlockRect(surface);
8552     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr=%08x\n", hr);
8553
8554     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
8555     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
8556     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
8557     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
8558     IDirect3DPixelShader9_Release(shader);
8559     IDirect3DPixelShader9_Release(shader_frac);
8560     IDirect3DVertexShader9_Release(vshader);
8561     if(surface) IDirect3DSurface9_Release(surface);
8562     IDirect3DSurface9_Release(backbuffer);
8563 }
8564
8565 static BOOL point_match(IDirect3DDevice9 *device, UINT x, UINT y, UINT r)
8566 {
8567     D3DCOLOR color;
8568
8569     color = D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0xff);
8570     if (!color_match(getPixelColor(device, x + r, y), color, 1)) return FALSE;
8571     if (!color_match(getPixelColor(device, x - r, y), color, 1)) return FALSE;
8572     if (!color_match(getPixelColor(device, x, y + r), color, 1)) return FALSE;
8573     if (!color_match(getPixelColor(device, x, y - r), color, 1)) return FALSE;
8574
8575     ++r;
8576     color = D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xff);
8577     if (!color_match(getPixelColor(device, x + r, y), color, 1)) return FALSE;
8578     if (!color_match(getPixelColor(device, x - r, y), color, 1)) return FALSE;
8579     if (!color_match(getPixelColor(device, x, y + r), color, 1)) return FALSE;
8580     if (!color_match(getPixelColor(device, x, y - r), color, 1)) return FALSE;
8581
8582     return TRUE;
8583 }
8584
8585 static void pointsize_test(IDirect3DDevice9 *device)
8586 {
8587     HRESULT hr;
8588     D3DCAPS9 caps;
8589     D3DMATRIX matrix;
8590     D3DMATRIX identity;
8591     float ptsize, ptsize_orig, ptsizemax_orig, ptsizemin_orig;
8592     DWORD color;
8593     IDirect3DSurface9 *rt, *backbuffer;
8594     IDirect3DTexture9 *tex1, *tex2;
8595     RECT rect = {0, 0, 128, 128};
8596     D3DLOCKED_RECT lr;
8597     const DWORD tex1_data[4] = {0x00ff0000, 0x00ff0000,
8598                                 0x00000000, 0x00000000};
8599     const DWORD tex2_data[4] = {0x00000000, 0x0000ff00,
8600                                 0x00000000, 0x0000ff00};
8601
8602     const float vertices[] = {
8603         64,     64,     0.1,
8604         128,    64,     0.1,
8605         192,    64,     0.1,
8606         256,    64,     0.1,
8607         320,    64,     0.1,
8608         384,    64,     0.1,
8609         448,    64,     0.1,
8610         512,    64,     0.1,
8611     };
8612
8613     /* Transforms the coordinate system [-1.0;1.0]x[-1.0;1.0] to [0.0;0.0]x[640.0;480.0]. Z is untouched */
8614     U(matrix).m[0][0] = 2.0/640.0; U(matrix).m[1][0] = 0.0;       U(matrix).m[2][0] = 0.0;   U(matrix).m[3][0] =-1.0;
8615     U(matrix).m[0][1] = 0.0;       U(matrix).m[1][1] =-2.0/480.0; U(matrix).m[2][1] = 0.0;   U(matrix).m[3][1] = 1.0;
8616     U(matrix).m[0][2] = 0.0;       U(matrix).m[1][2] = 0.0;       U(matrix).m[2][2] = 1.0;   U(matrix).m[3][2] = 0.0;
8617     U(matrix).m[0][3] = 0.0;       U(matrix).m[1][3] = 0.0;       U(matrix).m[2][3] = 0.0;   U(matrix).m[3][3] = 1.0;
8618
8619     U(identity).m[0][0] = 1.0;     U(identity).m[1][0] = 0.0;     U(identity).m[2][0] = 0.0; U(identity).m[3][0] = 0.0;
8620     U(identity).m[0][1] = 0.0;     U(identity).m[1][1] = 1.0;     U(identity).m[2][1] = 0.0; U(identity).m[3][1] = 0.0;
8621     U(identity).m[0][2] = 0.0;     U(identity).m[1][2] = 0.0;     U(identity).m[2][2] = 1.0; U(identity).m[3][2] = 0.0;
8622     U(identity).m[0][3] = 0.0;     U(identity).m[1][3] = 0.0;     U(identity).m[2][3] = 0.0; U(identity).m[3][3] = 1.0;
8623
8624     memset(&caps, 0, sizeof(caps));
8625     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8626     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%08x\n", hr);
8627     if(caps.MaxPointSize < 32.0) {
8628         skip("MaxPointSize < 32.0, skipping(MaxPointsize = %f)\n", caps.MaxPointSize);
8629         return;
8630     }
8631
8632     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 0.0, 0);
8633     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8634     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, &matrix);
8635     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed, hr=%08x\n", hr);
8636     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8637     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
8638     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSIZE, (DWORD *) &ptsize_orig);
8639     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed hr=%08x\n", hr);
8640
8641     hr = IDirect3DDevice9_BeginScene(device);
8642     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8643     if (SUCCEEDED(hr))
8644     {
8645         ptsize = 15.0;
8646         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8647         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8648         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[0], sizeof(float) * 3);
8649         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8650
8651         ptsize = 31.0;
8652         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8653         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8654         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[3], sizeof(float) * 3);
8655         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8656
8657         ptsize = 30.75;
8658         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8659         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8660         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[6], sizeof(float) * 3);
8661         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8662
8663         if (caps.MaxPointSize >= 63.0)
8664         {
8665             ptsize = 63.0;
8666             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8667             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8668             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[9], sizeof(float) * 3);
8669             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8670
8671             ptsize = 62.75;
8672             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8673             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8674             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[15], sizeof(float) * 3);
8675             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8676         }
8677
8678         ptsize = 1.0;
8679         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8680         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8681         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[12], sizeof(float) * 3);
8682         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8683
8684         hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSIZE_MAX, (DWORD *) (&ptsizemax_orig));
8685         ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed, hr=%08x\n", hr);
8686         hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSIZE_MIN, (DWORD *) (&ptsizemin_orig));
8687         ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed, hr=%08x\n", hr);
8688
8689         /* What happens if point scaling is disabled, and POINTSIZE_MAX < POINTSIZE? */
8690         ptsize = 15.0;
8691         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8692         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8693         ptsize = 1.0;
8694         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MAX, *((DWORD *) (&ptsize)));
8695         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8696         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[18], sizeof(float) * 3);
8697         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8698
8699         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MAX, *((DWORD *) (&ptsizemax_orig)));
8700         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8701
8702         /* pointsize < pointsize_min < pointsize_max?
8703          * pointsize = 1.0, pointsize_min = 15.0, pointsize_max = default(usually 64.0) */
8704         ptsize = 1.0;
8705         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8706         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8707         ptsize = 15.0;
8708         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MIN, *((DWORD *) (&ptsize)));
8709         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8710         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[21], sizeof(float) * 3);
8711         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8712
8713         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MIN, *((DWORD *) (&ptsizemin_orig)));
8714         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8715
8716         hr = IDirect3DDevice9_EndScene(device);
8717         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8718     }
8719
8720     ok(point_match(device, 64, 64, 7), "point_match(64, 64, 7) failed, expected point size 15.\n");
8721     ok(point_match(device, 128, 64, 15), "point_match(128, 64, 15) failed, expected point size 31.\n");
8722     ok(point_match(device, 192, 64, 15), "point_match(192, 64, 15) failed, expected point size 31.\n");
8723
8724     if (caps.MaxPointSize >= 63.0)
8725     {
8726         ok(point_match(device, 256, 64, 31), "point_match(256, 64, 31) failed, expected point size 63.\n");
8727         ok(point_match(device, 384, 64, 31), "point_match(384, 64, 31) failed, expected point size 63.\n");
8728     }
8729
8730     ok(point_match(device, 320, 64, 0), "point_match(320, 64, 0) failed, expected point size 1.\n");
8731     /* ptsize = 15, ptsize_max = 1 --> point has size 1 */
8732     ok(point_match(device, 448, 64, 0), "point_match(448, 64, 0) failed, expected point size 1.\n");
8733     /* ptsize = 1, ptsize_max = default(64), ptsize_min = 15 --> point has size 15 */
8734     ok(point_match(device, 512, 64, 7), "point_match(512, 64, 7) failed, expected point size 15.\n");
8735
8736     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8737
8738     /* The following code tests point sprites with two textures, to see if each texture coordinate unit
8739      * generates texture coordinates for the point(result: Yes, it does)
8740      *
8741      * However, not all GL implementations support point sprites(they need GL_ARB_point_sprite), but there
8742      * is no point sprite cap bit in d3d because native d3d software emulates point sprites. Until the
8743      * SW emulation is implemented in wined3d, this test will fail on GL drivers that does not support them.
8744      */
8745     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 0.0, 0);
8746     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8747
8748     hr = IDirect3DDevice9_CreateTexture(device, 2, 2, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tex1, NULL);
8749     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed hr=%08x\n", hr);
8750     hr = IDirect3DDevice9_CreateTexture(device, 2, 2, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tex2, NULL);
8751     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed hr=%08x\n", hr);
8752     memset(&lr, 0, sizeof(lr));
8753     hr = IDirect3DTexture9_LockRect(tex1, 0, &lr, NULL, 0);
8754     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed hr=%08x\n", hr);
8755     memcpy(lr.pBits, tex1_data, sizeof(tex1_data));
8756     hr = IDirect3DTexture9_UnlockRect(tex1, 0);
8757     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed hr=%08x\n", hr);
8758     memset(&lr, 0, sizeof(lr));
8759     hr = IDirect3DTexture9_LockRect(tex2, 0, &lr, NULL, 0);
8760     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed hr=%08x\n", hr);
8761     memcpy(lr.pBits, tex2_data, sizeof(tex2_data));
8762     hr = IDirect3DTexture9_UnlockRect(tex2, 0);
8763     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed hr=%08x\n", hr);
8764     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex1);
8765     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
8766     hr = IDirect3DDevice9_SetTexture(device, 1, (IDirect3DBaseTexture9 *) tex2);
8767     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
8768     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
8769     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed hr=%08x\n", hr);
8770     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
8771     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed hr=%08x\n", hr);
8772     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
8773     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed hr=%08x\n", hr);
8774     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
8775     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed hr=%08x\n", hr);
8776     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
8777     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed hr=%08x\n", hr);
8778
8779     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSPRITEENABLE, TRUE);
8780     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed hr=%08x\n", hr);
8781     ptsize = 32.0;
8782     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8783     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8784
8785     hr = IDirect3DDevice9_BeginScene(device);
8786     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed, hr=%08x\n", hr);
8787     if(SUCCEEDED(hr))
8788     {
8789         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[0], sizeof(float) * 3);
8790         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8791         hr = IDirect3DDevice9_EndScene(device);
8792         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%08x\n", hr);
8793     }
8794
8795     color = getPixelColor(device, 64-4, 64-4);
8796     ok(color == 0x00ff0000, "pSprite: Pixel (64-4),(64-4) has color 0x%08x, expected 0x00ff0000\n", color);
8797     color = getPixelColor(device, 64-4, 64+4);
8798     ok(color == 0x00000000, "pSprite: Pixel (64-4),(64+4) has color 0x%08x, expected 0x00000000\n", color);
8799     color = getPixelColor(device, 64+4, 64+4);
8800     ok(color == 0x0000ff00, "pSprite: Pixel (64+4),(64+4) has color 0x%08x, expected 0x0000ff00\n", color);
8801     color = getPixelColor(device, 64+4, 64-4);
8802     ok(color == 0x00ffff00, "pSprite: Pixel (64+4),(64-4) has color 0x%08x, expected 0x00ffff00\n", color);
8803     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8804
8805     U(matrix).m[0][0] =  1.0f / 64.0f;
8806     U(matrix).m[1][1] = -1.0f / 64.0f;
8807     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, &matrix);
8808     ok(SUCCEEDED(hr), "SetTransform failed, hr %#x.\n", hr);
8809
8810     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
8811     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
8812
8813     hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
8814             D3DMULTISAMPLE_NONE, 0, TRUE, &rt, NULL );
8815     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
8816
8817     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
8818     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
8819     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ffff, 0.0f, 0);
8820     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
8821
8822     hr = IDirect3DDevice9_BeginScene(device);
8823     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
8824     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[0], sizeof(float) * 3);
8825     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
8826     hr = IDirect3DDevice9_EndScene(device);
8827     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
8828
8829     hr = IDirect3DDevice9_StretchRect(device, rt, &rect, backbuffer, &rect, D3DTEXF_NONE);
8830     ok(SUCCEEDED(hr), "StretchRect failed, hr %#x.\n", hr);
8831     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
8832     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
8833     IDirect3DSurface9_Release(backbuffer);
8834     IDirect3DSurface9_Release(rt);
8835
8836     color = getPixelColor(device, 64-4, 64-4);
8837     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00), 0),
8838             "Expected color 0x00ff0000, got 0x%08x.\n", color);
8839     color = getPixelColor(device, 64+4, 64-4);
8840     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00), 0),
8841             "Expected color 0x00ffff00, got 0x%08x.\n", color);
8842     color = getPixelColor(device, 64-4, 64+4);
8843     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00), 0),
8844             "Expected color 0x00000000, got 0x%08x.\n", color);
8845     color = getPixelColor(device, 64+4, 64+4);
8846     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 0),
8847             "Expected color 0x0000ff00, got 0x%08x.\n", color);
8848
8849     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8850     ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
8851
8852     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
8853     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed hr=%08x\n", hr);
8854     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
8855     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed hr=%08x\n", hr);
8856     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
8857     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
8858     hr = IDirect3DDevice9_SetTexture(device, 1, NULL);
8859     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
8860     IDirect3DTexture9_Release(tex1);
8861     IDirect3DTexture9_Release(tex2);
8862
8863     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSPRITEENABLE, FALSE);
8864     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed hr=%08x\n", hr);
8865     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize_orig)));
8866     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed hr=%08x\n", hr);
8867     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, &identity);
8868     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed, hr=%08x\n", hr);
8869 }
8870
8871 static void multiple_rendertargets_test(IDirect3DDevice9 *device)
8872 {
8873     static const DWORD vshader_code[] =
8874     {
8875         0xfffe0300,                                                             /* vs_3_0                     */
8876         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0            */
8877         0x0200001f, 0x80000000, 0xe00f0000,                                     /* dcl_position o0            */
8878         0x02000001, 0xe00f0000, 0x90e40000,                                     /* mov o0, v0                 */
8879         0x0000ffff                                                              /* end                        */
8880     };
8881     static const DWORD pshader_code1[] =
8882     {
8883         0xffff0300,                                                             /* ps_3_0                     */
8884         0x05000051, 0xa00f0000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c0, 0.0, 1.0, 0.0, 0.0 */
8885         0x02000001, 0x800f0800, 0xa0e40000,                                     /* mov oC0, c0                */
8886         0x0000ffff                                                              /* end                        */
8887     };
8888     static const DWORD pshader_code2[] =
8889     {
8890         0xffff0300,                                                             /* ps_3_0                     */
8891         0x05000051, 0xa00f0000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c0, 0.0, 1.0, 0.0, 0.0 */
8892         0x05000051, 0xa00f0001, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, /* def c1, 0.0, 0.0, 1.0, 0.0 */
8893         0x02000001, 0x800f0800, 0xa0e40000,                                     /* mov oC0, c0                */
8894         0x02000001, 0x800f0801, 0xa0e40001,                                     /* mov oC1, c1                */
8895         0x0000ffff                                                              /* end                        */
8896     };
8897
8898     HRESULT hr;
8899     IDirect3DVertexShader9 *vs;
8900     IDirect3DPixelShader9 *ps1, *ps2;
8901     IDirect3DTexture9 *tex1, *tex2;
8902     IDirect3DSurface9 *surf1, *surf2, *backbuf, *readback;
8903     D3DCAPS9 caps;
8904     DWORD color;
8905     UINT i, j;
8906     float quad[] = {
8907        -1.0,   -1.0,    0.1,
8908         1.0,   -1.0,    0.1,
8909        -1.0,    1.0,    0.1,
8910         1.0,    1.0,    0.1,
8911     };
8912     float texquad[] = {
8913        -1.0,   -1.0,    0.1,    0.0,    0.0,
8914         0.0,   -1.0,    0.1,    1.0,    0.0,
8915        -1.0,    1.0,    0.1,    0.0,    1.0,
8916         0.0,    1.0,    0.1,    1.0,    1.0,
8917
8918         0.0,   -1.0,    0.1,    0.0,    0.0,
8919         1.0,   -1.0,    0.1,    1.0,    0.0,
8920         0.0,    1.0,    0.1,    0.0,    1.0,
8921         1.0,    1.0,    0.1,    1.0,    1.0,
8922     };
8923
8924     memset(&caps, 0, sizeof(caps));
8925     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8926     ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed, hr=%08x\n", hr);
8927     if(caps.NumSimultaneousRTs < 2) {
8928         skip("Only 1 simultaneous render target supported, skipping MRT test\n");
8929         return;
8930     }
8931
8932     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0, 0);
8933     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8934
8935     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 16, 16,
8936             D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &readback, NULL);
8937     ok(SUCCEEDED(hr), "CreateOffscreenPlainSurface failed, hr %#x.\n", hr);
8938
8939     hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, D3DUSAGE_RENDERTARGET,
8940             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex1, NULL);
8941     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
8942     hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, D3DUSAGE_RENDERTARGET,
8943             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex2, NULL);
8944     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
8945     hr = IDirect3DDevice9_CreateVertexShader(device, vshader_code, &vs);
8946     ok(SUCCEEDED(hr), "CreateVertexShader failed, hr %#x.\n", hr);
8947     hr = IDirect3DDevice9_CreatePixelShader(device, pshader_code1, &ps1);
8948     ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr);
8949     hr = IDirect3DDevice9_CreatePixelShader(device, pshader_code2, &ps2);
8950     ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr);
8951
8952     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuf);
8953     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderTarget failed, hr=%08x\n", hr);
8954     hr = IDirect3DTexture9_GetSurfaceLevel(tex1, 0, &surf1);
8955     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed, hr=%08x\n", hr);
8956     hr = IDirect3DTexture9_GetSurfaceLevel(tex2, 0, &surf2);
8957     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed, hr=%08x\n", hr);
8958
8959     hr = IDirect3DDevice9_SetVertexShader(device, vs);
8960     ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
8961     hr = IDirect3DDevice9_SetRenderTarget(device, 0, surf1);
8962     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8963     hr = IDirect3DDevice9_SetRenderTarget(device, 1, surf2);
8964     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8965     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8966     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr=%08x\n", hr);
8967
8968     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
8969     ok(SUCCEEDED(hr), "Clear failed, hr %#x,\n", hr);
8970     hr = IDirect3DDevice9_GetRenderTargetData(device, surf1, readback);
8971     ok(SUCCEEDED(hr), "GetRenderTargetData failed, hr %#x.\n", hr);
8972     color = getPixelColorFromSurface(readback, 8, 8);
8973     ok(color_match(color, D3DCOLOR_ARGB(0xff, 0x00, 0x00, 0xff), 0),
8974             "Expected color 0x000000ff, got 0x%08x.\n", color);
8975     hr = IDirect3DDevice9_GetRenderTargetData(device, surf2, readback);
8976     ok(SUCCEEDED(hr), "GetRenderTargetData failed, hr %#x.\n", hr);
8977     color = getPixelColorFromSurface(readback, 8, 8);
8978     ok(color_match(color, D3DCOLOR_ARGB(0xff, 0x00, 0x00, 0xff), 0),
8979             "Expected color 0x000000ff, got 0x%08x.\n", color);
8980
8981     /* Render targets not written by the pixel shader should be unmodified. */
8982     hr = IDirect3DDevice9_SetPixelShader(device, ps1);
8983     ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
8984     hr = IDirect3DDevice9_BeginScene(device);
8985     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
8986     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
8987     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
8988     hr = IDirect3DDevice9_EndScene(device);
8989     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
8990     hr = IDirect3DDevice9_GetRenderTargetData(device, surf1, readback);
8991     ok(SUCCEEDED(hr), "GetRenderTargetData failed, hr %#x.\n", hr);
8992     color = getPixelColorFromSurface(readback, 8, 8);
8993     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 0),
8994             "Expected color 0xff00ff00, got 0x%08x.\n", color);
8995     hr = IDirect3DDevice9_GetRenderTargetData(device, surf2, readback);
8996     ok(SUCCEEDED(hr), "GetRenderTargetData failed, hr %#x.\n", hr);
8997     for (i = 6; i < 10; ++i)
8998     {
8999         for (j = 6; j < 10; ++j)
9000         {
9001             color = getPixelColorFromSurface(readback, j, i);
9002             ok(color_match(color, D3DCOLOR_ARGB(0xff, 0x00, 0x00, 0xff), 0),
9003                     "Expected color 0xff0000ff, got 0x%08x at %u, %u.\n", color, j, i);
9004         }
9005     }
9006
9007     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
9008     ok(SUCCEEDED(hr), "Clear failed, hr %#x,\n", hr);
9009     hr = IDirect3DDevice9_GetRenderTargetData(device, surf1, readback);
9010     ok(SUCCEEDED(hr), "GetRenderTargetData failed, hr %#x.\n", hr);
9011     color = getPixelColorFromSurface(readback, 8, 8);
9012     ok(color_match(color, D3DCOLOR_ARGB(0xff, 0x00, 0xff, 0x00), 0),
9013             "Expected color 0x0000ff00, got 0x%08x.\n", color);
9014     hr = IDirect3DDevice9_GetRenderTargetData(device, surf2, readback);
9015     ok(SUCCEEDED(hr), "GetRenderTargetData failed, hr %#x.\n", hr);
9016     color = getPixelColorFromSurface(readback, 8, 8);
9017     ok(color_match(color, D3DCOLOR_ARGB(0xff, 0x00, 0xff, 0x00), 0),
9018             "Expected color 0x0000ff00, got 0x%08x.\n", color);
9019
9020     hr = IDirect3DDevice9_SetPixelShader(device, ps2);
9021     ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
9022
9023     hr = IDirect3DDevice9_BeginScene(device);
9024     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed, hr=%08x\n", hr);
9025     if(SUCCEEDED(hr)) {
9026         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
9027         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
9028
9029         hr = IDirect3DDevice9_SetVertexShader(device, NULL);
9030         ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
9031         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
9032         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed, hr=%08x\n", hr);
9033         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuf);
9034         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
9035         hr = IDirect3DDevice9_SetRenderTarget(device, 1, NULL);
9036         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
9037         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
9038         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr=%08x\n", hr);
9039
9040         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex1);
9041         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
9042         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &texquad[0], 5 * sizeof(float));
9043         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
9044
9045         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex2);
9046         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
9047         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &texquad[20], 5 * sizeof(float));
9048         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
9049
9050         hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
9051         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
9052
9053         hr = IDirect3DDevice9_EndScene(device);
9054         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%08x\n", hr);
9055     }
9056
9057     color = getPixelColor(device, 160, 240);
9058     ok(color == 0x0000ff00, "Texture 1(output color 1) has color 0x%08x, expected 0x0000ff00\n", color);
9059     color = getPixelColor(device, 480, 240);
9060     ok(color == 0x000000ff, "Texture 2(output color 2) has color 0x%08x, expected 0x000000ff\n", color);
9061     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9062
9063     IDirect3DPixelShader9_Release(ps2);
9064     IDirect3DPixelShader9_Release(ps1);
9065     IDirect3DVertexShader9_Release(vs);
9066     IDirect3DTexture9_Release(tex1);
9067     IDirect3DTexture9_Release(tex2);
9068     IDirect3DSurface9_Release(surf1);
9069     IDirect3DSurface9_Release(surf2);
9070     IDirect3DSurface9_Release(backbuf);
9071     IDirect3DSurface9_Release(readback);
9072 }
9073
9074 struct formats {
9075     const char *fmtName;
9076     D3DFORMAT textureFormat;
9077     DWORD resultColorBlending;
9078     DWORD resultColorNoBlending;
9079 };
9080
9081 static const struct formats test_formats[] = {
9082   { "D3DFMT_G16R16", D3DFMT_G16R16, 0x001818ff, 0x002010ff},
9083   { "D3DFMT_R16F", D3DFMT_R16F, 0x0018ffff, 0x0020ffff },
9084   { "D3DFMT_G16R16F", D3DFMT_G16R16F, 0x001818ff, 0x002010ff },
9085   { "D3DFMT_A16B16G16R16F", D3DFMT_A16B16G16R16F, 0x00181800, 0x00201000 },
9086   { "D3DFMT_R32F", D3DFMT_R32F, 0x0018ffff, 0x0020ffff },
9087   { "D3DFMT_G32R32F", D3DFMT_G32R32F, 0x001818ff, 0x002010ff },
9088   { "D3DFMT_A32B32G32R32F", D3DFMT_A32B32G32R32F, 0x00181800, 0x00201000 },
9089   { NULL, 0 }
9090 };
9091
9092 static void pixelshader_blending_test(IDirect3DDevice9 *device)
9093 {
9094     HRESULT hr;
9095     IDirect3DTexture9 *offscreenTexture = NULL;
9096     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
9097     IDirect3D9 *d3d = NULL;
9098     DWORD color;
9099     DWORD r0, g0, b0, r1, g1, b1;
9100     int fmt_index;
9101
9102     static const float quad[][5] = {
9103         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
9104         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
9105         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
9106         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
9107     };
9108
9109     /* Quad with R=0x10, G=0x20 */
9110     static const struct vertex quad1[] = {
9111         {-1.0f, -1.0f, 0.1f, 0x80102000},
9112         {-1.0f,  1.0f, 0.1f, 0x80102000},
9113         { 1.0f, -1.0f, 0.1f, 0x80102000},
9114         { 1.0f,  1.0f, 0.1f, 0x80102000},
9115     };
9116
9117     /* Quad with R=0x20, G=0x10 */
9118     static const struct vertex quad2[] = {
9119         {-1.0f, -1.0f, 0.1f, 0x80201000},
9120         {-1.0f,  1.0f, 0.1f, 0x80201000},
9121         { 1.0f, -1.0f, 0.1f, 0x80201000},
9122         { 1.0f,  1.0f, 0.1f, 0x80201000},
9123     };
9124
9125     IDirect3DDevice9_GetDirect3D(device, &d3d);
9126
9127     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
9128     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
9129     if(!backbuffer) {
9130         goto out;
9131     }
9132
9133     for(fmt_index=0; test_formats[fmt_index].textureFormat != 0; fmt_index++)
9134     {
9135         D3DFORMAT fmt = test_formats[fmt_index].textureFormat;
9136
9137         if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
9138                 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, fmt) != D3D_OK)
9139         {
9140             skip("%s textures not supported as render targets.\n", test_formats[fmt_index].fmtName);
9141             continue;
9142         }
9143
9144         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
9145         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
9146
9147         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, fmt, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
9148         ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %08x\n", hr);
9149         if(!offscreenTexture) {
9150             continue;
9151         }
9152
9153         hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
9154         ok(hr == D3D_OK, "Can't get offscreen surface, hr = %08x\n", hr);
9155         if(!offscreen) {
9156             continue;
9157         }
9158
9159         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
9160         ok(hr == D3D_OK, "SetFVF failed, hr = %08x\n", hr);
9161
9162         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9163         ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9164         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9165         ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9166         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
9167         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
9168         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
9169         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
9170         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
9171         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
9172
9173         /* Below we will draw two quads with different colors and try to blend them together.
9174          * The result color is compared with the expected outcome.
9175          */
9176         if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
9177             hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
9178             ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
9179             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 0.0, 0);
9180             ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
9181
9182             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
9183             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
9184
9185             /* Draw a quad using color 0x0010200 */
9186             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_ONE);
9187             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
9188             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_ZERO);
9189             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
9190             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
9191             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
9192
9193             /* Draw a quad using color 0x0020100 */
9194             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
9195             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
9196             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
9197             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
9198             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
9199             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
9200
9201             /* We don't want to blend the result on the backbuffer */
9202             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
9203             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
9204
9205             /* Prepare rendering the 'blended' texture quad to the backbuffer */
9206             hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
9207             ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
9208             hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
9209             ok(hr == D3D_OK, "SetTexture failed, %08x\n", hr);
9210
9211             hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
9212             ok(hr == D3D_OK, "SetFVF failed, hr = %08x\n", hr);
9213
9214             /* This time with the texture */
9215             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
9216             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %08x\n", hr);
9217
9218             IDirect3DDevice9_EndScene(device);
9219         }
9220
9221         if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, fmt) == D3D_OK) {
9222             /* Compare the color of the center quad with our expectation */
9223             color = getPixelColor(device, 320, 240);
9224             r0 = (color & 0x00ff0000) >> 16;
9225             g0 = (color & 0x0000ff00) >>  8;
9226             b0 = (color & 0x000000ff) >>  0;
9227
9228             r1 = (test_formats[fmt_index].resultColorBlending & 0x00ff0000) >> 16;
9229             g1 = (test_formats[fmt_index].resultColorBlending & 0x0000ff00) >>  8;
9230             b1 = (test_formats[fmt_index].resultColorBlending & 0x000000ff) >>  0;
9231
9232             ok(r0 >= max(r1, 1) - 1 && r0 <= r1 + 1 &&
9233                g0 >= max(g1, 1) - 1 && g0 <= g1 + 1 &&
9234                b0 >= max(b1, 1) - 1 && b0 <= b1 + 1,
9235                "Offscreen failed for %s: Got color %#08x, expected %#08x.\n", test_formats[fmt_index].fmtName, color, test_formats[fmt_index].resultColorBlending);
9236         } else {
9237             /* No pixel shader blending is supported so expect garbage. The type of 'garbage' depends on the driver version and OS.
9238              * E.g. on G16R16 ati reports (on old r9600 drivers) 0x00ffffff and on modern ones 0x002010ff which is also what Nvidia
9239              * reports. On Vista Nvidia seems to report 0x00ffffff on Geforce7 cards. */
9240             color = getPixelColor(device, 320, 240);
9241             ok((color == 0x00ffffff) || (color == test_formats[fmt_index].resultColorNoBlending), "Offscreen failed for %s: expected no color blending but received it anyway.\n", test_formats[fmt_index].fmtName);
9242         }
9243         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9244
9245         IDirect3DDevice9_SetTexture(device, 0, NULL);
9246         if(offscreenTexture) {
9247             IDirect3DTexture9_Release(offscreenTexture);
9248         }
9249         if(offscreen) {
9250             IDirect3DSurface9_Release(offscreen);
9251         }
9252     }
9253
9254 out:
9255     /* restore things */
9256     if(backbuffer) {
9257         IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
9258         IDirect3DSurface9_Release(backbuffer);
9259     }
9260 }
9261
9262 static void tssargtemp_test(IDirect3DDevice9 *device)
9263 {
9264     HRESULT hr;
9265     DWORD color;
9266     static const struct vertex quad[] = {
9267         {-1.0,     -1.0,    0.1,    0x00ff0000},
9268         { 1.0,     -1.0,    0.1,    0x00ff0000},
9269         {-1.0,      1.0,    0.1,    0x00ff0000},
9270         { 1.0,      1.0,    0.1,    0x00ff0000}
9271     };
9272     D3DCAPS9 caps;
9273
9274     memset(&caps, 0, sizeof(caps));
9275     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9276     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
9277     if(!(caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP)) {
9278         skip("D3DPMISCCAPS_TSSARGTEMP not supported\n");
9279         return;
9280     }
9281
9282     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
9283     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9284
9285     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9286     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9287     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
9288     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9289
9290     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9291     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9292     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
9293     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9294     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_RESULTARG, D3DTA_TEMP);
9295     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9296
9297     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_ADD);
9298     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9299     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLORARG1, D3DTA_CURRENT);
9300     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9301     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLORARG2, D3DTA_TEMP);
9302     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9303
9304     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_COLOROP, D3DTOP_DISABLE);
9305     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9306
9307     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0x0000ff00);
9308     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
9309     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
9310     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %08x\n", hr);
9311
9312     hr = IDirect3DDevice9_BeginScene(device);
9313     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed, hr = %08x\n", hr);
9314     if(SUCCEEDED(hr)) {
9315         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
9316         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed with %08x\n", hr);
9317         hr = IDirect3DDevice9_EndScene(device);
9318         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr = %08x\n", hr);
9319     }
9320     color = getPixelColor(device, 320, 240);
9321     ok(color == 0x00FFFF00, "TSSARGTEMP test returned color 0x%08x, expected 0x00FFFF00\n", color);
9322     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9323
9324     /* Set stage 1 back to default */
9325     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_RESULTARG, D3DTA_CURRENT);
9326     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9327     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
9328     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9329     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
9330     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9331     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
9332     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9333     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_COLOROP, D3DTOP_DISABLE);
9334     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9335 }
9336
9337 struct testdata
9338 {
9339     DWORD idxVertex; /* number of instances in the first stream */
9340     DWORD idxColor; /* number of instances in the second stream */
9341     DWORD idxInstance; /* should be 1 ?? */
9342     DWORD color1; /* color 1 instance */
9343     DWORD color2; /* color 2 instance */
9344     DWORD color3; /* color 3 instance */
9345     DWORD color4; /* color 4 instance */
9346     WORD strVertex; /* specify which stream to use 0-2*/
9347     WORD strColor;
9348     WORD strInstance;
9349 };
9350
9351 static const struct testdata testcases[]=
9352 {
9353     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  0 */
9354     {3, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0, 1, 2}, /*  1 */
9355     {2, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0, 1, 2}, /*  2 */
9356     {1, 4, 1, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0, 1, 2}, /*  3 */
9357     {4, 3, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  4 */
9358     {4, 2, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  5 */
9359     {4, 1, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  6 */
9360     {4, 0, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  7 */
9361     {3, 3, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0, 1, 2}, /*  8 */
9362     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 1, 0, 2}, /*  9 */
9363     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 2, 1}, /* 10 */
9364     {4, 4, 1, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 2, 3, 1}, /* 11 */
9365     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 2, 0, 1}, /* 12 */
9366     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 1, 2, 3}, /* 13 */
9367 /*
9368     This draws one instance on some machines, no instance on others
9369     {0, 4, 1, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0, 1, 2},
9370 */
9371 /*
9372     This case is handled in a stand alone test, SetStreamSourceFreq(0,(D3DSTREAMSOURCE_INSTANCEDATA | 1))  has to return D3DERR_INVALIDCALL!
9373     {4, 4, 1, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 2, 1, 0, D3DERR_INVALIDCALL},
9374 */
9375 };
9376
9377 /* Drawing Indexed Geometry with instances*/
9378 static void stream_test(IDirect3DDevice9 *device)
9379 {
9380     IDirect3DVertexBuffer9 *vb = NULL;
9381     IDirect3DVertexBuffer9 *vb2 = NULL;
9382     IDirect3DVertexBuffer9 *vb3 = NULL;
9383     IDirect3DIndexBuffer9 *ib = NULL;
9384     IDirect3DVertexDeclaration9 *pDecl = NULL;
9385     IDirect3DVertexShader9 *shader = NULL;
9386     HRESULT hr;
9387     BYTE *data;
9388     DWORD color;
9389     DWORD ind;
9390     unsigned i;
9391
9392     const DWORD shader_code[] =
9393     {
9394         0xfffe0101,                                     /* vs_1_1 */
9395         0x0000001f, 0x80000000, 0x900f0000,             /* dcl_position v0 */
9396         0x0000001f, 0x8000000a, 0x900f0001,             /* dcl_color0 v1 */
9397         0x0000001f, 0x80000005, 0x900f0002,             /* dcl_texcoord v2 */
9398         0x00000001, 0x800f0000, 0x90e40000,             /* mov r0, v0 */
9399         0x00000002, 0xc00f0000, 0x80e40000, 0x90e40002, /* add oPos, r0, v2 */
9400         0x00000001, 0xd00f0000, 0x90e40001,             /* mov oD0, v1 */
9401         0x0000ffff
9402     };
9403
9404     const float quad[][3] =
9405     {
9406         {-0.5f, -0.5f,  1.1f}, /*0 */
9407         {-0.5f,  0.5f,  1.1f}, /*1 */
9408         { 0.5f, -0.5f,  1.1f}, /*2 */
9409         { 0.5f,  0.5f,  1.1f}, /*3 */
9410     };
9411
9412     const float vertcolor[][4] =
9413     {
9414         {1.0f, 0.0f, 0.0f, 1.0f}, /*0 */
9415         {1.0f, 0.0f, 0.0f, 1.0f}, /*1 */
9416         {1.0f, 0.0f, 0.0f, 1.0f}, /*2 */
9417         {1.0f, 0.0f, 0.0f, 1.0f}, /*3 */
9418     };
9419
9420     /* 4 position for 4 instances */
9421     const float instancepos[][3] =
9422     {
9423         {-0.6f,-0.6f, 0.0f},
9424         { 0.6f,-0.6f, 0.0f},
9425         { 0.6f, 0.6f, 0.0f},
9426         {-0.6f, 0.6f, 0.0f},
9427     };
9428
9429     short indices[] = {0, 1, 2, 1, 2, 3};
9430
9431     D3DVERTEXELEMENT9 decl[] =
9432     {
9433         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9434         {1, 0,  D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
9435         {2, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
9436         D3DDECL_END()
9437     };
9438
9439     /* set the default value because it isn't done in wine? */
9440     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 1);
9441     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9442
9443     /* check for D3DSTREAMSOURCE_INDEXEDDATA at stream0 */
9444     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 0, (D3DSTREAMSOURCE_INSTANCEDATA | 1));
9445     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9446
9447     /* check wrong cases */
9448     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 0);
9449     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9450     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9451     ok(hr == D3D_OK && ind == 1, "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9452     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 2);
9453     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9454     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9455     ok(hr == D3D_OK && ind == 2, "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9456     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, (D3DSTREAMSOURCE_INDEXEDDATA | 0));
9457     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9458     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9459     ok(hr == D3D_OK && ind == (D3DSTREAMSOURCE_INDEXEDDATA | 0), "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9460     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, (D3DSTREAMSOURCE_INSTANCEDATA | 0));
9461     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9462     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9463     ok(hr == D3D_OK && ind == (0U | D3DSTREAMSOURCE_INSTANCEDATA), "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9464     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA | 0));
9465     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9466     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9467     ok(hr == D3D_OK && ind == (0U | D3DSTREAMSOURCE_INSTANCEDATA), "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9468
9469     /* set the default value back */
9470     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 1);
9471     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9472
9473     /* create all VertexBuffers*/
9474     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0, D3DPOOL_MANAGED, &vb, NULL);
9475     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
9476     if(!vb) {
9477         skip("Failed to create a vertex buffer\n");
9478         return;
9479     }
9480     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(vertcolor), 0, 0, D3DPOOL_MANAGED, &vb2, NULL);
9481     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
9482     if(!vb2) {
9483         skip("Failed to create a vertex buffer\n");
9484         goto out;
9485     }
9486     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(instancepos), 0, 0, D3DPOOL_MANAGED, &vb3, NULL);
9487     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
9488     if(!vb3) {
9489         skip("Failed to create a vertex buffer\n");
9490         goto out;
9491     }
9492
9493     /* create IndexBuffer*/
9494     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, NULL);
9495     ok(hr == D3D_OK, "IDirect3DDevice9_CreateIndexBuffer failed with %08x\n", hr);
9496     if(!ib) {
9497         skip("Failed to create a index buffer\n");
9498         goto out;
9499     }
9500
9501     /* copy all Buffers (Vertex + Index)*/
9502     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), (void **) &data, 0);
9503     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
9504     memcpy(data, quad, sizeof(quad));
9505     hr = IDirect3DVertexBuffer9_Unlock(vb);
9506     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
9507     hr = IDirect3DVertexBuffer9_Lock(vb2, 0, sizeof(vertcolor), (void **) &data, 0);
9508     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
9509     memcpy(data, vertcolor, sizeof(vertcolor));
9510     hr = IDirect3DVertexBuffer9_Unlock(vb2);
9511     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
9512     hr = IDirect3DVertexBuffer9_Lock(vb3, 0, sizeof(instancepos), (void **) &data, 0);
9513     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
9514     memcpy(data, instancepos, sizeof(instancepos));
9515     hr = IDirect3DVertexBuffer9_Unlock(vb3);
9516     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
9517     hr = IDirect3DIndexBuffer9_Lock(ib, 0, sizeof(indices), (void **) &data, 0);
9518     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Lock failed with %08x\n", hr);
9519     memcpy(data, indices, sizeof(indices));
9520     hr = IDirect3DIndexBuffer9_Unlock(ib);
9521     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
9522
9523     /* create VertexShader */
9524     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
9525     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexShader failed hr=%08x\n", hr);
9526     if(!shader) {
9527         skip("Failed to create a vetex shader\n");
9528         goto out;
9529     }
9530
9531     hr = IDirect3DDevice9_SetVertexShader(device, shader);
9532     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
9533
9534     hr = IDirect3DDevice9_SetIndices(device, ib);
9535     ok(hr == D3D_OK, "IDirect3DDevice9_SetIndices failed with %08x\n", hr);
9536
9537     /* run all tests */
9538     for( i = 0; i < sizeof(testcases)/sizeof(testcases[0]); ++i)
9539     {
9540         struct testdata act = testcases[i];
9541         decl[0].Stream = act.strVertex;
9542         decl[1].Stream = act.strColor;
9543         decl[2].Stream = act.strInstance;
9544         /* create VertexDeclarations */
9545         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl, &pDecl);
9546         ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed hr=%08x (case %i)\n", hr, i);
9547
9548         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
9549         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x (case %i)\n", hr, i);
9550
9551         hr = IDirect3DDevice9_BeginScene(device);
9552         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x (case %i)\n", hr, i);
9553         if(SUCCEEDED(hr))
9554         {
9555             hr = IDirect3DDevice9_SetVertexDeclaration(device, pDecl);
9556             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x (case %i)\n", hr, i);
9557
9558             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strVertex, (D3DSTREAMSOURCE_INDEXEDDATA | act.idxVertex));
9559             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9560             hr = IDirect3DDevice9_SetStreamSource(device, act.strVertex, vb, 0, sizeof(quad[0]));
9561             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9562
9563             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strColor, (D3DSTREAMSOURCE_INDEXEDDATA | act.idxColor));
9564             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9565             hr = IDirect3DDevice9_SetStreamSource(device, act.strColor, vb2, 0, sizeof(vertcolor[0]));
9566             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9567
9568             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strInstance, (D3DSTREAMSOURCE_INSTANCEDATA | act.idxInstance));
9569             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9570             hr = IDirect3DDevice9_SetStreamSource(device, act.strInstance, vb3, 0, sizeof(instancepos[0]));
9571             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9572
9573             hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2);
9574             ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitive failed with %08x (case %i)\n", hr, i);
9575             hr = IDirect3DDevice9_EndScene(device);
9576             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x (case %i)\n", hr, i);
9577
9578             /* set all StreamSource && StreamSourceFreq back to default */
9579             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strVertex, 1);
9580             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9581             hr = IDirect3DDevice9_SetStreamSource(device, act.strVertex, NULL, 0, 0);
9582             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9583             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.idxColor, 1);
9584             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9585             hr = IDirect3DDevice9_SetStreamSource(device, act.idxColor, NULL, 0, 0);
9586             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9587             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.idxInstance, 1);
9588             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9589             hr = IDirect3DDevice9_SetStreamSource(device, act.idxInstance, NULL, 0, 0);
9590             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9591         }
9592
9593         hr = IDirect3DVertexDeclaration9_Release(pDecl);
9594         ok(hr == D3D_OK, "IDirect3DVertexDeclaration9_Release failed with %08x (case %i)\n", hr, i);
9595
9596         color = getPixelColor(device, 160, 360);
9597         ok(color == act.color1, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color1, i);
9598         color = getPixelColor(device, 480, 360);
9599         ok(color == act.color2, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color2, i);
9600         color = getPixelColor(device, 480, 120);
9601         ok(color == act.color3, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color3, i);
9602         color = getPixelColor(device, 160, 120);
9603         ok(color == act.color4, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color4, i);
9604
9605         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9606         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x (case %i)\n", hr, i);
9607     }
9608
9609     hr = IDirect3DDevice9_SetIndices(device, NULL);
9610     ok(hr == D3D_OK, "IDirect3DDevice9_SetIndices failed with %08x\n", hr);
9611
9612 out:
9613     if(vb) IDirect3DVertexBuffer9_Release(vb);
9614     if(vb2)IDirect3DVertexBuffer9_Release(vb2);
9615     if(vb3)IDirect3DVertexBuffer9_Release(vb3);
9616     if(ib)IDirect3DIndexBuffer9_Release(ib);
9617     if(shader)IDirect3DVertexShader9_Release(shader);
9618 }
9619
9620 static void np2_stretch_rect_test(IDirect3DDevice9 *device) {
9621     IDirect3DSurface9 *src = NULL, *dst = NULL, *backbuffer = NULL;
9622     IDirect3DTexture9 *dsttex = NULL;
9623     HRESULT hr;
9624     DWORD color;
9625     D3DRECT r1 = {0,  0,  50,  50 };
9626     D3DRECT r2 = {50, 0,  100, 50 };
9627     D3DRECT r3 = {50, 50, 100, 100};
9628     D3DRECT r4 = {0,  50,  50, 100};
9629     const float quad[] = {
9630         -1.0,   -1.0,   0.1,    0.0,    0.0,
9631          1.0,   -1.0,   0.1,    1.0,    0.0,
9632         -1.0,    1.0,   0.1,    0.0,    1.0,
9633          1.0,    1.0,   0.1,    1.0,    1.0,
9634     };
9635
9636     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
9637     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
9638
9639     hr = IDirect3DDevice9_CreateRenderTarget(device, 100, 100, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &src, NULL );
9640     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
9641     hr = IDirect3DDevice9_CreateTexture(device, 25, 25, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &dsttex, NULL);
9642     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
9643
9644     if(!src || !dsttex) {
9645         skip("One or more test resources could not be created\n");
9646         goto cleanup;
9647     }
9648
9649     hr = IDirect3DTexture9_GetSurfaceLevel(dsttex, 0, &dst);
9650     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
9651
9652     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
9653     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9654
9655     /* Clear the StretchRect destination for debugging */
9656     hr = IDirect3DDevice9_SetRenderTarget(device, 0, dst);
9657     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
9658     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
9659     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9660
9661     hr = IDirect3DDevice9_SetRenderTarget(device, 0, src);
9662     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
9663
9664     hr = IDirect3DDevice9_Clear(device, 1, &r1, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
9665     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9666     hr = IDirect3DDevice9_Clear(device, 1, &r2, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
9667     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9668     hr = IDirect3DDevice9_Clear(device, 1, &r3, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
9669     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9670     hr = IDirect3DDevice9_Clear(device, 1, &r4, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
9671     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9672
9673     /* Stretchrect before setting the render target back to the backbuffer. This will make Wine use
9674      * the target -> texture GL blit path
9675      */
9676     hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst, NULL, D3DTEXF_POINT);
9677     ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
9678     IDirect3DSurface9_Release(dst);
9679
9680     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
9681     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
9682
9683     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) dsttex);
9684     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9685     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
9686     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
9687     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9688     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with %08x\n", hr);
9689     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9690     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with %08x\n", hr);
9691
9692     hr = IDirect3DDevice9_BeginScene(device);
9693     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
9694     if(SUCCEEDED(hr)) {
9695         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
9696         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
9697         hr = IDirect3DDevice9_EndScene(device);
9698         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
9699     }
9700
9701     color = getPixelColor(device, 160, 360);
9702     ok(color == 0x00ff0000, "stretchrect: Pixel 160,360 has color 0x%08x, expected 0x00ff0000\n", color);
9703     color = getPixelColor(device, 480, 360);
9704     ok(color == 0x0000ff00, "stretchrect: Pixel 480,360 has color 0x%08x, expected 0x0000ff00\n", color);
9705     color = getPixelColor(device, 480, 120);
9706     ok(color == 0x000000ff, "stretchrect: Pixel 480,120 has color 0x%08x, expected 0x000000ff\n", color);
9707     color = getPixelColor(device, 160, 120);
9708     ok(color == 0x00000000, "stretchrect: Pixel 160,120 has color 0x%08x, expected 0x00000000\n", color);
9709     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9710     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
9711
9712     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
9713     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9714     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
9715     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9716
9717 cleanup:
9718     if(src) IDirect3DSurface9_Release(src);
9719     if(backbuffer) IDirect3DSurface9_Release(backbuffer);
9720     if(dsttex) IDirect3DTexture9_Release(dsttex);
9721 }
9722
9723 static void texop_test(IDirect3DDevice9 *device)
9724 {
9725     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
9726     IDirect3DTexture9 *texture = NULL;
9727     D3DLOCKED_RECT locked_rect;
9728     D3DCOLOR color;
9729     D3DCAPS9 caps;
9730     HRESULT hr;
9731     unsigned i;
9732
9733     static const struct {
9734         float x, y, z;
9735         float s, t;
9736         D3DCOLOR diffuse;
9737     } quad[] = {
9738         {-1.0f, -1.0f, 0.1f, -1.0f, -1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)},
9739         {-1.0f,  1.0f, 0.1f, -1.0f,  1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)},
9740         { 1.0f, -1.0f, 0.1f,  1.0f, -1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)},
9741         { 1.0f,  1.0f, 0.1f,  1.0f,  1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)}
9742     };
9743
9744     static const D3DVERTEXELEMENT9 decl_elements[] = {
9745         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9746         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
9747         {0, 20, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
9748         D3DDECL_END()
9749     };
9750
9751     static const struct {
9752         D3DTEXTUREOP op;
9753         const char *name;
9754         DWORD caps_flag;
9755         D3DCOLOR result;
9756     } test_data[] = {
9757         {D3DTOP_SELECTARG1,                "SELECTARG1",                D3DTEXOPCAPS_SELECTARG1,                D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
9758         {D3DTOP_SELECTARG2,                "SELECTARG2",                D3DTEXOPCAPS_SELECTARG2,                D3DCOLOR_ARGB(0x00, 0x33, 0x33, 0x33)},
9759         {D3DTOP_MODULATE,                  "MODULATE",                  D3DTEXOPCAPS_MODULATE,                  D3DCOLOR_ARGB(0x00, 0x00, 0x33, 0x00)},
9760         {D3DTOP_MODULATE2X,                "MODULATE2X",                D3DTEXOPCAPS_MODULATE2X,                D3DCOLOR_ARGB(0x00, 0x00, 0x66, 0x00)},
9761         {D3DTOP_MODULATE4X,                "MODULATE4X",                D3DTEXOPCAPS_MODULATE4X,                D3DCOLOR_ARGB(0x00, 0x00, 0xcc, 0x00)},
9762         {D3DTOP_ADD,                       "ADD",                       D3DTEXOPCAPS_ADD,                       D3DCOLOR_ARGB(0x00, 0x33, 0xff, 0x33)},
9763         {D3DTOP_ADDSIGNED,                 "ADDSIGNED",                 D3DTEXOPCAPS_ADDSIGNED,                 D3DCOLOR_ARGB(0x00, 0x00, 0xb2, 0x00)},
9764         {D3DTOP_ADDSIGNED2X,               "ADDSIGNED2X",               D3DTEXOPCAPS_ADDSIGNED2X,               D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
9765         {D3DTOP_SUBTRACT,                  "SUBTRACT",                  D3DTEXOPCAPS_SUBTRACT,                  D3DCOLOR_ARGB(0x00, 0x00, 0xcc, 0x00)},
9766         {D3DTOP_ADDSMOOTH,                 "ADDSMOOTH",                 D3DTEXOPCAPS_ADDSMOOTH,                 D3DCOLOR_ARGB(0x00, 0x33, 0xff, 0x33)},
9767         {D3DTOP_BLENDDIFFUSEALPHA,         "BLENDDIFFUSEALPHA",         D3DTEXOPCAPS_BLENDDIFFUSEALPHA,         D3DCOLOR_ARGB(0x00, 0x22, 0x77, 0x22)},
9768         {D3DTOP_BLENDTEXTUREALPHA,         "BLENDTEXTUREALPHA",         D3DTEXOPCAPS_BLENDTEXTUREALPHA,         D3DCOLOR_ARGB(0x00, 0x14, 0xad, 0x14)},
9769         {D3DTOP_BLENDFACTORALPHA,          "BLENDFACTORALPHA",          D3DTEXOPCAPS_BLENDFACTORALPHA,          D3DCOLOR_ARGB(0x00, 0x07, 0xe4, 0x07)},
9770         {D3DTOP_BLENDTEXTUREALPHAPM,       "BLENDTEXTUREALPHAPM",       D3DTEXOPCAPS_BLENDTEXTUREALPHAPM,       D3DCOLOR_ARGB(0x00, 0x14, 0xff, 0x14)},
9771         {D3DTOP_BLENDCURRENTALPHA,         "BLENDCURRENTALPHA",         D3DTEXOPCAPS_BLENDCURRENTALPHA,         D3DCOLOR_ARGB(0x00, 0x22, 0x77, 0x22)},
9772         {D3DTOP_MODULATEALPHA_ADDCOLOR,    "MODULATEALPHA_ADDCOLOR",    D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR,    D3DCOLOR_ARGB(0x00, 0x1f, 0xff, 0x1f)},
9773         {D3DTOP_MODULATECOLOR_ADDALPHA,    "MODULATECOLOR_ADDALPHA",    D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA,    D3DCOLOR_ARGB(0x00, 0x99, 0xcc, 0x99)},
9774         {D3DTOP_MODULATEINVALPHA_ADDCOLOR, "MODULATEINVALPHA_ADDCOLOR", D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR, D3DCOLOR_ARGB(0x00, 0x14, 0xff, 0x14)},
9775         {D3DTOP_MODULATEINVCOLOR_ADDALPHA, "MODULATEINVCOLOR_ADDALPHA", D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA, D3DCOLOR_ARGB(0x00, 0xcc, 0x99, 0xcc)},
9776         /* BUMPENVMAP & BUMPENVMAPLUMINANCE have their own tests */
9777         {D3DTOP_DOTPRODUCT3,               "DOTPRODUCT3",               D3DTEXOPCAPS_DOTPRODUCT3,               D3DCOLOR_ARGB(0x00, 0x99, 0x99, 0x99)},
9778         {D3DTOP_MULTIPLYADD,               "MULTIPLYADD",               D3DTEXOPCAPS_MULTIPLYADD,               D3DCOLOR_ARGB(0x00, 0xff, 0x33, 0x00)},
9779         {D3DTOP_LERP,                      "LERP",                      D3DTEXOPCAPS_LERP,                      D3DCOLOR_ARGB(0x00, 0x00, 0x33, 0x33)},
9780     };
9781
9782     memset(&caps, 0, sizeof(caps));
9783     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9784     ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x\n", hr);
9785
9786     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
9787     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed with 0x%08x\n", hr);
9788     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
9789     ok(SUCCEEDED(hr), "SetVertexDeclaration failed with 0x%08x\n", hr);
9790
9791     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
9792     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed with 0x%08x\n", hr);
9793     hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
9794     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
9795     *((DWORD *)locked_rect.pBits) = D3DCOLOR_ARGB(0x99, 0x00, 0xff, 0x00);
9796     hr = IDirect3DTexture9_UnlockRect(texture, 0);
9797     ok(SUCCEEDED(hr), "UnlockRect failed with 0x%08x\n", hr);
9798     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
9799     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
9800
9801     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG0, D3DTA_DIFFUSE);
9802     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9803     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9804     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9805     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9806     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9807
9808     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
9809     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9810
9811     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
9812     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9813     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0xdd333333);
9814     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9815     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA);
9816     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9817
9818     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
9819     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9820
9821     for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
9822     {
9823         if (!(caps.TextureOpCaps & test_data[i].caps_flag))
9824         {
9825             skip("tex operation %s not supported\n", test_data[i].name);
9826             continue;
9827         }
9828
9829         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, test_data[i].op);
9830         ok(SUCCEEDED(hr), "SetTextureStageState (%s) failed with 0x%08x\n", test_data[i].name, hr);
9831
9832         hr = IDirect3DDevice9_BeginScene(device);
9833         ok(SUCCEEDED(hr), "BeginScene failed with 0x%08x\n", hr);
9834
9835         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
9836         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9837
9838         hr = IDirect3DDevice9_EndScene(device);
9839         ok(SUCCEEDED(hr), "EndScene failed with 0x%08x\n", hr);
9840
9841         color = getPixelColor(device, 320, 240);
9842         ok(color_match(color, test_data[i].result, 3), "Operation %s returned color 0x%08x, expected 0x%08x\n",
9843                 test_data[i].name, color, test_data[i].result);
9844
9845         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9846         ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
9847     }
9848
9849     if (texture) IDirect3DTexture9_Release(texture);
9850     if (vertex_declaration) IDirect3DVertexDeclaration9_Release(vertex_declaration);
9851 }
9852
9853 static void yuv_color_test(IDirect3DDevice9 *device) {
9854     HRESULT hr;
9855     IDirect3DSurface9 *surface = NULL, *target = NULL;
9856     unsigned int fmt, i;
9857     D3DFORMAT format;
9858     const char *fmt_string;
9859     D3DLOCKED_RECT lr;
9860     IDirect3D9 *d3d;
9861     HRESULT color;
9862     DWORD ref_color_left, ref_color_right;
9863
9864     struct {
9865         DWORD in;           /* The input color */
9866         DWORD uyvy_left;    /* "in" interpreted as uyvy and transformed to RGB, pixel 1/1*/
9867         DWORD uyvy_right;   /* "in" interpreted as uyvy and transformed to RGB, pixel 2/1*/
9868         DWORD yuy2_left;    /* "in" interpreted as yuy2 and transformed to RGB, pixel 1/1 */
9869         DWORD yuy2_right;   /* "in" interpreted as yuy2 and transformed to RGB, pixel 2/1 */
9870     } test_data[] = {
9871     /* Originally I wanted to avoid being evil, and set Y1 = Y2 to avoid triggering troubles in shader converters,
9872      * but the main difference between YUY2 and UYVY is the swapped ordering of the chroma and luminance
9873      * values. However, handling the two Y's properly could have a big impact on image quality, so be picky about
9874      * that
9875      */
9876       { 0x00000000, 0x00008700, 0x00008700, 0x00008700, 0x00008700 },
9877       { 0xff000000, 0x00008700, 0x004bff1c, 0x00b30000, 0x00b30000 },
9878       { 0x00ff0000, 0x00b30000, 0x00b30000, 0x00008700, 0x004bff1c },
9879       { 0x0000ff00, 0x004bff1c, 0x00008700, 0x000030e1, 0x000030e1 },
9880       { 0x000000ff, 0x000030e1, 0x000030e1, 0x004bff1c, 0x00008700 },
9881       { 0xffff0000, 0x00b30000, 0x00ffd01c, 0x00b30000, 0x00ffd01c },
9882       { 0xff00ff00, 0x004bff1c, 0x004bff1c, 0x00b300e1, 0x00b300e1 },
9883       { 0xff0000ff, 0x000030e1, 0x004bffff, 0x00ffd01c, 0x00b30000 },
9884       { 0x00ffff00, 0x00ffd01c, 0x00b30000, 0x000030e1, 0x004bffff },
9885       { 0x00ff00ff, 0x00b300e1, 0x00b300e1, 0x004bff1c, 0x004bff1c },
9886       { 0x0000ffff, 0x004bffff, 0x000030e1, 0x004bffff, 0x000030e1 },
9887       { 0xffffff00, 0x00ffd01c, 0x00ffd01c, 0x00b300e1, 0x00ff79ff },
9888       { 0xffff00ff, 0x00b300e1, 0x00ff79ff, 0x00ffd01c, 0x00ffd01c },
9889       { 0xffffffff, 0x00ff79ff, 0x00ff79ff, 0x00ff79ff, 0x00ff79ff },
9890
9891       { 0x4cff4c54, 0x00ff0000, 0x00ff0000, 0x000b8b00, 0x00b6ffa3 },
9892       { 0x00800080, 0x00000000, 0x00000000, 0x0000ff00, 0x0000ff00 },
9893       { 0xFF80FF80, 0x00ffffff, 0x00ffffff, 0x00ff00ff, 0x00ff00ff },
9894       { 0x1c6b1cff, 0x000000fd, 0x000000fd, 0x006dff45, 0x0000d500 },
9895     };
9896
9897     hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
9898     ok(hr == D3D_OK, "IDirect3DDevice9_GetDirect3D failed, hr = %08x\n", hr);
9899     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &target);
9900     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderTarget failed, hr = %08x\n", hr);
9901
9902     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX0);
9903     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %08x\n", hr);
9904
9905     for(fmt = 0; fmt < 2; fmt++) {
9906         if(fmt == 0) {
9907             format = D3DFMT_UYVY;
9908             fmt_string = "D3DFMT_UYVY";
9909         } else {
9910             format = D3DFMT_YUY2;
9911             fmt_string = "D3DFMT_YUY2";
9912         }
9913
9914         /* Some(all?) Windows drivers do not support YUV 3D textures, only 2D surfaces in StretchRect. Thus use
9915                        * StretchRect to draw the YUV surface onto the screen instead of drawPrimitive
9916                        */
9917         if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
9918                                         D3DRTYPE_SURFACE, format) != D3D_OK) {
9919             skip("%s is not supported\n", fmt_string);
9920             continue;
9921         }
9922
9923         /* A pixel is effectively 16 bit large, but two pixels are stored together, so the minimum size is 2x1 */
9924         hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2, 1, format, D3DPOOL_DEFAULT, &surface, NULL);
9925         ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed, hr = %08x\n", hr);
9926
9927         for(i = 0; i < (sizeof(test_data)/sizeof(test_data[0])); i++) {
9928             if(fmt == 0) {
9929                 ref_color_left = test_data[i].uyvy_left;
9930                 ref_color_right = test_data[i].uyvy_right;
9931             } else {
9932                 ref_color_left = test_data[i].yuy2_left;
9933                 ref_color_right = test_data[i].yuy2_right;
9934             }
9935
9936             memset(&lr, 0, sizeof(lr));
9937             hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
9938             ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr = %08x\n", hr);
9939             *((DWORD *) lr.pBits) = test_data[i].in;
9940             hr = IDirect3DSurface9_UnlockRect(surface);
9941             ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr = %08x\n", hr);
9942
9943             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
9944             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9945             hr = IDirect3DDevice9_StretchRect(device, surface, NULL, target, NULL, D3DTEXF_POINT);
9946             ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with 0x%08x\n", hr);
9947
9948             /* Native D3D can't resist filtering the YUY surface, even though we asked it not to do so above. To
9949              * prevent running into precision problems, read a far left and far right pixel. In the future we may
9950              * want to add tests for the filtered pixels as well.
9951              *
9952              * Unfortunately different implementations(Windows-NV and Mac-ATI tested) interpret some colors vastly
9953              * differently, so we need a max diff of 16
9954              */
9955             color = getPixelColor(device, 40, 240);
9956
9957             /* Newer versions of the Nvidia Windows driver mix up the U and V channels, breaking all the tests
9958              * where U != V. Skip the entire test if this bug in this case
9959              */
9960             if (broken(test_data[i].in == 0xff000000 && color == 0x00008800 && format == D3DFMT_UYVY))
9961             {
9962                 skip("Nvidia channel confusion bug detected, skipping YUV tests\n");
9963                 IDirect3DSurface9_Release(surface);
9964                 goto out;
9965             }
9966
9967             ok(color_match(color, ref_color_left, 18),
9968                "Input 0x%08x: Got color 0x%08x for pixel 1/1, expected 0x%08x, format %s\n",
9969                test_data[i].in, color, ref_color_left, fmt_string);
9970             color = getPixelColor(device, 600, 240);
9971             ok(color_match(color, ref_color_right, 18),
9972                "Input 0x%08x: Got color 0x%08x for pixel 2/1, expected 0x%08x, format %s\n",
9973                test_data[i].in, color, ref_color_right, fmt_string);
9974             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9975             ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
9976         }
9977         IDirect3DSurface9_Release(surface);
9978     }
9979
9980 out:
9981     IDirect3DSurface9_Release(target);
9982     IDirect3D9_Release(d3d);
9983 }
9984
9985 static void texop_range_test(IDirect3DDevice9 *device)
9986 {
9987     static const struct {
9988         float x, y, z;
9989         D3DCOLOR diffuse;
9990     } quad[] = {
9991         {-1.0f, -1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)},
9992         {-1.0f,  1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)},
9993         { 1.0f, -1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)},
9994         { 1.0f,  1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)}
9995     };
9996     HRESULT hr;
9997     IDirect3DTexture9 *texture;
9998     D3DLOCKED_RECT locked_rect;
9999     D3DCAPS9 caps;
10000     DWORD color;
10001
10002     /* We need ADD and SUBTRACT operations */
10003     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10004     ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x\n", hr);
10005     if (!(caps.TextureOpCaps & D3DTEXOPCAPS_ADD)) {
10006         skip("D3DTOP_ADD is not supported, skipping value range test\n");
10007         return;
10008     }
10009     if (!(caps.TextureOpCaps & D3DTEXOPCAPS_SUBTRACT)) {
10010         skip("D3DTEXOPCAPS_SUBTRACT is not supported, skipping value range test\n");
10011         return;
10012     }
10013
10014     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
10015     ok(SUCCEEDED(hr), "SetFVF failed with 0x%08x\n", hr);
10016     /* Stage 1: result = diffuse(=1.0) + diffuse
10017      * stage 2: result = result - tfactor(= 0.5)
10018      */
10019     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0x80808080);
10020     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
10021     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
10022     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10023     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
10024     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10025     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
10026     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10027     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_CURRENT);
10028     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10029     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10030     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10031     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SUBTRACT);
10032     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10033
10034     hr = IDirect3DDevice9_BeginScene(device);
10035     ok(SUCCEEDED(hr), "BeginScene failed with 0x%08x\n", hr);
10036     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
10037     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10038     hr = IDirect3DDevice9_EndScene(device);
10039     ok(SUCCEEDED(hr), "EndScene failed with 0x%08x\n", hr);
10040
10041     color = getPixelColor(device, 320, 240);
10042     ok(color_match(color, 0x00808080, 1), "texop Range > 1.0 returned 0x%08x, expected 0x00808080\n",
10043        color);
10044     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10045     ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
10046
10047     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
10048     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed with 0x%08x\n", hr);
10049     hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
10050     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
10051     *((DWORD *)locked_rect.pBits) = D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00);
10052     hr = IDirect3DTexture9_UnlockRect(texture, 0);
10053     ok(SUCCEEDED(hr), "UnlockRect failed with 0x%08x\n", hr);
10054     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
10055     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
10056
10057     /* Stage 1: result = texture(=0.0) - tfactor(= 0.5)
10058      * stage 2: result = result + diffuse(1.0)
10059      */
10060     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0x80808080);
10061     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
10062     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10063     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10064     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10065     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10066     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SUBTRACT);
10067     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10068     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_CURRENT);
10069     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10070     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
10071     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10072     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
10073     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10074
10075     hr = IDirect3DDevice9_BeginScene(device);
10076     ok(SUCCEEDED(hr), "BeginScene failed with 0x%08x\n", hr);
10077     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
10078     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10079     hr = IDirect3DDevice9_EndScene(device);
10080     ok(SUCCEEDED(hr), "EndScene failed with 0x%08x\n", hr);
10081
10082     color = getPixelColor(device, 320, 240);
10083     ok(color_match(color, 0x00ffffff, 1), "texop Range < 0.0 returned 0x%08x, expected 0x00ffffff\n",
10084        color);
10085     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10086     ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
10087
10088     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
10089     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10090     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
10091     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10092     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
10093     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
10094     IDirect3DTexture9_Release(texture);
10095 }
10096
10097 static void alphareplicate_test(IDirect3DDevice9 *device) {
10098     struct vertex quad[] = {
10099         { -1.0,    -1.0,    0.1,    0x80ff00ff },
10100         {  1.0,    -1.0,    0.1,    0x80ff00ff },
10101         { -1.0,     1.0,    0.1,    0x80ff00ff },
10102         {  1.0,     1.0,    0.1,    0x80ff00ff },
10103     };
10104     HRESULT hr;
10105     DWORD color;
10106
10107     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
10108     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10109
10110     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
10111     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
10112
10113     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
10114     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10115     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE | D3DTA_ALPHAREPLICATE);
10116     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10117
10118     hr = IDirect3DDevice9_BeginScene(device);
10119     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
10120     if(SUCCEEDED(hr)) {
10121         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
10122         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10123         hr = IDirect3DDevice9_EndScene(device);
10124         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with 0x%08x\n", hr);
10125     }
10126
10127     color = getPixelColor(device, 320, 240);
10128     ok(color_match(color, 0x00808080, 1), "alphareplicate test 0x%08x, expected 0x00808080\n",
10129        color);
10130     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10131     ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
10132
10133     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
10134     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10135
10136 }
10137
10138 static void dp3_alpha_test(IDirect3DDevice9 *device) {
10139     HRESULT hr;
10140     D3DCAPS9 caps;
10141     DWORD color;
10142     struct vertex quad[] = {
10143         { -1.0,    -1.0,    0.1,    0x408080c0 },
10144         {  1.0,    -1.0,    0.1,    0x408080c0 },
10145         { -1.0,     1.0,    0.1,    0x408080c0 },
10146         {  1.0,     1.0,    0.1,    0x408080c0 },
10147     };
10148
10149     memset(&caps, 0, sizeof(caps));
10150     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10151     ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x\n", hr);
10152     if (!(caps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3)) {
10153         skip("D3DTOP_DOTPRODUCT3 not supported\n");
10154         return;
10155     }
10156
10157     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
10158     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10159
10160     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
10161     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
10162
10163     /* dp3_x4 r0, diffuse_bias, tfactor_bias
10164      * mov r0.a, diffuse.a
10165      * mov r0, r0.a
10166      *
10167      * It turns out that the 2nd line is ignored, and the dp3 result written into r0.a instead
10168      * thus with input vec4(0.5, 0.5, 0.75, 0.25) and vec4(1.0, 1.0, 1.0, 1.0) the result is
10169      * (0.0 * 0.5 + 0.0 * 0.5 + 0.25 * 0.5) * 4 = 0.125 * 4 = 0.5, with a bunch of inprecision.
10170      */
10171     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);
10172     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10173     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
10174     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10175     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10176     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10177     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
10178     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10179     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
10180     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10181     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
10182     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10183     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_CURRENT | D3DTA_ALPHAREPLICATE);
10184     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10185     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
10186     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10187     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0xffffffff);
10188     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10189
10190     hr = IDirect3DDevice9_BeginScene(device);
10191     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
10192     if(SUCCEEDED(hr)) {
10193         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
10194         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10195         hr = IDirect3DDevice9_EndScene(device);
10196         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with 0x%08x\n", hr);
10197     }
10198
10199     color = getPixelColor(device, 320, 240);
10200     ok(color_match(color, 0x00808080, 4), "dp3 alpha test 0x%08x, expected 0x00808080\n",
10201        color);
10202     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10203     ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
10204
10205     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
10206     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10207     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
10208     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10209     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
10210     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10211 }
10212
10213 static void zwriteenable_test(IDirect3DDevice9 *device) {
10214     HRESULT hr;
10215     DWORD color;
10216     struct vertex quad1[] = {
10217         { -1.0,  -1.0,  0.1,    0x00ff0000},
10218         { -1.0,   1.0,  0.1,    0x00ff0000},
10219         {  1.0,  -1.0,  0.1,    0x00ff0000},
10220         {  1.0,   1.0,  0.1,    0x00ff0000},
10221     };
10222     struct vertex quad2[] = {
10223         { -1.0,  -1.0,  0.9,    0x0000ff00},
10224         { -1.0,   1.0,  0.9,    0x0000ff00},
10225         {  1.0,  -1.0,  0.9,    0x0000ff00},
10226         {  1.0,   1.0,  0.9,    0x0000ff00},
10227     };
10228
10229     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
10230     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10231
10232     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
10233     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
10234     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
10235     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10236     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
10237     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10238     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
10239     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10240
10241     hr = IDirect3DDevice9_BeginScene(device);
10242     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
10243     if(SUCCEEDED(hr)) {
10244         /* The Z buffer is filled with 1.0. Draw a red quad with z = 0.1, zenable = D3DZB_FALSE, zwriteenable = TRUE.
10245          * The red color is written because the z test is disabled. The question is whether the z = 0.1 values
10246          * are written into the Z buffer. After the draw, set zenable = TRUE and draw a green quad at z = 0.9.
10247          * If the values are written, the z test will fail(0.9 > 0.1) and the red color remains. If the values
10248          * are not written, the z test succeeds(0.9 < 1.0) and the green color is written. It turns out that
10249          * the screen is green, so zenable = D3DZB_FALSE and zwriteenable  = TRUE does NOT write to the z buffer.
10250          */
10251         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
10252         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10253         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
10254         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10255         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
10256         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10257
10258         hr = IDirect3DDevice9_EndScene(device);
10259         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
10260     }
10261
10262     color = getPixelColor(device, 320, 240);
10263     ok(color_match(color, 0x0000ff00, 1), "zwriteenable test returned 0x%08x, expected 0x0000ff00\n",
10264        color);
10265     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10266     ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
10267
10268     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
10269     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10270 }
10271
10272 static void alphatest_test(IDirect3DDevice9 *device) {
10273 #define ALPHATEST_PASSED 0x0000ff00
10274 #define ALPHATEST_FAILED 0x00ff0000
10275     struct {
10276         D3DCMPFUNC  func;
10277         DWORD       color_less;
10278         DWORD       color_equal;
10279         DWORD       color_greater;
10280     } testdata[] = {
10281         {   D3DCMP_NEVER,           ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED },
10282         {   D3DCMP_LESS,            ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED },
10283         {   D3DCMP_EQUAL,           ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED },
10284         {   D3DCMP_LESSEQUAL,       ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_FAILED },
10285         {   D3DCMP_GREATER,         ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_PASSED },
10286         {   D3DCMP_NOTEQUAL,        ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED },
10287         {   D3DCMP_GREATEREQUAL,    ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED },
10288         {   D3DCMP_ALWAYS,          ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED },
10289     };
10290     unsigned int i, j;
10291     HRESULT hr;
10292     DWORD color;
10293     struct vertex quad[] = {
10294         {   -1.0,    -1.0,   0.1,    ALPHATEST_PASSED | 0x80000000  },
10295         {    1.0,    -1.0,   0.1,    ALPHATEST_PASSED | 0x80000000  },
10296         {   -1.0,     1.0,   0.1,    ALPHATEST_PASSED | 0x80000000  },
10297         {    1.0,     1.0,   0.1,    ALPHATEST_PASSED | 0x80000000  },
10298     };
10299     D3DCAPS9 caps;
10300
10301     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, TRUE);
10302     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10303     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
10304     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
10305
10306     for(j = 0; j < 2; j++) {
10307         if(j == 1) {
10308             /* Try a pixel shader instead of fixed function. The wined3d code may emulate
10309              * the alpha test either for performance reasons(floating point RTs) or to work
10310              * around driver bugs(Geforce 7x00 cards on MacOS). There may be a different
10311              * codepath for ffp and shader in this case, and the test should cover both
10312              */
10313             IDirect3DPixelShader9 *ps;
10314             DWORD shader_code[] = {
10315                 0xffff0101,                                 /* ps_1_1           */
10316                 0x00000001, 0x800f0000, 0x90e40000,         /* mov r0, v0       */
10317                 0x0000ffff                                  /* end              */
10318             };
10319             memset(&caps, 0, sizeof(caps));
10320             IDirect3DDevice9_GetDeviceCaps(device, &caps);
10321             ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with 0x%08x\n", hr);
10322             if(caps.PixelShaderVersion < D3DPS_VERSION(1, 1)) {
10323                 break;
10324             }
10325
10326             hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &ps);
10327             ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed with 0x%08x\n", hr);
10328             IDirect3DDevice9_SetPixelShader(device, ps);
10329             ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with 0x%08x\n", hr);
10330             IDirect3DPixelShader9_Release(ps);
10331         }
10332
10333         for(i = 0; i < (sizeof(testdata)/sizeof(testdata[0])); i++) {
10334             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAFUNC, testdata[i].func);
10335             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10336
10337             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0, 0);
10338             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10339             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAREF, 0x90);
10340             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10341             hr = IDirect3DDevice9_BeginScene(device);
10342             ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
10343             if(SUCCEEDED(hr)) {
10344                 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
10345                 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10346                 hr = IDirect3DDevice9_EndScene(device);
10347                 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with 0x%08x\n", hr);
10348             }
10349             color = getPixelColor(device, 320, 240);
10350             ok(color_match(color, testdata[i].color_less, 1), "Alphatest failed. Got color 0x%08x, expected 0x%08x. alpha < ref, func %u\n",
10351             color, testdata[i].color_less, testdata[i].func);
10352             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10353             ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
10354
10355             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0, 0);
10356             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10357             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAREF, 0x80);
10358             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10359             hr = IDirect3DDevice9_BeginScene(device);
10360             ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
10361             if(SUCCEEDED(hr)) {
10362                 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
10363                 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10364                 hr = IDirect3DDevice9_EndScene(device);
10365                 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with 0x%08x\n", hr);
10366             }
10367             color = getPixelColor(device, 320, 240);
10368             ok(color_match(color, testdata[i].color_equal, 1), "Alphatest failed. Got color 0x%08x, expected 0x%08x. alpha == ref, func %u\n",
10369             color, testdata[i].color_equal, testdata[i].func);
10370             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10371             ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
10372
10373             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0, 0);
10374             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10375             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAREF, 0x70);
10376             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10377             hr = IDirect3DDevice9_BeginScene(device);
10378             ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
10379             if(SUCCEEDED(hr)) {
10380                 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
10381                 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10382                 hr = IDirect3DDevice9_EndScene(device);
10383                 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with 0x%08x\n", hr);
10384             }
10385             color = getPixelColor(device, 320, 240);
10386             ok(color_match(color, testdata[i].color_greater, 1), "Alphatest failed. Got color 0x%08x, expected 0x%08x. alpha > ref, func %u\n",
10387             color, testdata[i].color_greater, testdata[i].func);
10388             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10389             ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
10390         }
10391     }
10392
10393     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, FALSE);
10394     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10395     IDirect3DDevice9_SetPixelShader(device, NULL);
10396     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with 0x%08x\n", hr);
10397 }
10398
10399 static void sincos_test(IDirect3DDevice9 *device) {
10400     const DWORD sin_shader_code[] = {
10401         0xfffe0200,                                                                 /* vs_2_0                       */
10402         0x0200001f, 0x80000000, 0x900f0000,                                         /* dcl_position v0              */
10403         0x05000051, 0xa00f0002, 0x40490fdb, 0x3f800000, 0x00000000, 0x3f59999a,     /* def c2, 3.14159, 1, 0, 0.85  */
10404         0x03000005, 0x80010001, 0x90000000, 0xa0000002,                             /* mul r1.x, v0.x, c2.x         */
10405         0x04000025, 0x80020000, 0x80000001, 0xa0e40000, 0xa0e40001,                 /* sincos r0.y, r1.x, c0, c1    */
10406         0x02000001, 0xc00d0000, 0x90e40000,                                         /* mov oPos.xzw, v0             */
10407         0x03000005, 0xc0020000, 0x80550000, 0xa0ff0002,                             /* mul oPos.y, r0.y, c2.w       */
10408         0x02000001, 0xd00f0000, 0xa0a60002,                                         /* mov oD0, c2.zyzz             */
10409         0x0000ffff                                                                  /* end                          */
10410     };
10411     const DWORD cos_shader_code[] = {
10412         0xfffe0200,                                                                 /* vs_2_0                       */
10413         0x0200001f, 0x80000000, 0x900f0000,                                         /* dcl_position v0              */
10414         0x05000051, 0xa00f0002, 0x40490fdb, 0x3f800000, 0x00000000, 0x3f59999a,     /* def c2, 3.14159, 1, 0, 0.85  */
10415         0x03000005, 0x80010001, 0x90000000, 0xa0000002,                             /* mul r1.x, v0.x, c2.x         */
10416         0x04000025, 0x80010000, 0x80000001, 0xa0e40000, 0xa0e40001,                 /* sincos r0.x, r1.x, c0, c1    */
10417         0x02000001, 0xc00d0000, 0x90e40000,                                         /* mov oPos.xzw, v0             */
10418         0x03000005, 0xc0020000, 0x80000000, 0xa0ff0002,                             /* mul oPos.y, r0.x, c2.w       */
10419         0x02000001, 0xd00f0000, 0xa0a90002,                                         /* mov oD0, c2.yzzz             */
10420         0x0000ffff                                                                  /* end                          */
10421     };
10422     IDirect3DVertexShader9 *sin_shader, *cos_shader;
10423     HRESULT hr;
10424     struct {
10425         float x, y, z;
10426     } data[1280];
10427     unsigned int i;
10428     float sincosc1[4] = {D3DSINCOSCONST1};
10429     float sincosc2[4] = {D3DSINCOSCONST2};
10430
10431     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
10432     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10433
10434     hr = IDirect3DDevice9_CreateVertexShader(device, sin_shader_code, &sin_shader);
10435     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10436     hr = IDirect3DDevice9_CreateVertexShader(device, cos_shader_code, &cos_shader);
10437     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10438     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10439     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
10440     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, sincosc1, 1);
10441     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF failed with 0x%08x\n", hr);
10442     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, sincosc2, 1);
10443     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF failed with 0x%08x\n", hr);
10444
10445     /* Generate a point from -1 to 1 every 0.5 pixels */
10446     for(i = 0; i < 1280; i++) {
10447         data[i].x = (-640.0 + i) / 640.0;
10448         data[i].y = 0.0;
10449         data[i].z = 0.1;
10450     }
10451
10452     hr = IDirect3DDevice9_BeginScene(device);
10453     if(SUCCEEDED(hr)) {
10454         hr = IDirect3DDevice9_SetVertexShader(device, sin_shader);
10455         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with 0x%08x\n", hr);
10456         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1280, data, sizeof(*data));
10457         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed with 0x%08x\n", hr);
10458
10459         hr = IDirect3DDevice9_SetVertexShader(device, cos_shader);
10460         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with 0x%08x\n", hr);
10461         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1280, data, sizeof(*data));
10462         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed with 0x%08x\n", hr);
10463
10464         hr = IDirect3DDevice9_EndScene(device);
10465         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with 0x%08x\n", hr);
10466     }
10467     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10468     ok(SUCCEEDED(hr), "IDirect3DDevice9_Present returned %#x.\n", hr);
10469     /* TODO: Find a way to properly validate the lines. Precicion issues make this a kinda nasty task */
10470
10471     IDirect3DDevice9_SetVertexShader(device, NULL);
10472     IDirect3DVertexShader9_Release(sin_shader);
10473     IDirect3DVertexShader9_Release(cos_shader);
10474 }
10475
10476 static void loop_index_test(IDirect3DDevice9 *device) {
10477     const DWORD shader_code[] = {
10478         0xfffe0200,                                                 /* vs_2_0                   */
10479         0x0200001f, 0x80000000, 0x900f0000,                         /* dcl_position v0          */
10480         0x02000001, 0x800f0000, 0xa0e40000,                         /* mov r0, c0               */
10481         0x0200001b, 0xf0e40800, 0xf0e40000,                         /* loop aL, i0              */
10482         0x04000002, 0x800f0000, 0x80e40000, 0xa0e42001, 0xf0e40800, /* add r0, r0, c[aL + 1]    */
10483         0x0000001d,                                                 /* endloop                  */
10484         0x02000001, 0xc00f0000, 0x90e40000,                         /* mov oPos, v0             */
10485         0x02000001, 0xd00f0000, 0x80e40000,                         /* mov oD0, r0              */
10486         0x0000ffff                                                  /* END                      */
10487     };
10488     IDirect3DVertexShader9 *shader;
10489     HRESULT hr;
10490     DWORD color;
10491     const float quad[] = {
10492         -1.0,   -1.0,   0.1,
10493          1.0,   -1.0,   0.1,
10494         -1.0,    1.0,   0.1,
10495          1.0,    1.0,   0.1
10496     };
10497     const float zero[4] = {0, 0, 0, 0};
10498     const float one[4] = {1, 1, 1, 1};
10499     int i0[4] = {2, 10, -3, 0};
10500     float values[4];
10501
10502     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
10503     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader failed with %08x\n", hr);
10504     hr = IDirect3DDevice9_SetVertexShader(device, shader);
10505     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with %08x\n", hr);
10506     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10507     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
10508     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ff0000, 0.0, 0);
10509     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
10510
10511     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, zero, 1);
10512     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10513     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, one, 1);
10514     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10515     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 2, one, 1);
10516     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10517     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 3, one, 1);
10518     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10519     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 4, one, 1);
10520     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10521     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 5, one, 1);
10522     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10523     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 6, one, 1);
10524     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10525     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 7, one, 1);
10526     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10527     values[0] = 1.0;
10528     values[1] = 1.0;
10529     values[2] = 0.0;
10530     values[3] = 0.0;
10531     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 8, values, 1);
10532     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10533     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 9, one, 1);
10534     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10535     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 10, one, 1);
10536     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10537     values[0] = -1.0;
10538     values[1] = 0.0;
10539     values[2] = 0.0;
10540     values[3] = 0.0;
10541     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 11, values, 1);
10542     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10543     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 12, one, 1);
10544     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10545     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 13, one, 1);
10546     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10547     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 14, one, 1);
10548     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10549     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 15, one, 1);
10550     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10551
10552     hr = IDirect3DDevice9_SetVertexShaderConstantI(device, 0, i0, 1);
10553     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantI returned %#x.\n", hr);
10554
10555     hr = IDirect3DDevice9_BeginScene(device);
10556     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
10557     if(SUCCEEDED(hr))
10558     {
10559         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
10560         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
10561         hr = IDirect3DDevice9_EndScene(device);
10562         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
10563     }
10564     color = getPixelColor(device, 320, 240);
10565     ok(color_match(color, 0x0000ff00, 1),
10566        "aL indexing test returned color 0x%08x, expected 0x0000ff00\n", color);
10567     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10568     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
10569
10570     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
10571     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with %08x\n", hr);
10572     IDirect3DVertexShader9_Release(shader);
10573 }
10574
10575 static void sgn_test(IDirect3DDevice9 *device) {
10576     const DWORD shader_code[] = {
10577         0xfffe0200,                                                             /* vs_2_0                       */
10578         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position o0              */
10579         0x05000051, 0xa00f0000, 0xbf000000, 0x00000000, 0x3f000000, 0x41400000, /* def c0, -0.5, 0.0, 0.5, 12.0 */
10580         0x05000051, 0xa00f0001, 0x3fc00000, 0x00000000, 0x00000000, 0x00000000, /* def c1, 1.5, 0.0, 0.0, 0.0   */
10581         0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
10582         0x04000022, 0x800f0000, 0xa0e40000, 0x80e40001, 0x80e40002,             /* sgn r0, c0, r1, r2           */
10583         0x03000002, 0xd00f0000, 0x80e40000, 0xa0e40001,                         /* add oD0, r0, c1              */
10584         0x0000ffff                                                              /* end                          */
10585     };
10586     IDirect3DVertexShader9 *shader;
10587     HRESULT hr;
10588     DWORD color;
10589     const float quad[] = {
10590         -1.0,   -1.0,   0.1,
10591          1.0,   -1.0,   0.1,
10592         -1.0,    1.0,   0.1,
10593          1.0,    1.0,   0.1
10594     };
10595
10596     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
10597     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader failed with %08x\n", hr);
10598     hr = IDirect3DDevice9_SetVertexShader(device, shader);
10599     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with %08x\n", hr);
10600     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10601     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
10602     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ff0000, 0.0, 0);
10603     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
10604
10605     hr = IDirect3DDevice9_BeginScene(device);
10606     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
10607     if(SUCCEEDED(hr))
10608     {
10609         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
10610         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
10611         hr = IDirect3DDevice9_EndScene(device);
10612         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
10613     }
10614     color = getPixelColor(device, 320, 240);
10615     ok(color_match(color, 0x008000ff, 1),
10616        "sgn test returned color 0x%08x, expected 0x008000ff\n", color);
10617     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10618     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
10619
10620     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
10621     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with %08x\n", hr);
10622     IDirect3DVertexShader9_Release(shader);
10623 }
10624
10625 static void viewport_test(IDirect3DDevice9 *device) {
10626     HRESULT hr;
10627     DWORD color;
10628     D3DVIEWPORT9 vp, old_vp;
10629     BOOL draw_failed = TRUE;
10630     const float quad[] =
10631     {
10632         -0.5,   -0.5,   0.1,
10633          0.5,   -0.5,   0.1,
10634         -0.5,    0.5,   0.1,
10635          0.5,    0.5,   0.1
10636     };
10637
10638     memset(&old_vp, 0, sizeof(old_vp));
10639     hr = IDirect3DDevice9_GetViewport(device, &old_vp);
10640     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
10641
10642     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ff0000, 0.0, 0);
10643     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
10644
10645     /* Test a viewport with Width and Height bigger than the surface dimensions
10646      *
10647      * TODO: Test Width < surface.width, but X + Width > surface.width
10648      * TODO: Test Width < surface.width, what happens with the height?
10649      *
10650      * The expected behavior is that the viewport behaves like the "default"
10651      * viewport with X = Y = 0, Width = surface_width, Height = surface_height,
10652      * MinZ = 0.0, MaxZ = 1.0.
10653      *
10654      * Starting with Windows 7 the behavior among driver versions is not
10655      * consistent. The SetViewport call is accepted on all drivers. Some
10656      * drivers(older nvidia ones) refuse to draw and return an error. Newer
10657      * nvidia drivers draw, but use the actual values in the viewport and only
10658      * display the upper left part on the surface.
10659      */
10660     memset(&vp, 0, sizeof(vp));
10661     vp.X = 0;
10662     vp.Y = 0;
10663     vp.Width = 10000;
10664     vp.Height = 10000;
10665     vp.MinZ = 0.0;
10666     vp.MaxZ = 0.0;
10667     hr = IDirect3DDevice9_SetViewport(device, &vp);
10668     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
10669
10670     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10671     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
10672     hr = IDirect3DDevice9_BeginScene(device);
10673     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
10674     if(SUCCEEDED(hr))
10675     {
10676         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
10677         ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL), "DrawPrimitiveUP failed (%08x)\n", hr);
10678         draw_failed = FAILED(hr);
10679         hr = IDirect3DDevice9_EndScene(device);
10680         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
10681     }
10682
10683     if(!draw_failed)
10684     {
10685         color = getPixelColor(device, 158, 118);
10686         ok(color == 0x00ff0000, "viewport test: (158,118) has color %08x\n", color);
10687         color = getPixelColor(device, 162, 118);
10688         ok(color == 0x00ff0000, "viewport test: (162,118) has color %08x\n", color);
10689         color = getPixelColor(device, 158, 122);
10690         ok(color == 0x00ff0000, "viewport test: (158,122) has color %08x\n", color);
10691         color = getPixelColor(device, 162, 122);
10692         ok(color == 0x00ffffff || broken(color == 0x00ff0000), "viewport test: (162,122) has color %08x\n", color);
10693
10694         color = getPixelColor(device, 478, 358);
10695         ok(color == 0x00ffffff || broken(color == 0x00ff0000), "viewport test: (478,358 has color %08x\n", color);
10696         color = getPixelColor(device, 482, 358);
10697         ok(color == 0x00ff0000, "viewport test: (482,358) has color %08x\n", color);
10698         color = getPixelColor(device, 478, 362);
10699         ok(color == 0x00ff0000, "viewport test: (478,362) has color %08x\n", color);
10700         color = getPixelColor(device, 482, 362);
10701         ok(color == 0x00ff0000, "viewport test: (482,362) has color %08x\n", color);
10702     }
10703
10704     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10705     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
10706
10707     hr = IDirect3DDevice9_SetViewport(device, &old_vp);
10708     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
10709 }
10710
10711 /* This test tests depth clamping / clipping behaviour:
10712  *   - With software vertex processing, depth values are clamped to the
10713  *     minimum / maximum z value when D3DRS_CLIPPING is disabled, and clipped
10714  *     when D3DRS_CLIPPING is enabled. Pretransformed vertices behave the
10715  *     same as regular vertices here.
10716  *   - With hardware vertex processing, D3DRS_CLIPPING seems to be ignored.
10717  *     Normal vertices are always clipped. Pretransformed vertices are
10718  *     clipped when D3DPMISCCAPS_CLIPTLVERTS is set, clamped when it isn't.
10719  *   - The viewport's MinZ/MaxZ is irrelevant for this.
10720  */
10721 static void depth_clamp_test(IDirect3DDevice9 *device)
10722 {
10723     const struct tvertex quad1[] =
10724     {
10725         {  0.0f,   0.0f,  5.0f, 1.0f, 0xff002b7f},
10726         {640.0f,   0.0f,  5.0f, 1.0f, 0xff002b7f},
10727         {  0.0f, 480.0f,  5.0f, 1.0f, 0xff002b7f},
10728         {640.0f, 480.0f,  5.0f, 1.0f, 0xff002b7f},
10729     };
10730     const struct tvertex quad2[] =
10731     {
10732         {  0.0f, 300.0f, 10.0f, 1.0f, 0xfff9e814},
10733         {640.0f, 300.0f, 10.0f, 1.0f, 0xfff9e814},
10734         {  0.0f, 360.0f, 10.0f, 1.0f, 0xfff9e814},
10735         {640.0f, 360.0f, 10.0f, 1.0f, 0xfff9e814},
10736     };
10737     const struct tvertex quad3[] =
10738     {
10739         {112.0f, 108.0f,  5.0f, 1.0f, 0xffffffff},
10740         {208.0f, 108.0f,  5.0f, 1.0f, 0xffffffff},
10741         {112.0f, 204.0f,  5.0f, 1.0f, 0xffffffff},
10742         {208.0f, 204.0f,  5.0f, 1.0f, 0xffffffff},
10743     };
10744     const struct tvertex quad4[] =
10745     {
10746         { 42.0f,  41.0f, 10.0f, 1.0f, 0xffffffff},
10747         {112.0f,  41.0f, 10.0f, 1.0f, 0xffffffff},
10748         { 42.0f, 108.0f, 10.0f, 1.0f, 0xffffffff},
10749         {112.0f, 108.0f, 10.0f, 1.0f, 0xffffffff},
10750     };
10751     const struct vertex quad5[] =
10752     {
10753         { -0.5f,   0.5f, 10.0f,       0xff14f914},
10754         {  0.5f,   0.5f, 10.0f,       0xff14f914},
10755         { -0.5f,  -0.5f, 10.0f,       0xff14f914},
10756         {  0.5f,  -0.5f, 10.0f,       0xff14f914},
10757     };
10758     const struct vertex quad6[] =
10759     {
10760         { -1.0f,   0.5f, 10.0f,      0xfff91414},
10761         {  1.0f,   0.5f, 10.0f,      0xfff91414},
10762         { -1.0f,  0.25f, 10.0f,      0xfff91414},
10763         {  1.0f,  0.25f, 10.0f,      0xfff91414},
10764     };
10765
10766     D3DVIEWPORT9 vp;
10767     D3DCOLOR color;
10768     D3DCAPS9 caps;
10769     HRESULT hr;
10770
10771     vp.X = 0;
10772     vp.Y = 0;
10773     vp.Width = 640;
10774     vp.Height = 480;
10775     vp.MinZ = 0.0;
10776     vp.MaxZ = 7.5;
10777
10778     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10779     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10780
10781     hr = IDirect3DDevice9_SetViewport(device, &vp);
10782     if(FAILED(hr))
10783     {
10784         /* Windows 7 rejects MaxZ > 1.0, Windows XP allows it. This doesn't break
10785          * the tests because the 7.5 is just intended to show that it doesn't have
10786          * any influence on the drawing or D3DRS_CLIPPING = FALSE. Set an accepted
10787          * viewport and continue.
10788          */
10789         ok(broken(hr == D3DERR_INVALIDCALL), "D3D rejected maxZ > 1.0\n");
10790         vp.MaxZ = 1.0;
10791         hr = IDirect3DDevice9_SetViewport(device, &vp);
10792     }
10793     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
10794
10795     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ff00, 1.0, 0);
10796     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
10797
10798     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
10799     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10800     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
10801     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10802     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
10803     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10804     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
10805     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10806
10807     hr = IDirect3DDevice9_BeginScene(device);
10808     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
10809
10810     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
10811     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
10812
10813     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
10814     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10815     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
10816     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10817
10818     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, TRUE);
10819     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10820
10821     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(*quad3));
10822     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10823     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(*quad4));
10824     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10825
10826     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
10827     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10828
10829     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
10830     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
10831
10832     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad5, sizeof(*quad5));
10833     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10834
10835     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, TRUE);
10836     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10837
10838     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad6, sizeof(*quad6));
10839     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10840
10841     hr = IDirect3DDevice9_EndScene(device);
10842     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
10843
10844     if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_CLIPTLVERTS)
10845     {
10846         color = getPixelColor(device, 75, 75);
10847         ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
10848         color = getPixelColor(device, 150, 150);
10849         ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
10850         color = getPixelColor(device, 320, 240);
10851         ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
10852         color = getPixelColor(device, 320, 330);
10853         ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
10854         color = getPixelColor(device, 320, 330);
10855         ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
10856     }
10857     else
10858     {
10859         color = getPixelColor(device, 75, 75);
10860         ok(color_match(color, 0x00ffffff, 1), "color 0x%08x.\n", color);
10861         color = getPixelColor(device, 150, 150);
10862         ok(color_match(color, 0x00ffffff, 1), "color 0x%08x.\n", color);
10863         color = getPixelColor(device, 320, 240);
10864         ok(color_match(color, 0x00002b7f, 1), "color 0x%08x.\n", color);
10865         color = getPixelColor(device, 320, 330);
10866         ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
10867         color = getPixelColor(device, 320, 330);
10868         ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
10869     }
10870
10871     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10872     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
10873
10874     vp.MinZ = 0.0;
10875     vp.MaxZ = 1.0;
10876     hr = IDirect3DDevice9_SetViewport(device, &vp);
10877     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
10878 }
10879
10880 static void depth_bounds_test(IDirect3DDevice9 *device)
10881 {
10882     const struct tvertex quad1[] =
10883     {
10884         {    0,    0, 0.0f, 1, 0xfff9e814},
10885         {  640,    0, 0.0f, 1, 0xfff9e814},
10886         {    0,  480, 1.0f, 1, 0xfff9e814},
10887         {  640,  480, 1.0f, 1, 0xfff9e814},
10888     };
10889     const struct tvertex quad2[] =
10890     {
10891         {    0,    0,  0.6f, 1, 0xff002b7f},
10892         {  640,    0,  0.6f, 1, 0xff002b7f},
10893         {    0,  480,  0.6f, 1, 0xff002b7f},
10894         {  640,  480,  0.6f, 1, 0xff002b7f},
10895     };
10896     const struct tvertex quad3[] =
10897     {
10898         {    0,  100, 0.6f, 1, 0xfff91414},
10899         {  640,  100, 0.6f, 1, 0xfff91414},
10900         {    0,  160, 0.6f, 1, 0xfff91414},
10901         {  640,  160, 0.6f, 1, 0xfff91414},
10902     };
10903
10904     union {
10905         DWORD d;
10906         float f;
10907     } tmpvalue;
10908
10909     IDirect3D9 *d3d = NULL;
10910     IDirect3DSurface9 *offscreen_surface = NULL;
10911     D3DCOLOR color;
10912     HRESULT hr;
10913
10914     IDirect3DDevice9_GetDirect3D(device, &d3d);
10915     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
10916             0,  D3DRTYPE_SURFACE, MAKEFOURCC('N','V','D','B')) != D3D_OK) {
10917         skip("No NVDB (depth bounds test) support\n");
10918         IDirect3D9_Release(d3d);
10919         return;
10920     }
10921     IDirect3D9_Release(d3d);
10922
10923     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
10924             MAKEFOURCC('N','V','D','B'), D3DPOOL_DEFAULT, &offscreen_surface, NULL);
10925     ok(FAILED(hr), "Able to create surface, hr %#x.\n", hr);
10926     if (offscreen_surface) IDirect3DSurface9_Release(offscreen_surface);
10927
10928     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0, 0);
10929     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
10930
10931     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
10932     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10933     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, TRUE);
10934     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10935     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
10936     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10937     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
10938     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10939
10940
10941     hr = IDirect3DDevice9_BeginScene(device);
10942     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
10943
10944     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
10945     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
10946
10947     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
10948     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10949
10950     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ADAPTIVETESS_X, MAKEFOURCC('N','V','D','B'));
10951     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10952
10953     tmpvalue.f = 0.625;
10954     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ADAPTIVETESS_Z, tmpvalue.d);
10955     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10956
10957     tmpvalue.f = 0.75;
10958     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ADAPTIVETESS_W, tmpvalue.d);
10959     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10960
10961     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
10962     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10963
10964     tmpvalue.f = 0.75;
10965     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ADAPTIVETESS_Z, tmpvalue.d);
10966     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10967
10968     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(*quad3));
10969     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10970
10971     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ADAPTIVETESS_X, 0);
10972     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10973
10974     hr = IDirect3DDevice9_EndScene(device);
10975     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
10976
10977     color = getPixelColor(device, 150, 130);
10978     ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
10979     color = getPixelColor(device, 150, 200);
10980     ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
10981     color = getPixelColor(device, 150, 300-5);
10982     ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
10983     color = getPixelColor(device, 150, 300+5);
10984     ok(color_match(color, 0x00002b7f, 1), "color 0x%08x.\n", color);/**/
10985     color = getPixelColor(device, 150, 330);
10986     ok(color_match(color, 0x00002b7f, 1), "color 0x%08x.\n", color);
10987     color = getPixelColor(device, 150, 360-5);
10988     ok(color_match(color, 0x00002b7f, 1), "color 0x%08x.\n", color);/**/
10989     color = getPixelColor(device, 150, 360+5);
10990     ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
10991
10992     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10993     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
10994 }
10995
10996 static void depth_buffer_test(IDirect3DDevice9 *device)
10997 {
10998     static const struct vertex quad1[] =
10999     {
11000         { -1.0,  1.0, 0.33f, 0xff00ff00},
11001         {  1.0,  1.0, 0.33f, 0xff00ff00},
11002         { -1.0, -1.0, 0.33f, 0xff00ff00},
11003         {  1.0, -1.0, 0.33f, 0xff00ff00},
11004     };
11005     static const struct vertex quad2[] =
11006     {
11007         { -1.0,  1.0, 0.50f, 0xffff00ff},
11008         {  1.0,  1.0, 0.50f, 0xffff00ff},
11009         { -1.0, -1.0, 0.50f, 0xffff00ff},
11010         {  1.0, -1.0, 0.50f, 0xffff00ff},
11011     };
11012     static const struct vertex quad3[] =
11013     {
11014         { -1.0,  1.0, 0.66f, 0xffff0000},
11015         {  1.0,  1.0, 0.66f, 0xffff0000},
11016         { -1.0, -1.0, 0.66f, 0xffff0000},
11017         {  1.0, -1.0, 0.66f, 0xffff0000},
11018     };
11019     static const DWORD expected_colors[4][4] =
11020     {
11021         {0x000000ff, 0x000000ff, 0x0000ff00, 0x00ff0000},
11022         {0x000000ff, 0x000000ff, 0x0000ff00, 0x00ff0000},
11023         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x00ff0000},
11024         {0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000},
11025     };
11026
11027     IDirect3DSurface9 *backbuffer, *rt1, *rt2, *rt3;
11028     unsigned int i, j;
11029     D3DVIEWPORT9 vp;
11030     D3DCOLOR color;
11031     HRESULT hr;
11032
11033     vp.X = 0;
11034     vp.Y = 0;
11035     vp.Width = 640;
11036     vp.Height = 480;
11037     vp.MinZ = 0.0;
11038     vp.MaxZ = 1.0;
11039
11040     hr = IDirect3DDevice9_SetViewport(device, &vp);
11041     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
11042
11043     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
11044     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11045     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
11046     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11047     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
11048     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11049     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
11050     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11051     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
11052     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
11053
11054     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
11055     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
11056     hr = IDirect3DDevice9_CreateRenderTarget(device, 320, 240, D3DFMT_A8R8G8B8,
11057             D3DMULTISAMPLE_NONE, 0, FALSE, &rt1, NULL);
11058     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
11059     hr = IDirect3DDevice9_CreateRenderTarget(device, 480, 360, D3DFMT_A8R8G8B8,
11060             D3DMULTISAMPLE_NONE, 0, FALSE, &rt2, NULL);
11061     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
11062     hr = IDirect3DDevice9_CreateRenderTarget(device, 640, 480, D3DFMT_A8R8G8B8,
11063             D3DMULTISAMPLE_NONE, 0, FALSE, &rt3, NULL);
11064     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
11065
11066     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt3);
11067     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11068     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 0.0f, 0);
11069     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11070
11071     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
11072     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11073     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
11074     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11075
11076     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt1);
11077     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11078     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0f, 0);
11079     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11080
11081     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt2);
11082     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11083     hr = IDirect3DDevice9_BeginScene(device);
11084     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11085     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
11086     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11087     hr = IDirect3DDevice9_EndScene(device);
11088     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11089
11090     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
11091     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11092     IDirect3DSurface9_Release(backbuffer);
11093     IDirect3DSurface9_Release(rt3);
11094     IDirect3DSurface9_Release(rt2);
11095     IDirect3DSurface9_Release(rt1);
11096
11097     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
11098     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11099
11100     hr = IDirect3DDevice9_BeginScene(device);
11101     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11102     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
11103     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11104     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(*quad3));
11105     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11106     hr = IDirect3DDevice9_EndScene(device);
11107     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11108
11109     for (i = 0; i < 4; ++i)
11110     {
11111         for (j = 0; j < 4; ++j)
11112         {
11113             unsigned int x = 80 * ((2 * j) + 1);
11114             unsigned int y = 60 * ((2 * i) + 1);
11115             color = getPixelColor(device, x, y);
11116             ok(color_match(color, expected_colors[i][j], 0),
11117                     "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
11118         }
11119     }
11120
11121     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11122     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
11123 }
11124
11125 /* Test that partial depth copies work the way they're supposed to. The clear
11126  * on rt2 only needs a partial copy of the onscreen depth/stencil buffer, and
11127  * the following draw should only copy back the part that was modified. */
11128 static void depth_buffer2_test(IDirect3DDevice9 *device)
11129 {
11130     static const struct vertex quad[] =
11131     {
11132         { -1.0,  1.0, 0.66f, 0xffff0000},
11133         {  1.0,  1.0, 0.66f, 0xffff0000},
11134         { -1.0, -1.0, 0.66f, 0xffff0000},
11135         {  1.0, -1.0, 0.66f, 0xffff0000},
11136     };
11137
11138     IDirect3DSurface9 *backbuffer, *rt1, *rt2;
11139     unsigned int i, j;
11140     D3DVIEWPORT9 vp;
11141     D3DCOLOR color;
11142     HRESULT hr;
11143
11144     vp.X = 0;
11145     vp.Y = 0;
11146     vp.Width = 640;
11147     vp.Height = 480;
11148     vp.MinZ = 0.0;
11149     vp.MaxZ = 1.0;
11150
11151     hr = IDirect3DDevice9_SetViewport(device, &vp);
11152     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
11153
11154     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
11155     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11156     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
11157     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11158     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
11159     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11160     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
11161     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11162     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
11163     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
11164
11165     hr = IDirect3DDevice9_CreateRenderTarget(device, 640, 480, D3DFMT_A8R8G8B8,
11166             D3DMULTISAMPLE_NONE, 0, FALSE, &rt1, NULL);
11167     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
11168     hr = IDirect3DDevice9_CreateRenderTarget(device, 480, 360, D3DFMT_A8R8G8B8,
11169             D3DMULTISAMPLE_NONE, 0, FALSE, &rt2, NULL);
11170     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
11171     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
11172     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
11173
11174     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt1);
11175     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11176     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
11177     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11178
11179     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
11180     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11181     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ff00, 0.5f, 0);
11182     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11183
11184     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt2);
11185     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11186     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0f, 0);
11187     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11188
11189     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
11190     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11191     IDirect3DSurface9_Release(backbuffer);
11192     IDirect3DSurface9_Release(rt2);
11193     IDirect3DSurface9_Release(rt1);
11194
11195     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
11196     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11197
11198     hr = IDirect3DDevice9_BeginScene(device);
11199     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11200     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
11201     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11202     hr = IDirect3DDevice9_EndScene(device);
11203     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11204
11205     for (i = 0; i < 4; ++i)
11206     {
11207         for (j = 0; j < 4; ++j)
11208         {
11209             unsigned int x = 80 * ((2 * j) + 1);
11210             unsigned int y = 60 * ((2 * i) + 1);
11211             color = getPixelColor(device, x, y);
11212             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 0),
11213                     "Expected color 0x0000ff00 at %u,%u, got 0x%08x.\n", x, y, color);
11214         }
11215     }
11216
11217     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11218     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
11219 }
11220
11221 static void depth_blit_test(IDirect3DDevice9 *device)
11222 {
11223     static const struct vertex quad1[] =
11224     {
11225         { -1.0,  1.0, 0.50f, 0xff00ff00},
11226         {  1.0,  1.0, 0.50f, 0xff00ff00},
11227         { -1.0, -1.0, 0.50f, 0xff00ff00},
11228         {  1.0, -1.0, 0.50f, 0xff00ff00},
11229     };
11230     static const struct vertex quad2[] =
11231     {
11232         { -1.0,  1.0, 0.66f, 0xff0000ff},
11233         {  1.0,  1.0, 0.66f, 0xff0000ff},
11234         { -1.0, -1.0, 0.66f, 0xff0000ff},
11235         {  1.0, -1.0, 0.66f, 0xff0000ff},
11236     };
11237     static const DWORD expected_colors[4][4] =
11238     {
11239         {0x000000ff, 0x000000ff, 0x0000ff00, 0x00ff0000},
11240         {0x000000ff, 0x000000ff, 0x0000ff00, 0x00ff0000},
11241         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x00ff0000},
11242         {0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000},
11243     };
11244
11245     IDirect3DSurface9 *backbuffer, *ds1, *ds2;
11246     RECT src_rect, dst_rect;
11247     unsigned int i, j;
11248     D3DVIEWPORT9 vp;
11249     D3DCOLOR color;
11250     HRESULT hr;
11251
11252     vp.X = 0;
11253     vp.Y = 0;
11254     vp.Width = 640;
11255     vp.Height = 480;
11256     vp.MinZ = 0.0;
11257     vp.MaxZ = 1.0;
11258
11259     hr = IDirect3DDevice9_SetViewport(device, &vp);
11260     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
11261
11262     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
11263     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
11264     hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds1);
11265     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
11266     hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, 0, 0, FALSE, &ds2, NULL);
11267     ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#x.\n", hr);
11268     hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds2);
11269     ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11270
11271     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
11272     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11273     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
11274     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11275     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
11276     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11277     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
11278     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
11279
11280     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
11281     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11282     SetRect(&dst_rect, 0, 0, 480, 360);
11283     hr = IDirect3DDevice9_Clear(device, 1, (D3DRECT *)&dst_rect, D3DCLEAR_ZBUFFER, 0, 0.5f, 0);
11284     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11285     SetRect(&dst_rect, 0, 0, 320, 240);
11286     hr = IDirect3DDevice9_Clear(device, 1, (D3DRECT *)&dst_rect, D3DCLEAR_ZBUFFER, 0, 1.0f, 0);
11287     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11288
11289     /* Partial blit. */
11290     SetRect(&src_rect, 0, 0, 320, 240);
11291     SetRect(&dst_rect, 0, 0, 320, 240);
11292     hr = IDirect3DDevice9_StretchRect(device, ds2, &src_rect, ds1, &dst_rect, D3DTEXF_POINT);
11293     ok(hr == D3DERR_INVALIDCALL, "StretchRect returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
11294     /* Flipped. */
11295     SetRect(&src_rect, 0, 0, 640, 480);
11296     SetRect(&dst_rect, 0, 480, 640, 0);
11297     hr = IDirect3DDevice9_StretchRect(device, ds2, &src_rect, ds1, &dst_rect, D3DTEXF_POINT);
11298     ok(hr == D3DERR_INVALIDCALL, "StretchRect returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
11299     /* Full, explicit. */
11300     SetRect(&src_rect, 0, 0, 640, 480);
11301     SetRect(&dst_rect, 0, 0, 640, 480);
11302     hr = IDirect3DDevice9_StretchRect(device, ds2, &src_rect, ds1, &dst_rect, D3DTEXF_POINT);
11303     ok(SUCCEEDED(hr), "StretchRect failed, hr %#x.\n", hr);
11304     /* Filtered blit. */
11305     hr = IDirect3DDevice9_StretchRect(device, ds2, NULL, ds1, NULL, D3DTEXF_LINEAR);
11306     ok(SUCCEEDED(hr), "StretchRect failed, hr %#x.\n", hr);
11307     /* Depth -> color blit.*/
11308     hr = IDirect3DDevice9_StretchRect(device, ds2, NULL, backbuffer, NULL, D3DTEXF_POINT);
11309     ok(hr == D3DERR_INVALIDCALL, "StretchRect returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
11310     IDirect3DSurface9_Release(backbuffer);
11311
11312     hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds1);
11313     ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11314     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
11315     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11316     hr = IDirect3DDevice9_StretchRect(device, ds2, NULL, ds1, NULL, D3DTEXF_POINT);
11317     ok(SUCCEEDED(hr), "StretchRect failed, hr %#x.\n", hr);
11318     IDirect3DSurface9_Release(ds2);
11319     IDirect3DSurface9_Release(ds1);
11320
11321     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
11322     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11323     hr = IDirect3DDevice9_BeginScene(device);
11324     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11325     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
11326     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11327     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
11328     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11329     hr = IDirect3DDevice9_EndScene(device);
11330     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11331
11332     for (i = 0; i < 4; ++i)
11333     {
11334         for (j = 0; j < 4; ++j)
11335         {
11336             unsigned int x = 80 * ((2 * j) + 1);
11337             unsigned int y = 60 * ((2 * i) + 1);
11338             color = getPixelColor(device, x, y);
11339             ok(color_match(color, expected_colors[i][j], 0),
11340                     "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
11341         }
11342     }
11343
11344     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11345     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
11346 }
11347
11348 static void intz_test(IDirect3DDevice9 *device)
11349 {
11350     static const DWORD ps_code[] =
11351     {
11352         0xffff0200,                                                             /* ps_2_0                       */
11353         0x0200001f, 0x90000000, 0xa00f0800,                                     /* dcl_2d s0                    */
11354         0x0200001f, 0x80000000, 0xb00f0000,                                     /* dcl t0                       */
11355         0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0.0, 0.0, 0.0, 1.0   */
11356         0x02000001, 0x800f0001, 0xa0e40000,                                     /* mov r1, c0                   */
11357         0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800,                         /* texld r0, t0, s0             */
11358         0x02000001, 0x80010001, 0x80e40000,                                     /* mov r1.x, r0                 */
11359         0x03010042, 0x800f0000, 0xb0e40000, 0xa0e40800,                         /* texldp r0, t0, s0            */
11360         0x02000001, 0x80020001, 0x80000000,                                     /* mov r1.y, r0.x               */
11361         0x02000001, 0x800f0800, 0x80e40001,                                     /* mov oC0, r1                  */
11362         0x0000ffff,                                                             /* end                          */
11363     };
11364     struct
11365     {
11366         float x, y, z;
11367         float s, t, p, q;
11368     }
11369     quad[] =
11370     {
11371         { -1.0f,  1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f},
11372         {  1.0f,  1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.5f},
11373         { -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f},
11374         {  1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f},
11375     };
11376     struct
11377     {
11378         UINT x, y;
11379         D3DCOLOR color;
11380     }
11381     expected_colors[] =
11382     {
11383         { 80, 100, D3DCOLOR_ARGB(0x00, 0x20, 0x40, 0x00)},
11384         {240, 100, D3DCOLOR_ARGB(0x00, 0x60, 0xbf, 0x00)},
11385         {400, 100, D3DCOLOR_ARGB(0x00, 0x9f, 0x40, 0x00)},
11386         {560, 100, D3DCOLOR_ARGB(0x00, 0xdf, 0xbf, 0x00)},
11387         { 80, 450, D3DCOLOR_ARGB(0x00, 0x20, 0x40, 0x00)},
11388         {240, 450, D3DCOLOR_ARGB(0x00, 0x60, 0xbf, 0x00)},
11389         {400, 450, D3DCOLOR_ARGB(0x00, 0x9f, 0x40, 0x00)},
11390         {560, 450, D3DCOLOR_ARGB(0x00, 0xdf, 0xbf, 0x00)},
11391     };
11392
11393     IDirect3DSurface9 *original_ds, *original_rt, *rt;
11394     IDirect3DTexture9 *texture;
11395     IDirect3DPixelShader9 *ps;
11396     IDirect3DSurface9 *ds;
11397     IDirect3D9 *d3d9;
11398     D3DCAPS9 caps;
11399     HRESULT hr;
11400     UINT i;
11401
11402     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11403     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
11404     if (caps.PixelShaderVersion < D3DPS_VERSION(2, 0))
11405     {
11406         skip("No pixel shader 2.0 support, skipping INTZ test.\n");
11407         return;
11408     }
11409
11410     hr = IDirect3DDevice9_GetDirect3D(device, &d3d9);
11411     ok(SUCCEEDED(hr), "GetDirect3D failed, hr %#x.\n", hr);
11412
11413     hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11414             D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, MAKEFOURCC('I','N','T','Z'));
11415     if (FAILED(hr))
11416     {
11417         skip("No INTZ support, skipping INTZ test.\n");
11418         return;
11419     }
11420
11421     IDirect3D9_Release(d3d9);
11422
11423     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &original_rt);
11424     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
11425     hr = IDirect3DDevice9_GetDepthStencilSurface(device, &original_ds);
11426     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
11427
11428     hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1,
11429             D3DUSAGE_DEPTHSTENCIL, MAKEFOURCC('I','N','T','Z'), D3DPOOL_DEFAULT, &texture, NULL);
11430     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
11431     hr = IDirect3DDevice9_CreateRenderTarget(device, 1024, 1024, D3DFMT_A8R8G8B8,
11432             D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
11433     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
11434     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code, &ps);
11435     ok(SUCCEEDED(hr), "CreatePixelShader failed, hr %#x.\n", hr);
11436
11437     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE4(0));
11438     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
11439     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
11440     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11441     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
11442     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11443     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
11444     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11445     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
11446     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11447
11448     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
11449     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11450     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
11451     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11452     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
11453     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11454     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
11455     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11456     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
11457     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11458
11459     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &ds);
11460     ok(SUCCEEDED(hr), "GetSurfaceLevel failed, hr %#x.\n", hr);
11461     hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
11462     ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11463     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
11464     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11465     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
11466     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
11467
11468     /* Setup the depth/stencil surface. */
11469     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
11470     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11471
11472     hr = IDirect3DDevice9_BeginScene(device);
11473     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11474     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
11475     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11476     hr = IDirect3DDevice9_EndScene(device);
11477     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11478
11479     hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
11480     ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11481     IDirect3DSurface9_Release(ds);
11482     hr = IDirect3DDevice9_SetRenderTarget(device, 0, original_rt);
11483     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11484     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
11485     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
11486     hr = IDirect3DDevice9_SetPixelShader(device, ps);
11487     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
11488
11489     /* Read the depth values back. */
11490     hr = IDirect3DDevice9_BeginScene(device);
11491     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11492     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
11493     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11494     hr = IDirect3DDevice9_EndScene(device);
11495     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11496
11497     for (i = 0; i < sizeof(expected_colors) / sizeof(*expected_colors); ++i)
11498     {
11499         D3DCOLOR color = getPixelColor(device, expected_colors[i].x, expected_colors[i].y);
11500         ok(color_match(color, expected_colors[i].color, 1),
11501                 "Expected color 0x%08x at (%u, %u), got 0x%08x.\n",
11502                 expected_colors[i].color, expected_colors[i].x, expected_colors[i].y, color);
11503     }
11504
11505     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11506     ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
11507
11508     hr = IDirect3DDevice9_SetDepthStencilSurface(device, original_ds);
11509     ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11510     IDirect3DSurface9_Release(original_ds);
11511     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
11512     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
11513     IDirect3DTexture9_Release(texture);
11514     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
11515     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
11516     IDirect3DPixelShader9_Release(ps);
11517
11518     IDirect3DSurface9_Release(original_rt);
11519     IDirect3DSurface9_Release(rt);
11520 }
11521
11522 static void shadow_test(IDirect3DDevice9 *device)
11523 {
11524     static const DWORD ps_code[] =
11525     {
11526         0xffff0200,                                                             /* ps_2_0                       */
11527         0x0200001f, 0x90000000, 0xa00f0800,                                     /* dcl_2d s0                    */
11528         0x0200001f, 0x80000000, 0xb00f0000,                                     /* dcl t0                       */
11529         0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0.0, 0.0, 0.0, 1.0   */
11530         0x02000001, 0x800f0001, 0xa0e40000,                                     /* mov r1, c0                   */
11531         0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800,                         /* texld r0, t0, s0             */
11532         0x02000001, 0x80010001, 0x80e40000,                                     /* mov r1.x, r0                 */
11533         0x03010042, 0x800f0000, 0xb0e40000, 0xa0e40800,                         /* texldp r0, t0, s0            */
11534         0x02000001, 0x80020001, 0x80000000,                                     /* mov r1.y, r0.x               */
11535         0x02000001, 0x800f0800, 0x80e40001,                                     /* mov 0C0, r1                  */
11536         0x0000ffff,                                                             /* end                          */
11537     };
11538     struct
11539     {
11540         D3DFORMAT format;
11541         const char *name;
11542     }
11543     formats[] =
11544     {
11545         {D3DFMT_D16_LOCKABLE,   "D3DFMT_D16_LOCKABLE"},
11546         {D3DFMT_D32,            "D3DFMT_D32"},
11547         {D3DFMT_D15S1,          "D3DFMT_D15S1"},
11548         {D3DFMT_D24S8,          "D3DFMT_D24S8"},
11549         {D3DFMT_D24X8,          "D3DFMT_D24X8"},
11550         {D3DFMT_D24X4S4,        "D3DFMT_D24X4S4"},
11551         {D3DFMT_D16,            "D3DFMT_D16"},
11552         {D3DFMT_D32F_LOCKABLE,  "D3DFMT_D32F_LOCKABLE"},
11553         {D3DFMT_D24FS8,         "D3DFMT_D24FS8"},
11554     };
11555     struct
11556     {
11557         float x, y, z;
11558         float s, t, p, q;
11559     }
11560     quad[] =
11561     {
11562         { -1.0f,  1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f},
11563         {  1.0f,  1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f},
11564         { -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
11565         {  1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f},
11566     };
11567     struct
11568     {
11569         UINT x, y;
11570         D3DCOLOR color;
11571     }
11572     expected_colors[] =
11573     {
11574         {400,  60, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
11575         {560, 180, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00)},
11576         {560, 300, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00)},
11577         {400, 420, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00)},
11578         {240, 420, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00)},
11579         { 80, 300, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
11580         { 80, 180, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
11581         {240,  60, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
11582     };
11583
11584     IDirect3DSurface9 *original_ds, *original_rt, *rt;
11585     IDirect3DPixelShader9 *ps;
11586     IDirect3D9 *d3d9;
11587     D3DCAPS9 caps;
11588     HRESULT hr;
11589     UINT i;
11590
11591     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11592     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
11593     if (caps.PixelShaderVersion < D3DPS_VERSION(2, 0))
11594     {
11595         skip("No pixel shader 2.0 support, skipping shadow test.\n");
11596         return;
11597     }
11598
11599     hr = IDirect3DDevice9_GetDirect3D(device, &d3d9);
11600     ok(SUCCEEDED(hr), "GetDirect3D failed, hr %#x.\n", hr);
11601     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &original_rt);
11602     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
11603     hr = IDirect3DDevice9_GetDepthStencilSurface(device, &original_ds);
11604     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
11605
11606     hr = IDirect3DDevice9_CreateRenderTarget(device, 1024, 1024, D3DFMT_A8R8G8B8,
11607             D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
11608     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
11609     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code, &ps);
11610     ok(SUCCEEDED(hr), "CreatePixelShader failed, hr %#x.\n", hr);
11611
11612     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE4(0));
11613     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
11614     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
11615     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11616     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
11617     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11618     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
11619     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11620     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
11621     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11622
11623     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
11624     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11625     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
11626     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11627     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
11628     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11629     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
11630     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11631     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
11632     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11633
11634     for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i)
11635     {
11636         D3DFORMAT format = formats[i].format;
11637         IDirect3DTexture9 *texture;
11638         IDirect3DSurface9 *ds;
11639         unsigned int j;
11640
11641         hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11642                 D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, format);
11643         if (FAILED(hr)) continue;
11644
11645         hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1,
11646                 D3DUSAGE_DEPTHSTENCIL, format, D3DPOOL_DEFAULT, &texture, NULL);
11647         ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
11648
11649         hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &ds);
11650         ok(SUCCEEDED(hr), "GetSurfaceLevel failed, hr %#x.\n", hr);
11651
11652         hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
11653         ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11654
11655         hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
11656         ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11657
11658         IDirect3DDevice9_SetPixelShader(device, NULL);
11659         ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
11660
11661         /* Setup the depth/stencil surface. */
11662         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
11663         ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11664
11665         hr = IDirect3DDevice9_BeginScene(device);
11666         ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11667         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
11668         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11669         hr = IDirect3DDevice9_EndScene(device);
11670         ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11671
11672         hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
11673         ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11674         IDirect3DSurface9_Release(ds);
11675
11676         hr = IDirect3DDevice9_SetRenderTarget(device, 0, original_rt);
11677         ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11678
11679         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
11680         ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
11681
11682         hr = IDirect3DDevice9_SetPixelShader(device, ps);
11683         ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
11684
11685         /* Do the actual shadow mapping. */
11686         hr = IDirect3DDevice9_BeginScene(device);
11687         ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11688         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
11689         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11690         hr = IDirect3DDevice9_EndScene(device);
11691         ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11692
11693         hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
11694         ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
11695         IDirect3DTexture9_Release(texture);
11696
11697         for (j = 0; j < sizeof(expected_colors) / sizeof(*expected_colors); ++j)
11698         {
11699             D3DCOLOR color = getPixelColor(device, expected_colors[j].x, expected_colors[j].y);
11700             ok(color_match(color, expected_colors[j].color, 0),
11701                     "Expected color 0x%08x at (%u, %u) for format %s, got 0x%08x.\n",
11702                     expected_colors[j].color, expected_colors[j].x, expected_colors[j].y,
11703                     formats[i].name, color);
11704         }
11705
11706         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11707         ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
11708     }
11709
11710     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
11711     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
11712     IDirect3DPixelShader9_Release(ps);
11713
11714     hr = IDirect3DDevice9_SetDepthStencilSurface(device, original_ds);
11715     ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11716     IDirect3DSurface9_Release(original_ds);
11717
11718     IDirect3DSurface9_Release(original_rt);
11719     IDirect3DSurface9_Release(rt);
11720
11721     IDirect3D9_Release(d3d9);
11722 }
11723
11724 static void clip_planes(IDirect3DDevice9 *device, const char *test_name)
11725 {
11726     const struct vertex quad1[] =
11727     {
11728         {-1.0f, -1.0f, 0.0f, 0xfff9e814},
11729         { 1.0f, -1.0f, 0.0f, 0xfff9e814},
11730         {-1.0f,  1.0f, 0.0f, 0xfff9e814},
11731         { 1.0f,  1.0f, 0.0f, 0xfff9e814},
11732     };
11733     const struct vertex quad2[] =
11734     {
11735         {-1.0f, -1.0f, 0.0f, 0xff002b7f},
11736         { 1.0f, -1.0f, 0.0f, 0xff002b7f},
11737         {-1.0f,  1.0f, 0.0f, 0xff002b7f},
11738         { 1.0f,  1.0f, 0.0f, 0xff002b7f},
11739     };
11740     D3DCOLOR color;
11741     HRESULT hr;
11742
11743     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 1.0, 0);
11744     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11745
11746     hr = IDirect3DDevice9_BeginScene(device);
11747     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11748
11749     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
11750     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
11751
11752     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0);
11753     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11754     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
11755     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11756
11757     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0x1);
11758     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11759     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
11760     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11761
11762     hr = IDirect3DDevice9_EndScene(device);
11763     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11764
11765     color = getPixelColor(device, 1, 240);
11766     ok(color_match(color, 0x00002b7f, 1), "%s test: color 0x%08x.\n", test_name, color);
11767     color = getPixelColor(device, 638, 240);
11768     ok(color_match(color, 0x00002b7f, 1), "%s test: color 0x%08x.\n", test_name, color);
11769
11770     color = getPixelColor(device, 1, 241);
11771     ok(color_match(color, 0x00f9e814, 1), "%s test: color 0x%08x.\n", test_name, color);
11772     color = getPixelColor(device, 638, 241);
11773     ok(color_match(color, 0x00f9e814, 1), "%s test: color 0x%08x.\n", test_name, color);
11774 }
11775
11776 static void clip_planes_test(IDirect3DDevice9 *device)
11777 {
11778     const float plane0[4] = {0.0f, 1.0f, 0.0f, 0.5f / 480.0f}; /* a quarter-pixel offset */
11779
11780     const DWORD shader_code[] = {
11781         0xfffe0200, /* vs_2_0 */
11782         0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
11783         0x0200001f, 0x8000000a, 0x900f0001, /* dcl_color0 v1 */
11784         0x02000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
11785         0x02000001, 0xd00f0000, 0x90e40001, /* mov oD0, v1 */
11786         0x0000ffff /* end */
11787     };
11788     IDirect3DVertexShader9 *shader;
11789
11790     IDirect3DTexture9 *offscreen = NULL;
11791     IDirect3DSurface9 *offscreen_surface, *original_rt;
11792     HRESULT hr;
11793
11794     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &original_rt);
11795     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
11796
11797     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
11798     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11799     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
11800     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11801     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
11802     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11803     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, TRUE);
11804     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11805
11806     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
11807     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed, hr=%08x\n", hr);
11808     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
11809     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed, hr=%08x\n", hr);
11810
11811     IDirect3DDevice9_SetClipPlane(device, 0, plane0);
11812
11813     clip_planes(device, "Onscreen FFP");
11814
11815     hr = IDirect3DDevice9_CreateTexture(device, 640, 480, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &offscreen, NULL);
11816     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
11817     hr = IDirect3DTexture9_GetSurfaceLevel(offscreen, 0, &offscreen_surface);
11818     ok(SUCCEEDED(hr), "GetSurfaceLevel failed, hr %#x.\n", hr);
11819     hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen_surface);
11820     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
11821
11822     clip_planes(device, "Offscreen FFP");
11823
11824     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11825     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
11826
11827     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
11828     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
11829     IDirect3DDevice9_SetVertexShader(device, shader);
11830     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
11831
11832     hr = IDirect3DDevice9_SetRenderTarget(device, 0, original_rt);
11833     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
11834
11835     clip_planes(device, "Onscreen vertex shader");
11836
11837     hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen_surface);
11838     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
11839
11840     clip_planes(device, "Offscreen vertex shader");
11841
11842     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11843     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
11844
11845     IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0);
11846     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
11847     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed, hr=%08x\n", hr);
11848     IDirect3DVertexShader9_Release(shader);
11849     hr = IDirect3DDevice9_SetRenderTarget(device, 0, original_rt);
11850     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
11851     IDirect3DSurface9_Release(original_rt);
11852     IDirect3DSurface9_Release(offscreen_surface);
11853     IDirect3DTexture9_Release(offscreen);
11854 }
11855
11856 static void fp_special_test(IDirect3DDevice9 *device)
11857 {
11858     static const DWORD vs_header[] =
11859     {
11860         0xfffe0200,                                                             /* vs_2_0                       */
11861         0x05000051, 0xa00f0000, 0x00000000, 0x3f000000, 0x3f800000, 0x40000000, /* def c0, 0.0, 0.5, 1.0, 2.0   */
11862         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
11863         0x0200001f, 0x80000005, 0x900f0001,                                     /* dcl_texcoord0 v1             */
11864     };
11865
11866     static const DWORD vs_log[] = {0x0200000f, 0x80010000, 0x90000001};         /* log r0.x, v1.x               */
11867     static const DWORD vs_pow[] =
11868             {0x03000020, 0x80010000, 0x90000001, 0x90000001};                   /* pow r0.x, v1.x, v1.x         */
11869     static const DWORD vs_nrm[] = {0x02000024, 0x80070000, 0x90000001};         /* nrm r0.xyz, v1.x             */
11870     static const DWORD vs_rcp1[] = {0x02000006, 0x80010000, 0x90000001};        /* rcp r0.x, v1.x               */
11871     static const DWORD vs_rcp2[] = {0x02000006, 0x80010000, 0x91000001};        /* rcp r0.x, -v1.x              */
11872     static const DWORD vs_rsq1[] = {0x02000007, 0x80010000, 0x90000001};        /* rsq r0.x, v1.x               */
11873     static const DWORD vs_rsq2[] = {0x02000007, 0x80010000, 0x91000001};        /* rsq r0.x, -v1.x              */
11874     static const DWORD vs_lit[] = {0x02000010, 0x800f0000, 0x90000001,          /* lit r0, v1.xxxx              */
11875             0x02000001, 0x80010000, 0x80aa0000};                                /* mov r0.x, v0.z               */
11876
11877     static const DWORD vs_footer[] =
11878     {
11879         0x03000005, 0x80020000, 0x80000000, 0xa0ff0000,                         /* mul r0.y, r0.x, c0.w         */
11880         0x0300000d, 0x80040000, 0x80000000, 0x80550000,                         /* sge r0.z, r0.x, r0.y         */
11881         0x0300000d, 0x80020000, 0x80e40000, 0x80000000,                         /* sge r0.y, r0, r0.x           */
11882         0x03000005, 0x80040000, 0x80550000, 0x80e40000,                         /* mul r0.z, r0.y, r0           */
11883         0x0300000b, 0x80080000, 0x81aa0000, 0x80aa0000,                         /* max r0.w, -r0.z, r0.z        */
11884         0x0300000c, 0x80020000, 0x80000000, 0x80000000,                         /* slt r0.y, r0.x, r0.x         */
11885         0x03000002, 0x80040000, 0x80550000, 0x80550000,                         /* add r0.z, r0.y, r0.y         */
11886         0x0300000c, 0x80020000, 0xa0000000, 0x80ff0000,                         /* slt r0.y, c0.x, r0.w         */
11887         0x0300000b, 0x80080000, 0x81aa0000, 0x80aa0000,                         /* max r0.w, -r0.z, r0.z        */
11888         0x03000002, 0x80040000, 0x81550000, 0xa0e40000,                         /* add r0.z, -r0.y, c0          */
11889         0x0300000c, 0x80080000, 0xa0000000, 0x80e40000,                         /* slt r0.w, c0.x, r0           */
11890         0x03000005, 0x80040000, 0x80ff0000, 0x80e40000,                         /* mul r0.z, r0.w, r0           */
11891         0x04000004, 0x80020000, 0x80aa0000, 0xa0e40000, 0x80e40000,             /* mad r0.y, r0.z, c0, r0       */
11892         0x02000001, 0xe0030000, 0x80e40000,                                     /* mov oT0.xy, r0               */
11893         0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
11894         0x0000ffff,                                                             /* end                          */
11895     };
11896
11897     static const struct
11898     {
11899         const char *name;
11900         const DWORD *ops;
11901         DWORD size;
11902         D3DCOLOR r600;
11903         D3DCOLOR nv40;
11904         D3DCOLOR nv50;
11905     }
11906     vs_body[] =
11907     {
11908         /* The basic ideas here are:
11909          *     2.0 * +/-INF == +/-INF
11910          *     NAN != NAN
11911          *
11912          * The vertex shader value is written to the red component, with 0.0
11913          * and +/-INF mapping to 0xff, and NAN to 0x7f. Anything else should
11914          * result in 0x00. The pixel shader value is written to the green
11915          * component, but here 0.0 also results in 0x00. The actual value is
11916          * written to the blue component.
11917          *
11918          * There are considerable differences between graphics cards in how
11919          * these are handled, but pow and nrm never generate INF or NAN. */
11920         {"log",     vs_log,     sizeof(vs_log),     0x00000000, 0x00ff0000, 0x00ff7f00},
11921         {"pow",     vs_pow,     sizeof(vs_pow),     0x000000ff, 0x0000ff00, 0x000000ff},
11922         {"nrm",     vs_nrm,     sizeof(vs_nrm),     0x00ff0000, 0x0000ff00, 0x00ff0000},
11923         {"rcp1",    vs_rcp1,    sizeof(vs_rcp1),    0x000000ff, 0x00ff00ff, 0x00ff7f00},
11924         {"rcp2",    vs_rcp2,    sizeof(vs_rcp2),    0x00000000, 0x00ff0000, 0x00ff7f00},
11925         {"rsq1",    vs_rsq1,    sizeof(vs_rsq1),    0x000000ff, 0x00ff00ff, 0x00ff7f00},
11926         {"rsq2",    vs_rsq2,    sizeof(vs_rsq2),    0x000000ff, 0x00ff00ff, 0x00ff7f00},
11927         {"lit",     vs_lit,     sizeof(vs_lit),     0x00ff0000, 0x00ff0000, 0x00ff0000},
11928     };
11929
11930     static const DWORD ps_code[] =
11931     {
11932         0xffff0200,                                                             /* ps_2_0                       */
11933         0x05000051, 0xa00f0000, 0x00000000, 0x3f000000, 0x3f800000, 0x40000000, /* def c0, 0.0, 0.5, 1.0, 2.0   */
11934         0x0200001f, 0x80000000, 0xb0030000,                                     /* dcl t0.xy                    */
11935         0x0300000b, 0x80010001, 0xb0e40000, 0xa0e40000,                         /* max r1.x, t0, c0             */
11936         0x0300000a, 0x80010000, 0xb0e40000, 0xa0e40000,                         /* min r0.x, t0, c0             */
11937         0x03000002, 0x80010000, 0x80e40000, 0x81e40001,                         /* add r0.x, r0, -r1            */
11938         0x04000004, 0x80010001, 0xb0e40000, 0xa0ff0000, 0xb1e40000,             /* mad r1.x, t0, c0.w. -t0      */
11939         0x02000023, 0x80010002, 0x80e40001,                                     /* abs r2.x, r1                 */
11940         0x02000023, 0x80010000, 0x80e40000,                                     /* abs r0.x, r0                 */
11941         0x02000023, 0x80010001, 0xb0e40000,                                     /* abs r1.x, t0                 */
11942         0x04000058, 0x80010002, 0x81e40002, 0xa0aa0000, 0xa0e40000,             /* cmp r2.x, -r2, c0.z, c0      */
11943         0x02000023, 0x80010002, 0x80e40002,                                     /* abs r2.x, r2                 */
11944         0x04000058, 0x80010001, 0x81e40001, 0xa0aa0000, 0xa0e40000,             /* cmp r1.x, -r1, c0.z, c0      */
11945         0x02000023, 0x80010001, 0x80e40001,                                     /* abs r1.x, r1                 */
11946         0x04000058, 0x80010003, 0x81e40002, 0xa0aa0000, 0xa0e40000,             /* cmp r3.x, -r2, c0.z, c0      */
11947         0x04000058, 0x80010002, 0x81e40001, 0xa0aa0000, 0xa0e40000,             /* cmp r2.x, -r1, c0.z, c0      */
11948         0x04000058, 0x80010000, 0x81e40000, 0xa0550000, 0xa0e40000,             /* cmp r0.x, -r0, c0.y, c0      */
11949         0x03000005, 0x80010002, 0x80e40002, 0x80e40003,                         /* mul r2.x, r2, r3             */
11950         0x04000058, 0x80010000, 0x81e40002, 0xa0aa0000, 0x80e40000,             /* cmp r0.x, -r2, c0.z, r0      */
11951         0x04000058, 0x80020000, 0x81000001, 0x80000000, 0xa0000000,             /* cmp r0.y, -r1.x, r0.x, c0.x  */
11952         0x02000001, 0x80050000, 0xb0c90000,                                     /* mov r0.xz, t0.yzxw           */
11953         0x02000001, 0x80080000, 0xa0aa0000,                                     /* mov r0.w, c0.z               */
11954         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
11955         0x0000ffff,                                                             /* end                          */
11956     };
11957
11958     struct
11959     {
11960         float x, y, z;
11961         float s;
11962     }
11963     quad[] =
11964     {
11965         { -1.0f,  1.0f, 0.0f, 0.0f},
11966         {  1.0f,  1.0f, 1.0f, 0.0f},
11967         { -1.0f, -1.0f, 0.0f, 0.0f},
11968         {  1.0f, -1.0f, 1.0f, 0.0f},
11969     };
11970
11971     IDirect3DPixelShader9 *ps;
11972     UINT body_size = 0;
11973     DWORD *vs_code;
11974     D3DCAPS9 caps;
11975     HRESULT hr;
11976     UINT i;
11977
11978     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11979     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
11980     if (caps.PixelShaderVersion < D3DPS_VERSION(2, 0) || caps.VertexShaderVersion < D3DVS_VERSION(2, 0))
11981     {
11982         skip("No shader model 2.0 support, skipping floating point specials test.\n");
11983         return;
11984     }
11985
11986     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE1(0));
11987     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
11988
11989     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code, &ps);
11990     ok(SUCCEEDED(hr), "CreatePixelShader failed, hr %#x.\n", hr);
11991     IDirect3DDevice9_SetPixelShader(device, ps);
11992     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
11993
11994     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
11995     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11996
11997     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
11998     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11999
12000     for (i = 0; i < sizeof(vs_body) / sizeof(*vs_body); ++i)
12001     {
12002         if (vs_body[i].size > body_size) body_size = vs_body[i].size;
12003     }
12004
12005     vs_code = HeapAlloc(GetProcessHeap(), 0, sizeof(vs_header) + body_size + sizeof(vs_footer));
12006     memcpy(vs_code, vs_header, sizeof(vs_header));
12007
12008     for (i = 0; i < sizeof(vs_body) / sizeof(*vs_body); ++i)
12009     {
12010         DWORD offset = sizeof(vs_header) / sizeof(*vs_header);
12011         IDirect3DVertexShader9 *vs;
12012         D3DCOLOR color;
12013
12014         memcpy(vs_code + offset, vs_body[i].ops, vs_body[i].size);
12015         offset += vs_body[i].size / sizeof(*vs_body[i].ops);
12016         memcpy(vs_code + offset, vs_footer, sizeof(vs_footer));
12017
12018         hr = IDirect3DDevice9_CreateVertexShader(device, vs_code, &vs);
12019         ok(SUCCEEDED(hr), "CreateVertexShader failed, hr %#x.\n", hr);
12020         IDirect3DDevice9_SetVertexShader(device, vs);
12021         ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
12022
12023         hr = IDirect3DDevice9_BeginScene(device);
12024         ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
12025         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
12026         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
12027         hr = IDirect3DDevice9_EndScene(device);
12028         ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
12029
12030         color = getPixelColor(device, 320, 240);
12031         ok(color_match(color, vs_body[i].r600, 1)
12032                 || color_match(color, vs_body[i].nv40, 1)
12033                 || color_match(color, vs_body[i].nv50, 1),
12034                 "Expected color 0x%08x, 0x%08x or 0x%08x for instruction \"%s\", got 0x%08x.\n",
12035                 vs_body[i].r600, vs_body[i].nv40, vs_body[i].nv50, vs_body[i].name, color);
12036
12037         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
12038         ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
12039
12040         hr = IDirect3DDevice9_SetVertexShader(device, NULL);
12041         ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
12042         IDirect3DVertexShader9_Release(vs);
12043     }
12044
12045     HeapFree(GetProcessHeap(), 0, vs_code);
12046
12047     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
12048     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
12049     IDirect3DPixelShader9_Release(ps);
12050 }
12051
12052 static void srgbwrite_format_test(IDirect3DDevice9 *device)
12053 {
12054     IDirect3D9 *d3d;
12055     IDirect3DSurface9 *rt, *backbuffer;
12056     IDirect3DTexture9 *texture;
12057     HRESULT hr;
12058     int i;
12059     DWORD color_rgb = 0x00808080, color_srgb = 0x00bcbcbc, color;
12060     static const struct
12061     {
12062         D3DFORMAT fmt;
12063         const char *name;
12064     }
12065     formats[] =
12066     {
12067         { D3DFMT_R5G6B5, "D3DFMT_R5G6B5" },
12068         { D3DFMT_X8R8G8B8, "D3DFMT_X8R8G8B8" },
12069         { D3DFMT_A8R8G8B8, "D3DFMT_A8R8G8B8" },
12070         { D3DFMT_A16B16G16R16F, "D3DFMT_A16B16G16R16F" },
12071         { D3DFMT_A32B32G32R32F, "D3DFMT_A32B32G32R32F" },
12072     };
12073     static const struct
12074     {
12075         float x, y, z;
12076         float u, v;
12077     }
12078     quad[] =
12079     {
12080         {-1.0f,  -1.0f,  0.1f,   0.0f,   0.0f},
12081         {-1.0f,   1.0f,  0.1f,   1.0f,   0.0f},
12082         { 1.0f,  -1.0f,  0.1f,   0.0f,   1.0f},
12083         { 1.0f,   1.0f,  0.1f,   1.0f,   1.0f}
12084     };
12085
12086     hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
12087     ok(SUCCEEDED(hr), "GetDirect3D failed, hr %#x.\n", hr);
12088     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
12089     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
12090     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
12091     ok(SUCCEEDED(hr), "GetBackBuffer failed, hr %#x.\n", hr);
12092     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
12093     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
12094     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0x80808080);
12095     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
12096
12097     for(i = 0; i < (sizeof(formats) / sizeof(*formats)); i++)
12098     {
12099         if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
12100                 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, formats[i].fmt)))
12101         {
12102             skip("Format %s not supported as render target, skipping test.\n",
12103                     formats[i].name);
12104             continue;
12105         }
12106
12107         hr = IDirect3DDevice9_CreateTexture(device, 8, 8, 1, D3DUSAGE_RENDERTARGET, formats[i].fmt,
12108                                             D3DPOOL_DEFAULT, &texture, NULL);
12109         ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
12110         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ff0000, 0.0f, 0);
12111         ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
12112
12113         hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &rt);
12114         ok(SUCCEEDED(hr), "GetSurfaceLevel failed, hr %#x.\n", hr);
12115         hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
12116         ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
12117         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
12118         ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
12119
12120         hr = IDirect3DDevice9_BeginScene(device);
12121         ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
12122         if(SUCCEEDED(hr))
12123         {
12124             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, TRUE);
12125             ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
12126             hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
12127             ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
12128             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
12129             ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
12130
12131             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, FALSE);
12132             ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
12133             hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
12134             ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
12135             hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
12136             ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
12137             hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
12138             ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
12139             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
12140             ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
12141             hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
12142             ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
12143
12144             hr = IDirect3DDevice9_EndScene(device);
12145             ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
12146         }
12147
12148         IDirect3DSurface9_Release(rt);
12149         IDirect3DTexture9_Release(texture);
12150
12151         color = getPixelColor(device, 360, 240);
12152         if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
12153                                     D3DUSAGE_QUERY_SRGBWRITE,
12154                                     D3DRTYPE_TEXTURE, formats[i].fmt) == D3D_OK)
12155         {
12156             /* Big slop for R5G6B5 */
12157             ok(color_match(color, color_srgb, 5), "Format %s supports srgb, expected color 0x%08x, got 0x%08x\n",
12158                 formats[i].name, color_srgb, color);
12159         }
12160         else
12161         {
12162             /* Big slop for R5G6B5 */
12163             ok(color_match(color, color_rgb, 5), "Format %s does not support srgb, expected color 0x%08x, got 0x%08x\n",
12164                 formats[i].name, color_rgb, color);
12165         }
12166
12167         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
12168         ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
12169     }
12170
12171     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
12172     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
12173
12174     IDirect3D9_Release(d3d);
12175     IDirect3DSurface9_Release(backbuffer);
12176 }
12177
12178 static void ds_size_test(IDirect3DDevice9 *device)
12179 {
12180     IDirect3DSurface9 *ds, *rt, *old_rt, *old_ds, *readback;
12181     HRESULT hr;
12182     DWORD num_passes;
12183     struct
12184     {
12185         float x, y, z;
12186     }
12187     quad[] =
12188     {
12189         {-1.0,  -1.0,   0.0 },
12190         {-1.0,   1.0,   0.0 },
12191         { 1.0,  -1.0,   0.0 },
12192         { 1.0,   1.0,   0.0 }
12193     };
12194
12195     hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
12196     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateRenderTarget failed, hr %#x.\n", hr);
12197     hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 32, 32, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, 0, TRUE, &ds, NULL);
12198     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateDepthStencilSurface failed, hr %#x.\n", hr);
12199     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &readback, NULL);
12200     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateOffscreenPlainSurface failed, hr %#x.\n", hr);
12201
12202     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
12203     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
12204     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
12205     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
12206     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
12207     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
12208     hr = IDirect3DDevice9_ValidateDevice(device, &num_passes);
12209     ok(SUCCEEDED(hr), "IDirect3DDevice9_ValidateDevice failed, hr %#x.\n", hr);
12210     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &old_rt);
12211     ok(SUCCEEDED(hr), "IDirect3DDevice9_GetRenderTarget failed, hr %#x.\n", hr);
12212     hr = IDirect3DDevice9_GetDepthStencilSurface(device, &old_ds);
12213     ok(SUCCEEDED(hr), "IDirect3DDevice9_GetDepthStencilSurface failed, hr %#x.\n", hr);
12214     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
12215     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderTarget failed, hr %#x.\n", hr);
12216     hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
12217     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetDepthStencilSurface failed, hr %#x.\n", hr);
12218     hr = IDirect3DDevice9_ValidateDevice(device, &num_passes);
12219     ok(SUCCEEDED(hr), "IDirect3DDevice9_ValidateDevice failed, hr %#x.\n", hr);
12220
12221     /* The D3DCLEAR_TARGET clear works. D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER returns OK,
12222      * but does not change the surface's contents. */
12223     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000FF, 0.0f, 0);
12224     ok(SUCCEEDED(hr), "Target clear failed, hr %#x.\n", hr);
12225     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 0.2f, 0);
12226     ok(SUCCEEDED(hr), "Z Buffer clear failed, hr %#x.\n", hr);
12227     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00ff0000, 0.5f, 0);
12228     ok(SUCCEEDED(hr), "Target and Z Buffer clear failed, hr %#x.\n", hr);
12229
12230     /* Nvidia does not clear the surface(The color is still 0x000000ff), AMD does(the color is 0x00ff0000) */
12231
12232     /* Turning on any depth-related state results in a ValidateDevice failure */
12233     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
12234     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
12235     hr = IDirect3DDevice9_ValidateDevice(device, &num_passes);
12236     ok(hr == D3DERR_CONFLICTINGRENDERSTATE || hr == D3D_OK, "IDirect3DDevice9_ValidateDevice returned %#x, expected "
12237         "D3DERR_CONFLICTINGRENDERSTATE.\n", hr);
12238     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
12239     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
12240     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
12241     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
12242     hr = IDirect3DDevice9_ValidateDevice(device, &num_passes);
12243     ok(hr == D3DERR_CONFLICTINGRENDERSTATE || hr == D3D_OK, "IDirect3DDevice9_ValidateDevice returned %#x, expected "
12244         "D3DERR_CONFLICTINGRENDERSTATE.\n", hr);
12245
12246     /* Try to draw with the device in an invalid state */
12247     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
12248     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetFVF failed, hr %#x.\n", hr);
12249     hr = IDirect3DDevice9_BeginScene(device);
12250     ok(SUCCEEDED(hr), "IDirect3DDevice9_BeginScene failed, hr %#x.\n", hr);
12251     if(SUCCEEDED(hr))
12252     {
12253         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
12254         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitiveUP failed, hr %#x.\n", hr);
12255         hr = IDirect3DDevice9_EndScene(device);
12256         ok(SUCCEEDED(hr), "IDirect3DDevice9_EndScene failed, hr %#x.\n", hr);
12257
12258         /* Don't check the resulting draw unless we find an app that needs it. On nvidia ValidateDevice
12259          * returns CONFLICTINGRENDERSTATE, so the result is undefined. On AMD d3d seems to assume the
12260          * stored Z buffer value is 0.0 for all pixels, even those that are covered by the depth buffer */
12261     }
12262
12263     hr = IDirect3DDevice9_SetRenderTarget(device, 0, old_rt);
12264     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderTarget failed, hr %#x.\n", hr);
12265     hr = IDirect3DDevice9_SetDepthStencilSurface(device, old_ds);
12266     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetDepthStencilSurface failed, hr %#x.\n", hr);
12267     hr = IDirect3DDevice9_ValidateDevice(device, &num_passes);
12268     ok(SUCCEEDED(hr), "IDirect3DDevice9_ValidateDevice failed, hr %#x.\n", hr);
12269
12270     IDirect3DSurface9_Release(readback);
12271     IDirect3DSurface9_Release(ds);
12272     IDirect3DSurface9_Release(rt);
12273     IDirect3DSurface9_Release(old_rt);
12274     IDirect3DSurface9_Release(old_ds);
12275 }
12276
12277 static void unbound_sampler_test(IDirect3DDevice9 *device)
12278 {
12279     HRESULT hr;
12280     IDirect3DPixelShader9 *ps, *ps_cube, *ps_volume;
12281     IDirect3DSurface9 *rt, *old_rt;
12282     DWORD color;
12283
12284     static const DWORD ps_code[] =
12285     {
12286         0xffff0200,                                     /* ps_2_0           */
12287         0x0200001f, 0x90000000, 0xa00f0800,             /* dcl_2d s0        */
12288         0x0200001f, 0x80000000, 0xb00f0000,             /* dcl t0           */
12289         0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, /* texld r0, t0, s0 */
12290         0x02000001, 0x800f0800, 0x80e40000,             /* mov oC0, r0      */
12291         0x0000ffff,                                     /* end              */
12292     };
12293     static const DWORD ps_code_cube[] =
12294     {
12295         0xffff0200,                                     /* ps_2_0           */
12296         0x0200001f, 0x98000000, 0xa00f0800,             /* dcl_cube s0      */
12297         0x0200001f, 0x80000000, 0xb00f0000,             /* dcl t0           */
12298         0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, /* texld r0, t0, s0 */
12299         0x02000001, 0x800f0800, 0x80e40000,             /* mov oC0, r0      */
12300         0x0000ffff,                                     /* end              */
12301     };
12302     static const DWORD ps_code_volume[] =
12303     {
12304         0xffff0200,                                     /* ps_2_0           */
12305         0x0200001f, 0xa0000000, 0xa00f0800,             /* dcl_volume s0    */
12306         0x0200001f, 0x80000000, 0xb00f0000,             /* dcl t0           */
12307         0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, /* texld r0, t0, s0 */
12308         0x02000001, 0x800f0800, 0x80e40000,             /* mov oC0, r0      */
12309         0x0000ffff,                                     /* end              */
12310     };
12311
12312     static const struct
12313     {
12314         float x, y, z;
12315         float u, v;
12316     }
12317     quad[] =
12318     {
12319         {-1.0f,  -1.0f,  0.1f,   0.0f,   0.0f},
12320         {-1.0f,   1.0f,  0.1f,   1.0f,   0.0f},
12321         { 1.0f,  -1.0f,  0.1f,   0.0f,   1.0f},
12322         { 1.0f,   1.0f,  0.1f,   1.0f,   1.0f}
12323     };
12324
12325     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
12326     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStage failed, %#x.\n", hr);
12327
12328     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code, &ps);
12329     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreatePixelShader failed, hr %#x.\n", hr);
12330     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code_cube, &ps_cube);
12331     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreatePixelShader failed, hr %#x.\n", hr);
12332     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code_volume, &ps_volume);
12333     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreatePixelShader failed, hr %#x.\n", hr);
12334
12335     hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &rt, NULL);
12336     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateRenderTarget failed, hr %#x.\n", hr);
12337
12338     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &old_rt);
12339     ok(SUCCEEDED(hr), "IDirect3DDevice9_GetRenderTarget failed, hr %#x.\n", hr);
12340
12341     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
12342     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderTarget failed, hr %#x.\n", hr);
12343
12344     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 );
12345     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetFVF failed, hr %#x.\n", hr);
12346
12347     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x56ffffff, 0, 0);
12348     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed, hr %#x.\n", hr);
12349
12350     hr = IDirect3DDevice9_SetPixelShader(device, ps);
12351     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetPixelShader failed, hr %#x.\n", hr);
12352
12353     hr = IDirect3DDevice9_BeginScene(device);
12354     ok(SUCCEEDED(hr), "IDirect3DDevice9_BeginScene failed, hr %#x.\n", hr);
12355     if(SUCCEEDED(hr))
12356     {
12357         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
12358         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitiveUP failed, hr %#x.\n", hr);
12359
12360         hr = IDirect3DDevice9_EndScene(device);
12361         ok(SUCCEEDED(hr), "IDirect3DDevice9_EndScene failed, hr %#x.\n", hr);
12362     }
12363
12364     color = getPixelColorFromSurface(rt, 32, 32);
12365     ok(color == 0xff000000, "Unbound sampler color is %#x.\n", color);
12366
12367     /* Now try with a cube texture */
12368     hr = IDirect3DDevice9_SetPixelShader(device, ps_cube);
12369     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetPixelShader failed, hr %#x.\n", hr);
12370
12371     hr = IDirect3DDevice9_BeginScene(device);
12372     ok(SUCCEEDED(hr), "IDirect3DDevice9_BeginScene failed, hr %#x.\n", hr);
12373     if (SUCCEEDED(hr))
12374     {
12375         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
12376         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitiveUP failed, hr %#x.\n", hr);
12377
12378         hr = IDirect3DDevice9_EndScene(device);
12379         ok(SUCCEEDED(hr), "IDirect3DDevice9_EndScene failed, hr %#x.\n", hr);
12380     }
12381
12382     color = getPixelColorFromSurface(rt, 32, 32);
12383     ok(color == 0xff000000, "Unbound sampler color is %#x.\n", color);
12384
12385     /* And then with a volume texture */
12386     hr = IDirect3DDevice9_SetPixelShader(device, ps_volume);
12387     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetPixelShader failed, hr %#x.\n", hr);
12388
12389     hr = IDirect3DDevice9_BeginScene(device);
12390     ok(SUCCEEDED(hr), "IDirect3DDevice9_BeginScene failed, hr %#x.\n", hr);
12391     if (SUCCEEDED(hr))
12392     {
12393         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
12394         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitiveUP failed, hr %#x.\n", hr);
12395
12396         hr = IDirect3DDevice9_EndScene(device);
12397         ok(SUCCEEDED(hr), "IDirect3DDevice9_EndScene failed, hr %#x.\n", hr);
12398     }
12399
12400     color = getPixelColorFromSurface(rt, 32, 32);
12401     ok(color == 0xff000000, "Unbound sampler color is %#x.\n", color);
12402
12403     hr = IDirect3DDevice9_SetRenderTarget(device, 0, old_rt);
12404     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderTarget failed, hr %#x.\n", hr);
12405
12406     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
12407     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetPixelShader failed, hr %#x.\n", hr);
12408
12409     IDirect3DSurface9_Release(rt);
12410     IDirect3DSurface9_Release(old_rt);
12411     IDirect3DPixelShader9_Release(ps);
12412     IDirect3DPixelShader9_Release(ps_cube);
12413     IDirect3DPixelShader9_Release(ps_volume);
12414 }
12415
12416 static void update_surface_test(IDirect3DDevice9 *device)
12417 {
12418     static const BYTE blocks[][8] =
12419     {
12420         {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}, /* White */
12421         {0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00}, /* Red */
12422         {0xe0, 0xff, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00}, /* Yellow */
12423         {0xe0, 0x07, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00}, /* Green */
12424         {0xff, 0x07, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00}, /* Cyan */
12425         {0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00}, /* Blue */
12426         {0x1f, 0xf8, 0x1f, 0xf8, 0x00, 0x00, 0x00, 0x00}, /* Magenta */
12427     };
12428     static const struct
12429     {
12430         UINT x, y;
12431         D3DCOLOR color;
12432     }
12433     expected_colors[] =
12434     {
12435         { 18, 240, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0xff)},
12436         { 57, 240, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xff)},
12437         {109, 240, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0xff)},
12438         {184, 240, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
12439         {290, 240, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00)},
12440         {440, 240, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00)},
12441         {584, 240, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0xff)},
12442     };
12443     static const struct
12444     {
12445         float x, y, z, w;
12446         float u, v;
12447     }
12448     tri[] =
12449     {
12450         {  0.0f, 480.0f, 0.0f,  1.0f,   0.0f, 0.0f},
12451         {  0.0f,   0.0f, 0.0f,  1.0f,   0.0f, 1.0f},
12452         {640.0f, 240.0f, 0.0f, 10.0f, 100.0f, 0.5f},
12453     };
12454     static const RECT rect_2x2 = {0, 0, 2, 2};
12455     static const struct
12456     {
12457         UINT src_level;
12458         UINT dst_level;
12459         const RECT *r;
12460         HRESULT hr;
12461     }
12462     block_size_tests[] =
12463     {
12464         {1, 0, NULL,      D3D_OK},
12465         {0, 1, NULL,      D3DERR_INVALIDCALL},
12466         {5, 4, NULL,      D3DERR_INVALIDCALL},
12467         {4, 5, NULL,      D3DERR_INVALIDCALL},
12468         {4, 5, &rect_2x2, D3DERR_INVALIDCALL},
12469         {5, 5, &rect_2x2, D3D_OK},
12470     };
12471
12472     IDirect3DSurface9 *src_surface, *dst_surface;
12473     IDirect3DTexture9 *src_tex, *dst_tex;
12474     IDirect3D9 *d3d;
12475     UINT count, i;
12476     HRESULT hr;
12477
12478     hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
12479     ok(SUCCEEDED(hr), "GetDirect3D failed, hr %#x.\n", hr);
12480
12481     hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12482             D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1);
12483     IDirect3D9_Release(d3d);
12484     if (FAILED(hr))
12485     {
12486         skip("DXT1 not supported, skipping test.\n");
12487         return;
12488     }
12489
12490     IDirect3D9_Release(d3d);
12491
12492     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0, D3DFMT_DXT1, D3DPOOL_SYSTEMMEM, &src_tex, NULL);
12493     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
12494     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0, D3DFMT_DXT1, D3DPOOL_DEFAULT, &dst_tex, NULL);
12495     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
12496
12497     count = IDirect3DTexture9_GetLevelCount(src_tex);
12498     ok(count == 7, "Got level count %u, expected 7.\n", count);
12499
12500     for (i = 0; i < count; ++i)
12501     {
12502         UINT row_count, block_count, x, y;
12503         D3DSURFACE_DESC desc;
12504         BYTE *row, *block;
12505         D3DLOCKED_RECT r;
12506
12507         hr = IDirect3DTexture9_GetLevelDesc(src_tex, i, &desc);
12508         ok(SUCCEEDED(hr), "Failed to get level desc, hr %#x.\n", hr);
12509
12510         hr = IDirect3DTexture9_LockRect(src_tex, i, &r, NULL, 0);
12511         ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
12512
12513         row_count = ((desc.Height + 3) & ~3) / 4;
12514         block_count = ((desc.Width + 3) & ~3) / 4;
12515         row = r.pBits;
12516
12517         for (y = 0; y < row_count; ++y)
12518         {
12519             block = row;
12520             for (x = 0; x < block_count; ++x)
12521             {
12522                 memcpy(block, blocks[i], sizeof(blocks[i]));
12523                 block += sizeof(blocks[i]);
12524             }
12525             row += r.Pitch;
12526         }
12527
12528         hr = IDirect3DTexture9_UnlockRect(src_tex, i);
12529         ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
12530     }
12531
12532     for (i = 0; i < sizeof(block_size_tests) / sizeof(*block_size_tests); ++i)
12533     {
12534         hr = IDirect3DTexture9_GetSurfaceLevel(src_tex, block_size_tests[i].src_level, &src_surface);
12535         ok(SUCCEEDED(hr), "Failed to get texture surface, hr %#x.\n", hr);
12536         hr = IDirect3DTexture9_GetSurfaceLevel(dst_tex, block_size_tests[i].dst_level, &dst_surface);
12537         ok(SUCCEEDED(hr), "Failed to get texture surface, hr %#x.\n", hr);
12538
12539         hr = IDirect3DDevice9_UpdateSurface(device, src_surface, block_size_tests[i].r, dst_surface, NULL);
12540         ok(hr == block_size_tests[i].hr, "Update surface returned %#x for test %u, expected %#x.\n",
12541                 hr, i, block_size_tests[i].hr);
12542
12543         IDirect3DSurface9_Release(dst_surface);
12544         IDirect3DSurface9_Release(src_surface);
12545     }
12546
12547     for (i = 0; i < count; ++i)
12548     {
12549         hr = IDirect3DTexture9_GetSurfaceLevel(src_tex, i, &src_surface);
12550         ok(SUCCEEDED(hr), "Failed to get texture surface, hr %#x.\n", hr);
12551         hr = IDirect3DTexture9_GetSurfaceLevel(dst_tex, i, &dst_surface);
12552         ok(SUCCEEDED(hr), "Failed to get texture surface, hr %#x.\n", hr);
12553
12554         hr = IDirect3DDevice9_UpdateSurface(device, src_surface, NULL, dst_surface, NULL);
12555         ok(SUCCEEDED(hr), "Failed to update surface at level %u, hr %#x.\n", i, hr);
12556
12557         IDirect3DSurface9_Release(dst_surface);
12558         IDirect3DSurface9_Release(src_surface);
12559     }
12560
12561     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
12562     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
12563     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
12564     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
12565     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_TEX1);
12566     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
12567     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)dst_tex);
12568     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
12569     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
12570     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
12571     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
12572     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
12573
12574     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0f, 0);
12575     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
12576
12577     hr = IDirect3DDevice9_BeginScene(device);
12578     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
12579     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 1, tri, sizeof(*tri));
12580     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
12581     hr = IDirect3DDevice9_EndScene(device);
12582     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
12583
12584     for (i = 0; i < sizeof(expected_colors) / sizeof(*expected_colors); ++i)
12585     {
12586         D3DCOLOR color = getPixelColor(device, expected_colors[i].x, expected_colors[i].y);
12587         ok(color_match(color, expected_colors[i].color, 0),
12588                 "Expected color 0x%08x at (%u, %u), got 0x%08x.\n",
12589                 expected_colors[i].color, expected_colors[i].x, expected_colors[i].y, color);
12590     }
12591
12592     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
12593     ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
12594
12595     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
12596     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
12597     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
12598     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
12599     IDirect3DTexture9_Release(dst_tex);
12600     IDirect3DTexture9_Release(src_tex);
12601 }
12602
12603 START_TEST(visual)
12604 {
12605     IDirect3DDevice9 *device_ptr;
12606     D3DCAPS9 caps;
12607     HRESULT hr;
12608     DWORD color;
12609
12610     d3d9_handle = LoadLibraryA("d3d9.dll");
12611     if (!d3d9_handle)
12612     {
12613         skip("Could not load d3d9.dll\n");
12614         return;
12615     }
12616
12617     device_ptr = init_d3d9();
12618     if (!device_ptr)
12619     {
12620         skip("Creating the device failed\n");
12621         return;
12622     }
12623
12624     IDirect3DDevice9_GetDeviceCaps(device_ptr, &caps);
12625
12626     /* Check for the reliability of the returned data */
12627     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
12628     if(FAILED(hr))
12629     {
12630         skip("Clear failed, can't assure correctness of the test results, skipping\n");
12631         goto cleanup;
12632     }
12633
12634     color = getPixelColor(device_ptr, 1, 1);
12635     if(color !=0x00ff0000)
12636     {
12637         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
12638         goto cleanup;
12639     }
12640     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
12641
12642     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xff00ddee, 0.0, 0);
12643     if(FAILED(hr))
12644     {
12645         skip("Clear failed, can't assure correctness of the test results, skipping\n");
12646         goto cleanup;
12647     }
12648
12649     color = getPixelColor(device_ptr, 639, 479);
12650     if(color != 0x0000ddee)
12651     {
12652         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
12653         goto cleanup;
12654     }
12655     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
12656
12657     /* Now execute the real tests */
12658     depth_clamp_test(device_ptr);
12659     stretchrect_test(device_ptr);
12660     lighting_test(device_ptr);
12661     clear_test(device_ptr);
12662     color_fill_test(device_ptr);
12663     fog_test(device_ptr);
12664     if(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
12665     {
12666         test_cube_wrap(device_ptr);
12667     } else {
12668         skip("No cube texture support\n");
12669     }
12670     z_range_test(device_ptr);
12671     if(caps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)
12672     {
12673         maxmip_test(device_ptr);
12674     }
12675     else
12676     {
12677         skip("No mipmap support\n");
12678     }
12679     offscreen_test(device_ptr);
12680     ds_size_test(device_ptr);
12681     alpha_test(device_ptr);
12682     shademode_test(device_ptr);
12683     srgbtexture_test(device_ptr);
12684     release_buffer_test(device_ptr);
12685     float_texture_test(device_ptr);
12686     g16r16_texture_test(device_ptr);
12687     pixelshader_blending_test(device_ptr);
12688     texture_transform_flags_test(device_ptr);
12689     autogen_mipmap_test(device_ptr);
12690     fixed_function_decl_test(device_ptr);
12691     conditional_np2_repeat_test(device_ptr);
12692     fixed_function_bumpmap_test(device_ptr);
12693     if(caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) {
12694         stencil_cull_test(device_ptr);
12695     } else {
12696         skip("No two sided stencil support\n");
12697     }
12698     pointsize_test(device_ptr);
12699     tssargtemp_test(device_ptr);
12700     np2_stretch_rect_test(device_ptr);
12701     yuv_color_test(device_ptr);
12702     zwriteenable_test(device_ptr);
12703     alphatest_test(device_ptr);
12704     viewport_test(device_ptr);
12705
12706     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1))
12707     {
12708         test_constant_clamp_vs(device_ptr);
12709         test_compare_instructions(device_ptr);
12710     }
12711     else skip("No vs_1_1 support\n");
12712
12713     if (caps.VertexShaderVersion >= D3DVS_VERSION(2, 0))
12714     {
12715         test_mova(device_ptr);
12716         loop_index_test(device_ptr);
12717         sincos_test(device_ptr);
12718         sgn_test(device_ptr);
12719         if (caps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) {
12720             test_vshader_input(device_ptr);
12721             test_vshader_float16(device_ptr);
12722             stream_test(device_ptr);
12723         } else {
12724             skip("No vs_3_0 support\n");
12725         }
12726     }
12727     else skip("No vs_2_0 support\n");
12728
12729     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1) && caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
12730     {
12731         fog_with_shader_test(device_ptr);
12732     }
12733     else skip("No vs_1_1 and ps_1_1 support\n");
12734
12735     if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
12736     {
12737         texbem_test(device_ptr);
12738         texdepth_test(device_ptr);
12739         texkill_test(device_ptr);
12740         x8l8v8u8_test(device_ptr);
12741         if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 4)) {
12742             constant_clamp_ps_test(device_ptr);
12743             cnd_test(device_ptr);
12744             if (caps.PixelShaderVersion >= D3DPS_VERSION(2, 0)) {
12745                 dp2add_ps_test(device_ptr);
12746                 unbound_sampler_test(device_ptr);
12747                 if (caps.PixelShaderVersion >= D3DPS_VERSION(3, 0) && caps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) {
12748                     nested_loop_test(device_ptr);
12749                     pretransformed_varying_test(device_ptr);
12750                     vFace_register_test(device_ptr);
12751                     vpos_register_test(device_ptr);
12752                     multiple_rendertargets_test(device_ptr);
12753                 } else {
12754                     skip("No ps_3_0 or vs_3_0 support\n");
12755                 }
12756             } else {
12757                 skip("No ps_2_0 support\n");
12758             }
12759         }
12760     }
12761     else skip("No ps_1_1 support\n");
12762
12763     texop_test(device_ptr);
12764     texop_range_test(device_ptr);
12765     alphareplicate_test(device_ptr);
12766     dp3_alpha_test(device_ptr);
12767     depth_buffer_test(device_ptr);
12768     depth_buffer2_test(device_ptr);
12769     depth_blit_test(device_ptr);
12770     intz_test(device_ptr);
12771     shadow_test(device_ptr);
12772     fp_special_test(device_ptr);
12773     depth_bounds_test(device_ptr);
12774     srgbwrite_format_test(device_ptr);
12775     clip_planes_test(device_ptr);
12776     update_surface_test(device_ptr);
12777
12778 cleanup:
12779     if(device_ptr) {
12780         D3DPRESENT_PARAMETERS present_parameters;
12781         IDirect3DSwapChain9 *swapchain;
12782         ULONG ref;
12783
12784         IDirect3DDevice9_GetSwapChain(device_ptr, 0, &swapchain);
12785         IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters);
12786         IDirect3DSwapChain9_Release(swapchain);
12787         ref = IDirect3DDevice9_Release(device_ptr);
12788         ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
12789         DestroyWindow(present_parameters.hDeviceWindow);
12790     }
12791 }