comctl32/tests: Destroy the window after the tests.
[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_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
47     return ret;
48 }
49
50 static BOOL color_match(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
51 {
52     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
53     c1 >>= 8; c2 >>= 8;
54     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
55     c1 >>= 8; c2 >>= 8;
56     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
57     c1 >>= 8; c2 >>= 8;
58     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
59     return TRUE;
60 }
61
62 /* Locks a given surface and returns the color at (x,y).  It's the caller's
63  * responsibility to only pass in lockable surfaces and valid x,y coordinates */
64 static DWORD getPixelColorFromSurface(IDirect3DSurface9 *surface, UINT x, UINT y)
65 {
66     DWORD color;
67     HRESULT hr;
68     D3DSURFACE_DESC desc;
69     RECT rectToLock = {x, y, x+1, y+1};
70     D3DLOCKED_RECT lockedRect;
71
72     hr = IDirect3DSurface9_GetDesc(surface, &desc);
73     if(FAILED(hr))  /* This is not a test */
74     {
75         trace("Can't get the surface description, hr=%08x\n", hr);
76         return 0xdeadbeef;
77     }
78
79     hr = IDirect3DSurface9_LockRect(surface, &lockedRect, &rectToLock, D3DLOCK_READONLY);
80     if(FAILED(hr))  /* This is not a test */
81     {
82         trace("Can't lock the surface, hr=%08x\n", hr);
83         return 0xdeadbeef;
84     }
85     switch(desc.Format) {
86         case D3DFMT_A8R8G8B8:
87         {
88             color = ((DWORD *) lockedRect.pBits)[0] & 0xffffffff;
89             break;
90         }
91         default:
92             trace("Error: unknown surface format: %d\n", desc.Format);
93             color = 0xdeadbeef;
94             break;
95     }
96     hr = IDirect3DSurface9_UnlockRect(surface);
97     if(FAILED(hr))
98     {
99         trace("Can't unlock the surface, hr=%08x\n", hr);
100     }
101     return color;
102 }
103
104 static DWORD getPixelColor(IDirect3DDevice9 *device, UINT x, UINT y)
105 {
106     DWORD ret;
107     IDirect3DSurface9 *surf;
108     HRESULT hr;
109     D3DLOCKED_RECT lockedRect;
110     RECT rectToLock = {x, y, x+1, y+1};
111
112     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 640, 480, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL);
113     if(FAILED(hr) || !surf )  /* This is not a test */
114     {
115         trace("Can't create an offscreen plain surface to read the render target data, hr=%08x\n", hr);
116         return 0xdeadbeef;
117     }
118
119     hr = IDirect3DDevice9_GetFrontBufferData(device, 0, surf);
120     if(FAILED(hr))
121     {
122         trace("Can't read the front buffer data, hr=%08x\n", hr);
123         ret = 0xdeadbeed;
124         goto out;
125     }
126
127     hr = IDirect3DSurface9_LockRect(surf, &lockedRect, &rectToLock, D3DLOCK_READONLY);
128     if(FAILED(hr))
129     {
130         trace("Can't lock the offscreen surface, hr=%08x\n", hr);
131         ret = 0xdeadbeec;
132         goto out;
133     }
134
135     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
136      * really important for these tests
137      */
138     ret = ((DWORD *) lockedRect.pBits)[0] & 0x00ffffff;
139     hr = IDirect3DSurface9_UnlockRect(surf);
140     if(FAILED(hr))
141     {
142         trace("Can't unlock the offscreen surface, hr=%08x\n", hr);
143     }
144
145 out:
146     if(surf) IDirect3DSurface9_Release(surf);
147     return ret;
148 }
149
150 static IDirect3DDevice9 *init_d3d9(void)
151 {
152     IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion) = 0;
153     IDirect3D9 *d3d9_ptr = 0;
154     IDirect3DDevice9 *device_ptr = 0;
155     D3DPRESENT_PARAMETERS present_parameters;
156     HRESULT hr;
157     D3DADAPTER_IDENTIFIER9 identifier;
158
159     d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
160     ok(d3d9_create != NULL, "Failed to get address of Direct3DCreate9\n");
161     if (!d3d9_create) return NULL;
162
163     d3d9_ptr = d3d9_create(D3D_SDK_VERSION);
164     if (!d3d9_ptr)
165     {
166         skip("could not create D3D9\n");
167         return NULL;
168     }
169
170     ZeroMemory(&present_parameters, sizeof(present_parameters));
171     present_parameters.Windowed = FALSE;
172     present_parameters.hDeviceWindow = create_window();
173     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
174     present_parameters.BackBufferWidth = 640;
175     present_parameters.BackBufferHeight = 480;
176     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
177     present_parameters.EnableAutoDepthStencil = TRUE;
178     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
179
180     memset(&identifier, 0, sizeof(identifier));
181     hr = IDirect3D9_GetAdapterIdentifier(d3d9_ptr, 0, 0, &identifier);
182     ok(hr == D3D_OK, "Failed to get adapter identifier description\n");
183     trace("Driver string: \"%s\"\n", identifier.Driver);
184     trace("Description string: \"%s\"\n", identifier.Description);
185     trace("Device name string: \"%s\"\n", identifier.DeviceName);
186     trace("Driver version %d.%d.%d.%d\n",
187           HIWORD(U(identifier.DriverVersion).HighPart), LOWORD(U(identifier.DriverVersion).HighPart),
188           HIWORD(U(identifier.DriverVersion).LowPart), LOWORD(U(identifier.DriverVersion).LowPart));
189
190     hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
191     if(FAILED(hr)) {
192         present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
193         hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
194         if(FAILED(hr)) {
195             hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
196         }
197     }
198     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D_CreateDevice returned: %08x\n", hr);
199
200     return device_ptr;
201 }
202
203 struct vertex
204 {
205     float x, y, z;
206     DWORD diffuse;
207 };
208
209 struct tvertex
210 {
211     float x, y, z, rhw;
212     DWORD diffuse;
213 };
214
215 struct nvertex
216 {
217     float x, y, z;
218     float nx, ny, nz;
219     DWORD diffuse;
220 };
221
222 static void lighting_test(IDirect3DDevice9 *device)
223 {
224     HRESULT hr;
225     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
226     DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
227     DWORD color;
228     D3DMATERIAL9 material, old_material;
229     DWORD cop, carg;
230
231     float mat[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
232                       0.0f, 1.0f, 0.0f, 0.0f,
233                       0.0f, 0.0f, 1.0f, 0.0f,
234                       0.0f, 0.0f, 0.0f, 1.0f };
235
236     struct vertex unlitquad[] =
237     {
238         {-1.0f, -1.0f,   0.1f,                          0xffff0000},
239         {-1.0f,  0.0f,   0.1f,                          0xffff0000},
240         { 0.0f,  0.0f,   0.1f,                          0xffff0000},
241         { 0.0f, -1.0f,   0.1f,                          0xffff0000},
242     };
243     struct vertex litquad[] =
244     {
245         {-1.0f,  0.0f,   0.1f,                          0xff00ff00},
246         {-1.0f,  1.0f,   0.1f,                          0xff00ff00},
247         { 0.0f,  1.0f,   0.1f,                          0xff00ff00},
248         { 0.0f,  0.0f,   0.1f,                          0xff00ff00},
249     };
250     struct nvertex unlitnquad[] =
251     {
252         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
253         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
254         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
255         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
256     };
257     struct nvertex litnquad[] =
258     {
259         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
260         { 0.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
261         { 1.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
262         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
263     };
264     WORD Indices[] = {0, 1, 2, 2, 3, 0};
265
266     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
267     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
268
269     /* Setup some states that may cause issues */
270     hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(0), (D3DMATRIX *) mat);
271     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %08x\n", hr);
272     hr = IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, (D3DMATRIX *)mat);
273     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %08x\n", hr);
274     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, (D3DMATRIX *) mat);
275     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %08x\n", hr);
276     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
277     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
278     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
279     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
280     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
281     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
282     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
283     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
284     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, FALSE);
285     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
286     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
287     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
288     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, FALSE);
289     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
290     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
291     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
292     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
293     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
294
295     hr = IDirect3DDevice9_SetFVF(device, fvf);
296     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
297
298     hr = IDirect3DDevice9_BeginScene(device);
299     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
300     if(hr == D3D_OK)
301     {
302         /* No lights are defined... That means, lit vertices should be entirely black */
303         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
304         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
305         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
306                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitquad, sizeof(unlitquad[0]));
307         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
308
309         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
310         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
311         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
312                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litquad, sizeof(litquad[0]));
313         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
314
315         hr = IDirect3DDevice9_SetFVF(device, nfvf);
316         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
317
318         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
319         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
320         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
321                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitnquad, sizeof(unlitnquad[0]));
322         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
323
324         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
325         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
326         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
327                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litnquad, sizeof(litnquad[0]));
328         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
329
330         IDirect3DDevice9_EndScene(device);
331         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
332     }
333
334     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
335
336     color = getPixelColor(device, 160, 360); /* lower left quad - unlit without normals */
337     ok(color == 0x00ff0000, "Unlit quad without normals has color %08x\n", color);
338     color = getPixelColor(device, 160, 120); /* upper left quad - lit without normals */
339     ok(color == 0x00000000, "Lit quad without normals has color %08x\n", color);
340     color = getPixelColor(device, 480, 360); /* lower left quad - unlit with normals */
341     ok(color == 0x000000ff, "Unlit quad with normals has color %08x\n", color);
342     color = getPixelColor(device, 480, 120); /* upper left quad - lit with normals */
343     ok(color == 0x00000000, "Lit quad with normals has color %08x\n", color);
344
345     hr = IDirect3DDevice9_GetMaterial(device, &old_material);
346     ok(hr == D3D_OK, "IDirect3DDevice9_GetMaterial returned %08x\n", hr);
347     memset(&material, 0, sizeof(material));
348     material.Diffuse.r = 0.0;
349     material.Diffuse.g = 0.0;
350     material.Diffuse.b = 0.0;
351     material.Diffuse.a = 1.0;
352     material.Ambient.r = 0.0;
353     material.Ambient.g = 0.0;
354     material.Ambient.b = 0.0;
355     material.Ambient.a = 0.0;
356     material.Specular.r = 0.0;
357     material.Specular.g = 0.0;
358     material.Specular.b = 0.0;
359     material.Specular.a = 0.0;
360     material.Emissive.r = 0.0;
361     material.Emissive.g = 0.0;
362     material.Emissive.b = 0.0;
363     material.Emissive.a = 0.0;
364     material.Power = 0.0;
365     IDirect3DDevice9_SetMaterial(device, &material);
366     ok(hr == D3D_OK, "IDirect3DDevice9_SetMaterial returned %08x\n", hr);
367
368     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
369     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
370     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
371     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
372
373     hr = IDirect3DDevice9_GetTextureStageState(device, 0, D3DTSS_COLOROP, &cop);
374     ok(hr == D3D_OK, "IDirect3DDevice9_GetTextureStageState returned %08x\n", hr);
375     hr = IDirect3DDevice9_GetTextureStageState(device, 0, D3DTSS_COLORARG1, &carg);
376     ok(hr == D3D_OK, "IDirect3DDevice9_GetTextureStageState returned %08x\n", hr);
377     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
378     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
379     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE | D3DTA_ALPHAREPLICATE);
380     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
381
382     hr = IDirect3DDevice9_BeginScene(device);
383     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
384     if(SUCCEEDED(hr)) {
385         struct vertex lighting_test[] = {
386             {-1.0,   -1.0,   0.1,    0x8000ff00},
387             { 1.0,   -1.0,   0.1,    0x80000000},
388             {-1.0,    1.0,   0.1,    0x8000ff00},
389             { 1.0,    1.0,   0.1,    0x80000000}
390         };
391         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
392         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr=%08x\n", hr);
393         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, lighting_test, sizeof(lighting_test[0]));
394         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
395
396         hr = IDirect3DDevice9_EndScene(device);
397         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
398     }
399
400     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
401     color = getPixelColor(device, 320, 240);
402     ok(color == 0x00ffffff, "Lit vertex alpha test returned color %08x, expected 0x00ffffff\n", color);
403
404     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, cop);
405     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
406     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
407     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
408     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
409     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
410     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
411     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
412     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, carg);
413     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
414     hr = IDirect3DDevice9_SetMaterial(device, &old_material);
415     ok(hr == D3D_OK, "IDirect3DDevice9_SetMaterial returned %08x\n", hr);
416 }
417
418 static void clear_test(IDirect3DDevice9 *device)
419 {
420     /* Tests the correctness of clearing parameters */
421     HRESULT hr;
422     D3DRECT rect[2];
423     D3DRECT rect_negneg;
424     DWORD color;
425     D3DVIEWPORT9 old_vp, vp;
426     RECT scissor;
427     DWORD oldColorWrite;
428     BOOL invalid_clear_failed = FALSE;
429
430     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
431     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
432
433     /* Positive x, negative y */
434     rect[0].x1 = 0;
435     rect[0].y1 = 480;
436     rect[0].x2 = 320;
437     rect[0].y2 = 240;
438
439     /* Positive x, positive y */
440     rect[1].x1 = 0;
441     rect[1].y1 = 0;
442     rect[1].x2 = 320;
443     rect[1].y2 = 240;
444     /* Clear 2 rectangles with one call. The refrast returns an error in this case, every real driver tested so far
445      * returns D3D_OK, but ignores the rectangle silently
446      */
447     hr = IDirect3DDevice9_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
448     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
449     if(hr == D3DERR_INVALIDCALL) invalid_clear_failed = TRUE;
450
451     /* negative x, negative y */
452     rect_negneg.x1 = 640;
453     rect_negneg.y1 = 240;
454     rect_negneg.x2 = 320;
455     rect_negneg.y2 = 0;
456     hr = IDirect3DDevice9_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
457     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
458     if(hr == D3DERR_INVALIDCALL) invalid_clear_failed = TRUE;
459
460     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
461
462     color = getPixelColor(device, 160, 360); /* lower left quad */
463     ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
464     color = getPixelColor(device, 160, 120); /* upper left quad */
465     if(invalid_clear_failed) {
466         /* If the negative rectangle was refused, the other rectangles in the list shouldn't be cleared either */
467         ok(color == 0x00ffffff, "Clear rectangle 1(pos, pos) has color %08x\n", color);
468     } else {
469         /* If the negative rectangle was dropped silently, the correct ones are cleared */
470         ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
471     }
472     color = getPixelColor(device, 480, 360); /* lower right quad  */
473     ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
474     color = getPixelColor(device, 480, 120); /* upper right quad */
475     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
476
477     /* Test how the viewport affects clears */
478     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
479     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
480     hr = IDirect3DDevice9_GetViewport(device, &old_vp);
481     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
482
483     vp.X = 160;
484     vp.Y = 120;
485     vp.Width = 160;
486     vp.Height = 120;
487     vp.MinZ = 0.0;
488     vp.MaxZ = 1.0;
489     hr = IDirect3DDevice9_SetViewport(device, &vp);
490     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
491     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
492     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
493
494     vp.X = 320;
495     vp.Y = 240;
496     vp.Width = 320;
497     vp.Height = 240;
498     vp.MinZ = 0.0;
499     vp.MaxZ = 1.0;
500     hr = IDirect3DDevice9_SetViewport(device, &vp);
501     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
502     rect[0].x1 = 160;
503     rect[0].y1 = 120;
504     rect[0].x2 = 480;
505     rect[0].y2 = 360;
506     hr = IDirect3DDevice9_Clear(device, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
507     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
508
509     hr = IDirect3DDevice9_SetViewport(device, &old_vp);
510     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
511
512     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
513     color = getPixelColor(device, 158, 118);
514     ok(color == 0x00ffffff, "(158,118) has color %08x\n", color);
515     color = getPixelColor(device, 162, 118);
516     ok(color == 0x00ffffff, "(162,118) has color %08x\n", color);
517     color = getPixelColor(device, 158, 122);
518     ok(color == 0x00ffffff, "(158,122) has color %08x\n", color);
519     color = getPixelColor(device, 162, 122);
520     ok(color == 0x000000ff, "(162,122) has color %08x\n", color);
521
522     color = getPixelColor(device, 318, 238);
523     ok(color == 0x000000ff, "(318,238) has color %08x\n", color);
524     color = getPixelColor(device, 322, 238);
525     ok(color == 0x00ffffff, "(322,328) has color %08x\n", color);
526     color = getPixelColor(device, 318, 242);
527     ok(color == 0x00ffffff, "(318,242) has color %08x\n", color);
528     color = getPixelColor(device, 322, 242);
529     ok(color == 0x0000ff00, "(322,242) has color %08x\n", color);
530
531     color = getPixelColor(device, 478, 358);
532     ok(color == 0x0000ff00, "(478,358 has color %08x\n", color);
533     color = getPixelColor(device, 482, 358);
534     ok(color == 0x00ffffff, "(482,358) has color %08x\n", color);
535     color = getPixelColor(device, 478, 362);
536     ok(color == 0x00ffffff, "(478,362) has color %08x\n", color);
537     color = getPixelColor(device, 482, 362);
538     ok(color == 0x00ffffff, "(482,362) has color %08x\n", color);
539
540     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
541     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
542
543     scissor.left = 160;
544     scissor.right = 480;
545     scissor.top = 120;
546     scissor.bottom = 360;
547     hr = IDirect3DDevice9_SetScissorRect(device, &scissor);
548     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %08x\n", hr);
549     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, TRUE);
550     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %08x\n", hr);
551
552     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
553     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
554     hr = IDirect3DDevice9_Clear(device, 1, &rect[1], D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
555     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
556
557     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, FALSE);
558     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %08x\n", hr);
559
560     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
561     color = getPixelColor(device, 158, 118);
562     ok(color == 0x00ffffff, "Pixel 158/118 has color %08x\n", color);
563     color = getPixelColor(device, 162, 118);
564     ok(color == 0x00ffffff, "Pixel 162/118 has color %08x\n", color);
565     color = getPixelColor(device, 158, 122);
566     ok(color == 0x00ffffff, "Pixel 158/122 has color %08x\n", color);
567     color = getPixelColor(device, 162, 122);
568     ok(color == 0x00ff0000, "Pixel 162/122 has color %08x\n", color);
569
570     color = getPixelColor(device, 158, 358);
571     ok(color == 0x00ffffff, "Pixel 158/358 has color %08x\n", color);
572     color = getPixelColor(device, 162, 358);
573     ok(color == 0x0000ff00, "Pixel 162/358 has color %08x\n", color);
574     color = getPixelColor(device, 158, 358);
575     ok(color == 0x00ffffff, "Pixel 158/358 has color %08x\n", color);
576     color = getPixelColor(device, 162, 362);
577     ok(color == 0x00ffffff, "Pixel 162/362 has color %08x\n", color);
578
579     color = getPixelColor(device, 478, 118);
580     ok(color == 0x00ffffff, "Pixel 158/118 has color %08x\n", color);
581     color = getPixelColor(device, 478, 122);
582     ok(color == 0x0000ff00, "Pixel 162/118 has color %08x\n", color);
583     color = getPixelColor(device, 482, 122);
584     ok(color == 0x00ffffff, "Pixel 158/122 has color %08x\n", color);
585     color = getPixelColor(device, 482, 358);
586     ok(color == 0x00ffffff, "Pixel 162/122 has color %08x\n", color);
587
588     color = getPixelColor(device, 478, 358);
589     ok(color == 0x0000ff00, "Pixel 478/358 has color %08x\n", color);
590     color = getPixelColor(device, 478, 362);
591     ok(color == 0x00ffffff, "Pixel 478/118 has color %08x\n", color);
592     color = getPixelColor(device, 482, 358);
593     ok(color == 0x00ffffff, "Pixel 482/122 has color %08x\n", color);
594     color = getPixelColor(device, 482, 362);
595     ok(color == 0x00ffffff, "Pixel 482/122 has color %08x\n", color);
596
597     color = getPixelColor(device, 318, 238);
598     ok(color == 0x00ff0000, "Pixel 318/238 has color %08x\n", color);
599     color = getPixelColor(device, 318, 242);
600     ok(color == 0x0000ff00, "Pixel 318/242 has color %08x\n", color);
601     color = getPixelColor(device, 322, 238);
602     ok(color == 0x0000ff00, "Pixel 322/238 has color %08x\n", color);
603     color = getPixelColor(device, 322, 242);
604     ok(color == 0x0000ff00, "Pixel 322/242 has color %08x\n", color);
605
606     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_COLORWRITEENABLE, &oldColorWrite);
607     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
608     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED);
609     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
610
611     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
612     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
613
614     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, oldColorWrite);
615     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
616
617     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
618
619     /* Colorwriteenable does not affect the clear */
620     color = getPixelColor(device, 320, 240);
621     ok(color == 0x00ffffff, "Color write protected clear returned color %08x\n", color);
622 }
623
624 typedef struct {
625     float in[4];
626     DWORD out;
627 } test_data_t;
628
629 /*
630  *  c7      mova    ARGB            mov     ARGB
631  * -2.4     -2      0x00ffff00      -3      0x00ff0000
632  * -1.6     -2      0x00ffff00      -2      0x00ffff00
633  * -0.4      0      0x0000ffff      -1      0x0000ff00
634  *  0.4      0      0x0000ffff       0      0x0000ffff
635  *  1.6      2      0x00ff00ff       1      0x000000ff
636  *  2.4      2      0x00ff00ff       2      0x00ff00ff
637  */
638 static void test_mova(IDirect3DDevice9 *device)
639 {
640     static const DWORD mova_test[] = {
641         0xfffe0200,                                                             /* vs_2_0                       */
642         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
643         0x05000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0   */
644         0x05000051, 0xa00f0001, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, /* def c1, 1.0, 1.0, 0.0, 1.0   */
645         0x05000051, 0xa00f0002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, /* def c2, 0.0, 1.0, 0.0, 1.0   */
646         0x05000051, 0xa00f0003, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 0.0, 1.0, 1.0, 1.0   */
647         0x05000051, 0xa00f0004, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c4, 0.0, 0.0, 1.0, 1.0   */
648         0x05000051, 0xa00f0005, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, /* def c5, 1.0, 0.0, 1.0, 1.0   */
649         0x05000051, 0xa00f0006, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c6, 1.0, 1.0, 1.0, 1.0   */
650         0x0200002e, 0xb0010000, 0xa0000007,                                     /* mova a0.x, c7.x              */
651         0x03000001, 0xd00f0000, 0xa0e42003, 0xb0000000,                         /* mov oD0, c[a0.x + 3]         */
652         0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
653         0x0000ffff                                                              /* END                          */
654     };
655     static const DWORD mov_test[] = {
656         0xfffe0101,                                                             /* vs_1_1                       */
657         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
658         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0   */
659         0x00000051, 0xa00f0001, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, /* def c1, 1.0, 1.0, 0.0, 1.0   */
660         0x00000051, 0xa00f0002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, /* def c2, 0.0, 1.0, 0.0, 1.0   */
661         0x00000051, 0xa00f0003, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 0.0, 1.0, 1.0, 1.0   */
662         0x00000051, 0xa00f0004, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c4, 0.0, 0.0, 1.0, 1.0   */
663         0x00000051, 0xa00f0005, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, /* def c5, 1.0, 0.0, 1.0, 1.0   */
664         0x00000051, 0xa00f0006, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c6, 1.0, 1.0, 1.0, 1.0   */
665         0x00000001, 0xb0010000, 0xa0000007,                                     /* mov a0.x, c7.x               */
666         0x00000001, 0xd00f0000, 0xa0e42003,                                     /* mov oD0, c[a0.x + 3]         */
667         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
668         0x0000ffff                                                              /* END                          */
669     };
670
671     static const test_data_t test_data[2][6] = {
672         {
673             {{-2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff0000},
674             {{-1.6f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
675             {{-0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ff00},
676             {{ 0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
677             {{ 1.6f, 0.0f, 0.0f, 0.0f}, 0x000000ff},
678             {{ 2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff}
679         },
680         {
681             {{-2.4f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
682             {{-1.6f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
683             {{-0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
684             {{ 0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
685             {{ 1.6f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff},
686             {{ 2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff}
687         }
688     };
689
690     static const float quad[][3] = {
691         {-1.0f, -1.0f, 0.0f},
692         {-1.0f,  1.0f, 0.0f},
693         { 1.0f, -1.0f, 0.0f},
694         { 1.0f,  1.0f, 0.0f},
695     };
696
697     static const D3DVERTEXELEMENT9 decl_elements[] = {
698         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
699         D3DDECL_END()
700     };
701
702     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
703     IDirect3DVertexShader9 *mova_shader = NULL;
704     IDirect3DVertexShader9 *mov_shader = NULL;
705     HRESULT hr;
706     UINT i, j;
707
708     hr = IDirect3DDevice9_CreateVertexShader(device, mova_test, &mova_shader);
709     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
710     hr = IDirect3DDevice9_CreateVertexShader(device, mov_test, &mov_shader);
711     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
712     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
713     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
714     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
715     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
716
717     hr = IDirect3DDevice9_SetVertexShader(device, mov_shader);
718     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
719     for(j = 0; j < 2; ++j)
720     {
721         for (i = 0; i < (sizeof(test_data[0]) / sizeof(test_data_t)); ++i)
722         {
723             DWORD color;
724
725             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 7, test_data[j][i].in, 1);
726             ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
727
728             hr = IDirect3DDevice9_BeginScene(device);
729             ok(SUCCEEDED(hr), "BeginScene failed (%08x)\n", hr);
730
731             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], 3 * sizeof(float));
732             ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
733
734             hr = IDirect3DDevice9_EndScene(device);
735             ok(SUCCEEDED(hr), "EndScene failed (%08x)\n", hr);
736
737             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
738             ok(SUCCEEDED(hr), "Present failed (%08x)\n", hr);
739
740             color = getPixelColor(device, 320, 240);
741             ok(color == test_data[j][i].out, "Expected color %08x, got %08x (for input %f, instruction %s)\n",
742                test_data[j][i].out, color, test_data[j][i].in[0], j == 0 ? "mov" : "mova");
743
744             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
745             ok(SUCCEEDED(hr), "Clear failed (%08x)\n", hr);
746         }
747         hr = IDirect3DDevice9_SetVertexShader(device, mova_shader);
748         ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
749     }
750
751     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
752     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
753
754     IDirect3DVertexDeclaration9_Release(vertex_declaration);
755     IDirect3DVertexShader9_Release(mova_shader);
756     IDirect3DVertexShader9_Release(mov_shader);
757 }
758
759 struct sVertex {
760     float x, y, z;
761     DWORD diffuse;
762     DWORD specular;
763 };
764
765 struct sVertexT {
766     float x, y, z, rhw;
767     DWORD diffuse;
768     DWORD specular;
769 };
770
771 static void fog_test(IDirect3DDevice9 *device)
772 {
773     HRESULT hr;
774     DWORD color;
775     BYTE r, g, b;
776     float start = 0.0f, end = 1.0f;
777     D3DCAPS9 caps;
778     int i;
779
780     /* Gets full z based fog with linear fog, no fog with specular color */
781     struct sVertex unstransformed_1[] = {
782         {-1,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
783         {-1,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
784         { 0,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
785         { 0,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
786     };
787     /* Ok, I am too lazy to deal with transform matrices */
788     struct sVertex unstransformed_2[] = {
789         {-1,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
790         {-1,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
791         { 0,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
792         { 0,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
793     };
794     /* Untransformed ones. Give them a different diffuse color to make the test look
795      * nicer. It also makes making sure that they are drawn correctly easier.
796      */
797     struct sVertexT transformed_1[] = {
798         {320,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
799         {640,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
800         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
801         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
802     };
803     struct sVertexT transformed_2[] = {
804         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
805         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
806         {640,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
807         {320,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
808     };
809     struct vertex rev_fog_quads[] = {
810        {-1.0,   -1.0,   0.1,    0x000000ff},
811        {-1.0,    0.0,   0.1,    0x000000ff},
812        { 0.0,    0.0,   0.1,    0x000000ff},
813        { 0.0,   -1.0,   0.1,    0x000000ff},
814
815        { 0.0,   -1.0,   0.9,    0x000000ff},
816        { 0.0,    0.0,   0.9,    0x000000ff},
817        { 1.0,    0.0,   0.9,    0x000000ff},
818        { 1.0,   -1.0,   0.9,    0x000000ff},
819
820        { 0.0,    0.0,   0.4,    0x000000ff},
821        { 0.0,    1.0,   0.4,    0x000000ff},
822        { 1.0,    1.0,   0.4,    0x000000ff},
823        { 1.0,    0.0,   0.4,    0x000000ff},
824
825        {-1.0,    0.0,   0.7,    0x000000ff},
826        {-1.0,    1.0,   0.7,    0x000000ff},
827        { 0.0,    1.0,   0.7,    0x000000ff},
828        { 0.0,    0.0,   0.7,    0x000000ff},
829     };
830     WORD Indices[] = {0, 1, 2, 2, 3, 0};
831
832     memset(&caps, 0, sizeof(caps));
833     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
834     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %08x\n", hr);
835     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
836     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
837
838     /* Setup initial states: No lighting, fog on, fog color */
839     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
840     ok(hr == D3D_OK, "Turning off lighting returned %08x\n", hr);
841     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
842     ok(hr == D3D_OK, "Turning on fog calculations returned %08x\n", hr);
843     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
844     ok(hr == D3D_OK, "Turning on fog calculations returned %08x\n", hr);
845
846     /* First test: Both table fog and vertex fog off */
847     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
848     ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
849     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
850     ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
851
852     /* Start = 0, end = 1. Should be default, but set them */
853     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
854     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
855     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
856     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
857
858     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
859     {
860         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
861         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
862         /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
863         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
864                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_1,
865                                                      sizeof(unstransformed_1[0]));
866         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
867
868         /* That makes it use the Z value */
869         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
870         ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
871         /* Untransformed, vertex fog != none (or table fog != none):
872          * Use the Z value as input into the equation
873          */
874         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
875                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_2,
876                                                      sizeof(unstransformed_1[0]));
877         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
878
879         /* transformed verts */
880         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
881         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
882         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
883         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
884                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
885                                                      sizeof(transformed_1[0]));
886         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
887
888         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
889         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
890         /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
891          * equation
892          */
893         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
894                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_2,
895                                                      sizeof(transformed_2[0]));
896
897         hr = IDirect3DDevice9_EndScene(device);
898         ok(hr == D3D_OK, "EndScene returned %08x\n", hr);
899     }
900     else
901     {
902         ok(FALSE, "BeginScene failed\n");
903     }
904
905     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
906     color = getPixelColor(device, 160, 360);
907     ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color);
908     color = getPixelColor(device, 160, 120);
909     ok(color == 0x0000FF00 || color == 0x0000FE00, "Untransformed vertex with linear vertex fog has color %08x\n", color);
910     color = getPixelColor(device, 480, 120);
911     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
912     if(caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
913     {
914         color = getPixelColor(device, 480, 360);
915         ok(color == 0x0000FF00 || color == 0x0000FE00, "Transformed vertex with linear table fog has color %08x\n", color);
916     }
917     else
918     {
919         /* Without fog table support the vertex fog is still applied, even though table fog is turned on.
920          * The settings above result in no fogging with vertex fog
921          */
922         color = getPixelColor(device, 480, 120);
923         ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
924         trace("Info: Table fog not supported by this device\n");
925     }
926
927     /* Now test the special case fogstart == fogend */
928     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
929     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
930
931     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
932     {
933         start = 512;
934         end = 512;
935         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
936         ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
937         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
938         ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
939
940         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
941         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
942         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
943         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState %08x\n", hr);
944         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
945         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
946
947         /* Untransformed vertex, z coord = 0.1, fogstart = 512, fogend = 512. Would result in
948          * a completely fog-free primitive because start > zcoord, but because start == end, the primitive
949          * is fully covered by fog. The same happens to the 2nd untransformed quad with z = 1.0.
950          * The third transformed quad remains unfogged because the fogcoords are read from the specular
951          * color and has fixed fogstart and fogend.
952          */
953         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
954                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_1,
955                 sizeof(unstransformed_1[0]));
956         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
957         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
958                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_2,
959                 sizeof(unstransformed_1[0]));
960         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
961
962         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
963         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
964         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
965         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
966                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
967                 sizeof(transformed_1[0]));
968         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
969
970         hr = IDirect3DDevice9_EndScene(device);
971         ok(hr == D3D_OK, "EndScene returned %08x\n", hr);
972     }
973     else
974     {
975         ok(FALSE, "BeginScene failed\n");
976     }
977     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
978     color = getPixelColor(device, 160, 360);
979     ok(color == 0x0000FF00 || color == 0x0000FE00, "Untransformed vertex with vertex fog and z = 0.1 has color %08x\n", color);
980     color = getPixelColor(device, 160, 120);
981     ok(color == 0x0000FF00 || color == 0x0000FE00, "Untransformed vertex with vertex fog and z = 1.0 has color %08x\n", color);
982     color = getPixelColor(device, 480, 120);
983     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
984
985     /* Test "reversed" fog without shaders. With shaders this fails on a few Windows D3D implementations,
986      * but without shaders it seems to work everywhere
987      */
988     end = 0.2;
989     start = 0.8;
990     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
991     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
992     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
993     ok(hr == D3D_OK, "Setting fog end returned %08x\n", hr);
994     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
995     ok( hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
996
997     /* Test reversed fog without shaders. ATI cards have problems with reversed fog and shaders, so
998      * it doesn't seem very important for games. ATI cards also have problems with reversed table fog,
999      * so skip this for now
1000      */
1001     for(i = 0; i < 1 /*2 - Table fog test disabled, fails on ATI */; i++) {
1002         const char *mode = (i ? "table" : "vertex");
1003         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
1004         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
1005         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, i == 0 ? D3DFOG_LINEAR : D3DFOG_NONE);
1006         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1007         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, i == 0 ? D3DFOG_NONE : D3DFOG_LINEAR);
1008         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1009         hr = IDirect3DDevice9_BeginScene(device);
1010         ok( hr == D3D_OK, "IDirect3DDDevice9_BeginScene returned %08x\n", hr);
1011         if(SUCCEEDED(hr)) {
1012             WORD Indices2[] = { 0,  1,  2,  2,  3, 0,
1013                                 4,  5,  6,  6,  7, 4,
1014                                 8,  9, 10, 10, 11, 8,
1015                             12, 13, 14, 14, 15, 12};
1016
1017             hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */,
1018                     16 /* NumVerts */, 8 /*PrimCount */, Indices2, D3DFMT_INDEX16, rev_fog_quads,
1019                     sizeof(rev_fog_quads[0]));
1020
1021             hr = IDirect3DDevice9_EndScene(device);
1022             ok( hr == D3D_OK, "IDirect3DDDevice9_EndScene returned %08x\n", hr);
1023         }
1024         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1025         color = getPixelColor(device, 160, 360);
1026         ok(color == 0x0000FF00 || color == 0x0000FE00, "Reversed %s fog: z=0.1 has color 0x%08x, expected 0x0000ff00\n", mode, color);
1027
1028         color = getPixelColor(device, 160, 120);
1029         r = (color & 0x00ff0000) >> 16;
1030         g = (color & 0x0000ff00) >>  8;
1031         b = (color & 0x000000ff);
1032         ok(r == 0x00 && g >= 0x29 && g <= 0x2d && b >= 0xd2 && b <= 0xd6,
1033            "Reversed %s fog: z=0.7 has color 0x%08x, expected\n", mode, color);
1034
1035         color = getPixelColor(device, 480, 120);
1036         r = (color & 0x00ff0000) >> 16;
1037         g = (color & 0x0000ff00) >>  8;
1038         b = (color & 0x000000ff);
1039         ok(r == 0x00 && g >= 0xa8 && g <= 0xac && b >= 0x53 && b <= 0x57,
1040            "Reversed %s fog: z=0.4 has color 0x%08x, expected\n", mode, color);
1041
1042         color = getPixelColor(device, 480, 360);
1043         ok(color == 0x000000ff, "Reversed %s fog: z=0.9 has color 0x%08x, expected 0x000000ff\n", mode, color);
1044
1045         if(!(caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)) {
1046             skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping reversed table fog test\n");
1047             break;
1048         }
1049     }
1050     /* Turn off the fog master switch to avoid confusing other tests */
1051     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
1052     ok(hr == D3D_OK, "Turning off fog calculations returned %08x\n", hr);
1053     start = 0.0;
1054     end = 1.0;
1055     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
1056     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
1057     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
1058     ok(hr == D3D_OK, "Setting fog end returned %08x\n", hr);
1059     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
1060     ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState %08x\n", hr);
1061     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
1062     ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
1063 }
1064
1065 /* This test verifies the behaviour of cube maps wrt. texture wrapping.
1066  * D3D cube map wrapping always behaves like GL_CLAMP_TO_EDGE,
1067  * regardless of the actual addressing mode set. */
1068 static void test_cube_wrap(IDirect3DDevice9 *device)
1069 {
1070     static const float quad[][6] = {
1071         {-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1072         {-1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1073         { 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1074         { 1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1075     };
1076
1077     static const D3DVERTEXELEMENT9 decl_elements[] = {
1078         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1079         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1080         D3DDECL_END()
1081     };
1082
1083     static const struct {
1084         D3DTEXTUREADDRESS mode;
1085         const char *name;
1086     } address_modes[] = {
1087         {D3DTADDRESS_WRAP, "D3DTADDRESS_WRAP"},
1088         {D3DTADDRESS_MIRROR, "D3DTADDRESS_MIRROR"},
1089         {D3DTADDRESS_CLAMP, "D3DTADDRESS_CLAMP"},
1090         {D3DTADDRESS_BORDER, "D3DTADDRESS_BORDER"},
1091         {D3DTADDRESS_MIRRORONCE, "D3DTADDRESS_MIRRORONCE"},
1092     };
1093
1094     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1095     IDirect3DCubeTexture9 *texture = NULL;
1096     IDirect3DSurface9 *surface = NULL;
1097     D3DLOCKED_RECT locked_rect;
1098     HRESULT hr;
1099     UINT x;
1100     INT y, face;
1101
1102     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1103     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1104     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1105     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1106
1107     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
1108             D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL);
1109     ok(SUCCEEDED(hr), "CreateOffscreenPlainSurface failed (0x%08x)\n", hr);
1110
1111     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
1112     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1113
1114     for (y = 0; y < 128; ++y)
1115     {
1116         DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1117         for (x = 0; x < 64; ++x)
1118         {
1119             *ptr++ = 0xffff0000;
1120         }
1121         for (x = 64; x < 128; ++x)
1122         {
1123             *ptr++ = 0xff0000ff;
1124         }
1125     }
1126
1127     hr = IDirect3DSurface9_UnlockRect(surface);
1128     ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
1129
1130     hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
1131             D3DPOOL_DEFAULT, &texture, NULL);
1132     ok(SUCCEEDED(hr), "CreateCubeTexture failed (0x%08x)\n", hr);
1133
1134     /* Create cube faces */
1135     for (face = 0; face < 6; ++face)
1136     {
1137         IDirect3DSurface9 *face_surface = NULL;
1138
1139         hr= IDirect3DCubeTexture9_GetCubeMapSurface(texture, face, 0, &face_surface);
1140         ok(SUCCEEDED(hr), "GetCubeMapSurface failed (0x%08x)\n", hr);
1141
1142         hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, face_surface, NULL);
1143         ok(SUCCEEDED(hr), "UpdateSurface failed (0x%08x)\n", hr);
1144
1145         IDirect3DSurface9_Release(face_surface);
1146     }
1147
1148     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
1149     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1150
1151     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
1152     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1153     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
1154     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1155     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_BORDERCOLOR, 0xff00ff00);
1156     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_BORDERCOLOR failed (0x%08x)\n", hr);
1157
1158     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1159     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1160
1161     for (x = 0; x < (sizeof(address_modes) / sizeof(*address_modes)); ++x)
1162     {
1163         DWORD color;
1164
1165         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, address_modes[x].mode);
1166         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU (%s) failed (0x%08x)\n", address_modes[x].name, hr);
1167         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, address_modes[x].mode);
1168         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV (%s) failed (0x%08x)\n", address_modes[x].name, hr);
1169
1170         hr = IDirect3DDevice9_BeginScene(device);
1171         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1172
1173         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1174         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
1175
1176         hr = IDirect3DDevice9_EndScene(device);
1177         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1178
1179         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1180         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1181
1182         /* Due to the nature of this test, we sample essentially at the edge
1183          * between two faces. Because of this it's undefined from which face
1184          * the driver will sample. Fortunately that's not important for this
1185          * test, since all we care about is that it doesn't sample from the
1186          * other side of the surface or from the border. */
1187         color = getPixelColor(device, 320, 240);
1188         ok(color == 0x00ff0000 || color == 0x000000ff,
1189                 "Got color 0x%08x for addressing mode %s, expected 0x00ff0000 or 0x000000ff.\n",
1190                 color, address_modes[x].name);
1191
1192         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
1193         ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
1194     }
1195
1196     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1197     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1198
1199     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1200     IDirect3DCubeTexture9_Release(texture);
1201     IDirect3DSurface9_Release(surface);
1202 }
1203
1204 static void offscreen_test(IDirect3DDevice9 *device)
1205 {
1206     HRESULT hr;
1207     IDirect3DTexture9 *offscreenTexture = NULL;
1208     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
1209     DWORD color;
1210
1211     static const float quad[][5] = {
1212         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
1213         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
1214         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
1215         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
1216     };
1217
1218     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
1219     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
1220
1221     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
1222     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %08x\n", hr);
1223     if(!offscreenTexture) {
1224         trace("Failed to create an X8R8G8B8 offscreen texture, trying R5G6B5\n");
1225         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
1226         ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %08x\n", hr);
1227         if(!offscreenTexture) {
1228             skip("Cannot create an offscreen render target\n");
1229             goto out;
1230         }
1231     }
1232
1233     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1234     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
1235     if(!backbuffer) {
1236         goto out;
1237     }
1238
1239     hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
1240     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %08x\n", hr);
1241     if(!offscreen) {
1242         goto out;
1243     }
1244
1245     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
1246     ok(hr == D3D_OK, "SetFVF failed, hr = %08x\n", hr);
1247
1248     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
1249     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
1250     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
1251     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
1252     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
1253     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1254     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
1255     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1256     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1257     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1258
1259     if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
1260         hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
1261         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
1262         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1263         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
1264
1265         /* Draw without textures - Should result in a white quad */
1266         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
1267         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %08x\n", hr);
1268
1269         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
1270         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
1271         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
1272         ok(hr == D3D_OK, "SetTexture failed, %08x\n", hr);
1273
1274         /* This time with the texture */
1275         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
1276         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %08x\n", hr);
1277
1278         IDirect3DDevice9_EndScene(device);
1279     }
1280
1281     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1282
1283     /* Center quad - should be white */
1284     color = getPixelColor(device, 320, 240);
1285     ok(color == 0x00ffffff, "Offscreen failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1286     /* Some quad in the cleared part of the texture */
1287     color = getPixelColor(device, 170, 240);
1288     ok(color == 0x00ff00ff, "Offscreen failed: Got color 0x%08x, expected 0x00ff00ff.\n", color);
1289     /* Part of the originally cleared back buffer */
1290     color = getPixelColor(device, 10, 10);
1291     ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1292     if(0) {
1293         /* Lower left corner of the screen, where back buffer offscreen rendering draws the offscreen texture.
1294          * It should be red, but the offscreen texture may leave some junk there. Not tested yet. Depending on
1295          * the offscreen rendering mode this test would succeed or fail
1296          */
1297         color = getPixelColor(device, 10, 470);
1298         ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1299     }
1300
1301 out:
1302     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1303
1304     /* restore things */
1305     if(backbuffer) {
1306         IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
1307         IDirect3DSurface9_Release(backbuffer);
1308     }
1309     if(offscreenTexture) {
1310         IDirect3DTexture9_Release(offscreenTexture);
1311     }
1312     if(offscreen) {
1313         IDirect3DSurface9_Release(offscreen);
1314     }
1315 }
1316
1317 /* This test tests fog in combination with shaders.
1318  * What's tested: linear fog (vertex and table) with pixel shader
1319  *                linear table fog with non foggy vertex shader
1320  *                vertex fog with foggy vertex shader
1321  * What's not tested: non linear fog with shader
1322  *                    table fog with foggy vertex shader
1323  */
1324 static void fog_with_shader_test(IDirect3DDevice9 *device)
1325 {
1326     HRESULT hr;
1327     DWORD color;
1328     union {
1329         float f;
1330         DWORD i;
1331     } start, end;
1332     unsigned int i, j;
1333
1334     /* basic vertex shader without fog computation ("non foggy") */
1335     static const DWORD vertex_shader_code1[] = {
1336         0xfffe0101,                                                             /* vs_1_1                       */
1337         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
1338         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                */
1339         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
1340         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                  */
1341         0x0000ffff
1342     };
1343     /* basic vertex shader with reversed fog computation ("foggy") */
1344     static const DWORD vertex_shader_code2[] = {
1345         0xfffe0101,                                                             /* vs_1_1                        */
1346         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0               */
1347         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                 */
1348         0x00000051, 0xa00f0000, 0xbfa00000, 0x00000000, 0xbf666666, 0x00000000, /* def c0, -1.25, 0.0, -0.9, 0.0 */
1349         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                  */
1350         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                   */
1351         0x00000002, 0x800f0000, 0x90aa0000, 0xa0aa0000,                         /* add r0, v0.z, c0.z            */
1352         0x00000005, 0xc00f0001, 0x80000000, 0xa0000000,                         /* mul oFog, r0.x, c0.x          */
1353         0x0000ffff
1354     };
1355     /* basic pixel shader */
1356     static const DWORD pixel_shader_code[] = {
1357         0xffff0101,                                                             /* ps_1_1     */
1358         0x00000001, 0x800f0000, 0x90e40000,                                     /* mov r0, vo */
1359         0x0000ffff
1360     };
1361
1362     static struct vertex quad[] = {
1363         {-1.0f, -1.0f,  0.0f,          0xFFFF0000  },
1364         {-1.0f,  1.0f,  0.0f,          0xFFFF0000  },
1365         { 1.0f, -1.0f,  0.0f,          0xFFFF0000  },
1366         { 1.0f,  1.0f,  0.0f,          0xFFFF0000  },
1367     };
1368
1369     static const D3DVERTEXELEMENT9 decl_elements[] = {
1370         {0,  0, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1371         {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
1372         D3DDECL_END()
1373     };
1374
1375     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1376     IDirect3DVertexShader9      *vertex_shader[3]   = {NULL, NULL, NULL};
1377     IDirect3DPixelShader9       *pixel_shader[2]    = {NULL, NULL};
1378
1379     /* This reference data was collected on a nVidia GeForce 7600GS driver version 84.19 DirectX version 9.0c on Windows XP */
1380     static const struct test_data_t {
1381         int vshader;
1382         int pshader;
1383         D3DFOGMODE vfog;
1384         D3DFOGMODE tfog;
1385         unsigned int color[11];
1386     } test_data[] = {
1387         /* only pixel shader: */
1388         {0, 1, 0, 3,
1389         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1390         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1391         {0, 1, 1, 3,
1392         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1393         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1394         {0, 1, 2, 3,
1395         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1396         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1397         {0, 1, 3, 0,
1398         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1399         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1400         {0, 1, 3, 3,
1401         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1402         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1403
1404         /* vertex shader */
1405         {1, 0, 0, 0,
1406         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1407          0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1408         {1, 0, 0, 3,
1409         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1410         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1411         {1, 0, 1, 3,
1412         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1413         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1414
1415         {1, 0, 2, 3,
1416         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1417         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1418         {1, 0, 3, 3,
1419         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1420         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1421
1422         /* vertex shader and pixel shader */
1423         {1, 1, 0, 3,
1424         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1425         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1426         {1, 1, 1, 3,
1427         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1428         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1429         {1, 1, 2, 3,
1430         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1431         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1432
1433         {1, 1, 3, 3,
1434         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1435         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1436
1437
1438 #if 0  /* FIXME: these fail on GeForce 8500 */
1439         /* foggy vertex shader */
1440         {2, 0, 0, 0,
1441         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1442          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1443         {2, 0, 1, 0,
1444         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1445          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1446         {2, 0, 2, 0,
1447         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1448          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1449         {2, 0, 3, 0,
1450         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1451          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1452 #endif
1453
1454         /* foggy vertex shader and pixel shader */
1455         {2, 1, 0, 0,
1456         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1457          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1458         {2, 1, 1, 0,
1459         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1460          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1461         {2, 1, 2, 0,
1462         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1463          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1464         {2, 1, 3, 0,
1465         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1466          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1467
1468     };
1469
1470     /* NOTE: changing these values will not affect the tests with foggy vertex shader, as the values are hardcoded in the shader*/
1471     start.f=0.1f;
1472     end.f=0.9f;
1473
1474     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code1, &vertex_shader[1]);
1475     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1476     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code2, &vertex_shader[2]);
1477     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1478     hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader[1]);
1479     ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1480     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1481     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
1482
1483     /* Setup initial states: No lighting, fog on, fog color */
1484     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1485     ok(hr == D3D_OK, "Turning off lighting failed (%08x)\n", hr);
1486     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
1487     ok(hr == D3D_OK, "Turning on fog calculations failed (%08x)\n", hr);
1488     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
1489     ok(hr == D3D_OK, "Setting fog color failed (%08x)\n", hr);
1490     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1491     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1492
1493     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
1494     ok(hr == D3D_OK, "Turning off table fog failed (%08x)\n", hr);
1495     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
1496     ok(hr == D3D_OK, "Turning off vertex fog failed (%08x)\n", hr);
1497
1498     /* Use fogtart = 0.1 and end = 0.9 to test behavior outside the fog transition phase, too*/
1499     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, start.i);
1500     ok(hr == D3D_OK, "Setting fog start failed (%08x)\n", hr);
1501     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, end.i);
1502     ok(hr == D3D_OK, "Setting fog end failed (%08x)\n", hr);
1503
1504     for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++)
1505     {
1506         hr = IDirect3DDevice9_SetVertexShader(device, vertex_shader[test_data[i].vshader]);
1507         ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1508         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader[test_data[i].pshader]);
1509         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1510         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, test_data[i].vfog);
1511         ok( hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1512         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, test_data[i].tfog);
1513         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1514
1515         for(j=0; j < 11; j++)
1516         {
1517             /* Don't use the whole zrange to prevent rounding errors */
1518             quad[0].z = 0.001f + (float)j / 10.02f;
1519             quad[1].z = 0.001f + (float)j / 10.02f;
1520             quad[2].z = 0.001f + (float)j / 10.02f;
1521             quad[3].z = 0.001f + (float)j / 10.02f;
1522
1523             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1524             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
1525
1526             hr = IDirect3DDevice9_BeginScene(device);
1527             ok( hr == D3D_OK, "BeginScene returned failed (%08x)\n", hr);
1528
1529             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1530             ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1531
1532             hr = IDirect3DDevice9_EndScene(device);
1533             ok(hr == D3D_OK, "EndScene failed (%08x)\n", hr);
1534
1535             IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1536
1537             /* As the red and green component are the result of blending use 5% tolerance on the expected value */
1538             color = getPixelColor(device, 128, 240);
1539             ok(color_match(color, test_data[i].color[j], 13),
1540                "fog vs%i ps%i fvm%i ftm%i %d: got color %08x, expected %08x +-5%%\n",
1541                test_data[i].vshader, test_data[i].pshader, test_data[i].vfog, test_data[i].tfog, j, color, test_data[i].color[j]);
1542         }
1543     }
1544
1545     /* reset states */
1546     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
1547     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1548     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1549     ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1550     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1551     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1552     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
1553     ok(hr == D3D_OK, "Turning off fog calculations failed (%08x)\n", hr);
1554
1555     IDirect3DVertexShader9_Release(vertex_shader[1]);
1556     IDirect3DVertexShader9_Release(vertex_shader[2]);
1557     IDirect3DPixelShader9_Release(pixel_shader[1]);
1558     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1559 }
1560
1561 static void generate_bumpmap_textures(IDirect3DDevice9 *device) {
1562     unsigned int i, x, y;
1563     HRESULT hr;
1564     IDirect3DTexture9 *texture[2] = {NULL, NULL};
1565     D3DLOCKED_RECT locked_rect;
1566
1567     /* Generate the textures */
1568     for(i=0; i<2; i++)
1569     {
1570         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, i?D3DFMT_A8R8G8B8:D3DFMT_V8U8,
1571                                             D3DPOOL_MANAGED, &texture[i], NULL);
1572         ok(SUCCEEDED(hr), "CreateTexture failed (0x%08x)\n", hr);
1573
1574         hr = IDirect3DTexture9_LockRect(texture[i], 0, &locked_rect, NULL, 0);
1575         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1576         for (y = 0; y < 128; ++y)
1577         {
1578             if(i)
1579             { /* Set up black texture with 2x2 texel white spot in the middle */
1580                 DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1581                 for (x = 0; x < 128; ++x)
1582                 {
1583                     if(y>62 && y<66 && x>62 && x<66)
1584                         *ptr++ = 0xffffffff;
1585                     else
1586                         *ptr++ = 0xff000000;
1587                 }
1588             }
1589             else
1590             { /* Set up a displacement map which points away from the center parallel to the closest axis.
1591                * (if multiplied with bumpenvmat)
1592               */
1593                 WORD *ptr = (WORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1594                 for (x = 0; x < 128; ++x)
1595                 {
1596                     if(abs(x-64)>abs(y-64))
1597                     {
1598                         if(x < 64)
1599                             *ptr++ = 0xc000;
1600                         else
1601                             *ptr++ = 0x4000;
1602                     }
1603                     else
1604                     {
1605                         if(y < 64)
1606                             *ptr++ = 0x0040;
1607                         else
1608                             *ptr++ = 0x00c0;
1609                     }
1610                 }
1611             }
1612         }
1613         hr = IDirect3DTexture9_UnlockRect(texture[i], 0);
1614         ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
1615
1616         hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture[i]);
1617         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1618
1619         /* Disable texture filtering */
1620         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MINFILTER, D3DTEXF_POINT);
1621         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1622         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
1623         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1624
1625         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1626         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU failed (0x%08x)\n", hr);
1627         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1628         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV failed (0x%08x)\n", hr);
1629     }
1630 }
1631
1632 /* test the behavior of the texbem instruction
1633  * with normal 2D and projective 2D textures
1634  */
1635 static void texbem_test(IDirect3DDevice9 *device)
1636 {
1637     HRESULT hr;
1638     DWORD color;
1639     int i;
1640
1641     static const DWORD pixel_shader_code[] = {
1642         0xffff0101,                         /* ps_1_1*/
1643         0x00000042, 0xb00f0000,             /* tex t0*/
1644         0x00000043, 0xb00f0001, 0xb0e40000, /* texbem t1, t0*/
1645         0x00000001, 0x800f0000, 0xb0e40001, /* mov r0, t1*/
1646         0x0000ffff
1647     };
1648     static const DWORD double_texbem_code[] =  {
1649         0xffff0103,                                         /* ps_1_3           */
1650         0x00000042, 0xb00f0000,                             /* tex t0           */
1651         0x00000043, 0xb00f0001, 0xb0e40000,                 /* texbem t1, t0    */
1652         0x00000042, 0xb00f0002,                             /* tex t2           */
1653         0x00000043, 0xb00f0003, 0xb0e40002,                 /* texbem t3, t2    */
1654         0x00000002, 0x800f0000, 0xb0e40001, 0xb0e40003,     /* add r0, t1, t3   */
1655         0x0000ffff                                          /* end              */
1656     };
1657
1658
1659     static const float quad[][7] = {
1660         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f},
1661         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f},
1662         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 1.0f, 0.0f},
1663         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 1.0f, 1.0f},
1664     };
1665     static const float quad_proj[][9] = {
1666         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f,   0.0f,   0.0f, 0.0f, 128.0f},
1667         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f,   0.0f, 128.0f, 0.0f, 128.0f},
1668         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 128.0f,   0.0f, 0.0f, 128.0f},
1669         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 128.0f, 128.0f, 0.0f, 128.0f},
1670     };
1671
1672     static const D3DVERTEXELEMENT9 decl_elements[][4] = { {
1673         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1674         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1675         {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1676         D3DDECL_END()
1677     },{
1678         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1679         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1680         {0, 20, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1681         D3DDECL_END()
1682     } };
1683
1684     /* use asymmetric matrix to test loading */
1685     float bumpenvmat[4] = {0.0,0.5,-0.5,0.0};
1686
1687     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1688     IDirect3DPixelShader9       *pixel_shader       = NULL;
1689     IDirect3DTexture9           *texture            = NULL, *texture1, *texture2;
1690     D3DLOCKED_RECT locked_rect;
1691
1692     generate_bumpmap_textures(device);
1693
1694     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
1695     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
1696     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
1697     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
1698     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
1699
1700     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
1701     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1702
1703     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1704     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
1705
1706     for(i=0; i<2; i++)
1707     {
1708         if(i)
1709         {
1710             hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4|D3DTTFF_PROJECTED);
1711             ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
1712         }
1713
1714         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements[i], &vertex_declaration);
1715         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1716         hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1717         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1718
1719         hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader);
1720         ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1721         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader);
1722         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1723
1724         hr = IDirect3DDevice9_BeginScene(device);
1725         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1726
1727         if(!i)
1728             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1729         else
1730             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad_proj[0], sizeof(quad_proj[0]));
1731         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
1732
1733         hr = IDirect3DDevice9_EndScene(device);
1734         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1735
1736         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1737         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1738
1739         color = getPixelColor(device, 320-32, 240);
1740         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1741         color = getPixelColor(device, 320+32, 240);
1742         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1743         color = getPixelColor(device, 320, 240-32);
1744         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1745         color = getPixelColor(device, 320, 240+32);
1746         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1747
1748         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1749         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1750         IDirect3DPixelShader9_Release(pixel_shader);
1751
1752         hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1753         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1754         IDirect3DVertexDeclaration9_Release(vertex_declaration);
1755     }
1756
1757     /* clean up */
1758     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
1759     ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
1760
1761     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
1762     ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
1763
1764     for(i=0; i<2; i++)
1765     {
1766         hr = IDirect3DDevice9_GetTexture(device, i, (IDirect3DBaseTexture9 **) &texture);
1767         ok(SUCCEEDED(hr), "IDirect3DDevice9_GetTexture failed (0x%08x)\n", hr);
1768         IDirect3DTexture9_Release(texture); /* For the GetTexture */
1769         hr = IDirect3DDevice9_SetTexture(device, i, NULL);
1770         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1771         IDirect3DTexture9_Release(texture);
1772     }
1773
1774     /* Test double texbem */
1775     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_V8U8, D3DPOOL_MANAGED, &texture, NULL);
1776     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed (0x%08x)\n", hr);
1777     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_V8U8, D3DPOOL_MANAGED, &texture1, NULL);
1778     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed (0x%08x)\n", hr);
1779     hr = IDirect3DDevice9_CreateTexture(device, 8, 8, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture2, NULL);
1780     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed (0x%08x)\n", hr);
1781     hr = IDirect3DDevice9_CreatePixelShader(device, double_texbem_code, &pixel_shader);
1782     ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1783
1784     hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
1785     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1786     ((signed char *) locked_rect.pBits)[0] = (-1.0 / 8.0) * 127;
1787     ((signed char *) locked_rect.pBits)[1] = ( 1.0 / 8.0) * 127;
1788
1789     hr = IDirect3DTexture9_UnlockRect(texture, 0);
1790     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1791
1792     hr = IDirect3DTexture9_LockRect(texture1, 0, &locked_rect, NULL, 0);
1793     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1794     ((signed char *) locked_rect.pBits)[0] = (-2.0 / 8.0) * 127;
1795     ((signed char *) locked_rect.pBits)[1] = (-4.0 / 8.0) * 127;
1796     hr = IDirect3DTexture9_UnlockRect(texture1, 0);
1797     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1798
1799     {
1800         /* Some data without any meaning, just to have an 8x8 array to see which element is picked */
1801 #define tex  0x00ff0000
1802 #define tex1 0x0000ff00
1803 #define origin 0x000000ff
1804         static const DWORD pixel_data[] = {
1805             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1806             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1807             0x000000ff, tex1      , 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1808             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1809             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, origin,     0x000000ff, tex       , 0x000000ff,
1810             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1811             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1812             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1813         };
1814 #undef tex1
1815 #undef tex2
1816 #undef origin
1817
1818         hr = IDirect3DTexture9_LockRect(texture2, 0, &locked_rect, NULL, 0);
1819         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1820         for(i = 0; i < 8; i++) {
1821             memcpy(((char *) locked_rect.pBits) + i * locked_rect.Pitch, pixel_data + 8 * i, 8 * sizeof(DWORD));
1822         }
1823         hr = IDirect3DTexture9_UnlockRect(texture2, 0);
1824         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1825     }
1826
1827     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
1828     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1829     hr = IDirect3DDevice9_SetTexture(device, 1, (IDirect3DBaseTexture9 *) texture2);
1830     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1831     hr = IDirect3DDevice9_SetTexture(device, 2, (IDirect3DBaseTexture9 *) texture1);
1832     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1833     hr = IDirect3DDevice9_SetTexture(device, 3, (IDirect3DBaseTexture9 *) texture2);
1834     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1835     hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader);
1836     ok(SUCCEEDED(hr), "Direct3DDevice9_SetPixelShader failed (0x%08x)\n", hr);
1837     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX4);
1838     ok(SUCCEEDED(hr), "Direct3DDevice9_SetPixelShader failed (0x%08x)\n", hr);
1839
1840     bumpenvmat[0] =-1.0;  bumpenvmat[2] =  2.0;
1841     bumpenvmat[1] = 0.0;  bumpenvmat[3] =  0.0;
1842     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
1843     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
1844     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
1845     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
1846
1847     bumpenvmat[0] = 1.5; bumpenvmat[2] =  0.0;
1848     bumpenvmat[1] = 0.0; bumpenvmat[3] =  0.5;
1849     IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
1850     IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
1851     IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
1852     IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
1853
1854     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1855     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1856     hr = IDirect3DDevice9_SetSamplerState(device, 1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1857     hr = IDirect3DDevice9_SetSamplerState(device, 1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1858     hr = IDirect3DDevice9_SetSamplerState(device, 2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1859     hr = IDirect3DDevice9_SetSamplerState(device, 2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1860     hr = IDirect3DDevice9_SetSamplerState(device, 3, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1861     hr = IDirect3DDevice9_SetSamplerState(device, 3, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1862
1863     hr = IDirect3DDevice9_BeginScene(device);
1864     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1865     if(SUCCEEDED(hr)) {
1866         static const float double_quad[] = {
1867             -1.0,   -1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
1868              1.0,   -1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
1869             -1.0,    1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
1870              1.0,    1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
1871         };
1872
1873         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, double_quad, sizeof(float) * 11);
1874         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
1875         hr = IDirect3DDevice9_EndScene(device);
1876         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1877     }
1878     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1879     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1880     color = getPixelColor(device, 320, 240);
1881     ok(color == 0x00ffff00, "double texbem failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
1882
1883     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1884     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1885     hr = IDirect3DDevice9_SetTexture(device, 1, NULL);
1886     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1887     hr = IDirect3DDevice9_SetTexture(device, 2, NULL);
1888     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1889     hr = IDirect3DDevice9_SetTexture(device, 3, NULL);
1890     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1891     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1892     ok(SUCCEEDED(hr), "Direct3DDevice9_SetPixelShader failed (0x%08x)\n", hr);
1893
1894     IDirect3DPixelShader9_Release(pixel_shader);
1895     IDirect3DTexture9_Release(texture);
1896     IDirect3DTexture9_Release(texture1);
1897     IDirect3DTexture9_Release(texture2);
1898 }
1899
1900 static void z_range_test(IDirect3DDevice9 *device)
1901 {
1902     const struct vertex quad[] =
1903     {
1904         {-1.0f,  0.0f,   1.1f,                          0xffff0000},
1905         {-1.0f,  1.0f,   1.1f,                          0xffff0000},
1906         { 1.0f,  0.0f,  -1.1f,                          0xffff0000},
1907         { 1.0f,  1.0f,  -1.1f,                          0xffff0000},
1908     };
1909     const struct vertex quad2[] =
1910     {
1911         {-1.0f,  0.0f,   1.1f,                          0xff0000ff},
1912         {-1.0f,  1.0f,   1.1f,                          0xff0000ff},
1913         { 1.0f,  0.0f,  -1.1f,                          0xff0000ff},
1914         { 1.0f,  1.0f,  -1.1f,                          0xff0000ff},
1915     };
1916
1917     const struct tvertex quad3[] =
1918     {
1919         {    0,   240,   1.1f,  1.0,                    0xffffff00},
1920         {    0,   480,   1.1f,  1.0,                    0xffffff00},
1921         {  640,   240,  -1.1f,  1.0,                    0xffffff00},
1922         {  640,   480,  -1.1f,  1.0,                    0xffffff00},
1923     };
1924     const struct tvertex quad4[] =
1925     {
1926         {    0,   240,   1.1f,  1.0,                    0xff00ff00},
1927         {    0,   480,   1.1f,  1.0,                    0xff00ff00},
1928         {  640,   240,  -1.1f,  1.0,                    0xff00ff00},
1929         {  640,   480,  -1.1f,  1.0,                    0xff00ff00},
1930     };
1931     HRESULT hr;
1932     DWORD color;
1933     IDirect3DVertexShader9 *shader;
1934     IDirect3DVertexDeclaration9 *decl;
1935     D3DCAPS9 caps;
1936     const DWORD shader_code[] = {
1937         0xfffe0101,                                     /* vs_1_1           */
1938         0x0000001f, 0x80000000, 0x900f0000,             /* dcl_position v0  */
1939         0x00000001, 0xc00f0000, 0x90e40000,             /* mov oPos, v0     */
1940         0x00000001, 0xd00f0000, 0xa0e40000,             /* mov oD0, c0      */
1941         0x0000ffff                                      /* end              */
1942     };
1943     static const D3DVERTEXELEMENT9 decl_elements[] = {
1944         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1945         D3DDECL_END()
1946     };
1947     /* Does the Present clear the depth stencil? Clear the depth buffer with some value != 0,
1948      * then call Present. Then clear the color buffer to make sure it has some defined content
1949      * after the Present with D3DSWAPEFFECT_DISCARD. After that draw a plane that is somewhere cut
1950      * by the depth value.
1951      */
1952     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.75, 0);
1953     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
1954     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1955     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4, 0);
1956
1957     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, TRUE);
1958     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1959     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
1960     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1961     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
1962     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1963     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
1964     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1965     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1966     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
1967
1968     hr = IDirect3DDevice9_BeginScene(device);
1969     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1970     if(hr == D3D_OK)
1971     {
1972         /* Test the untransformed vertex path */
1973         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
1974         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
1975         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS);
1976         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1977         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad2, sizeof(quad2[0]));
1978         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
1979
1980         /* Test the transformed vertex path */
1981         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
1982         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
1983
1984         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad4, sizeof(quad4[0]));
1985         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
1986         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
1987         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1988         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad3, sizeof(quad3[0]));
1989         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
1990
1991         hr = IDirect3DDevice9_EndScene(device);
1992         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1993     }
1994
1995     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1996     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1997
1998     /* Do not test the exact corner pixels, but go pretty close to them */
1999
2000     /* Clipped because z > 1.0 */
2001     color = getPixelColor(device, 28, 238);
2002     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2003     color = getPixelColor(device, 28, 241);
2004     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2005
2006     /* Not clipped, > z buffer clear value(0.75) */
2007     color = getPixelColor(device, 31, 238);
2008     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2009     color = getPixelColor(device, 31, 241);
2010     ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
2011     color = getPixelColor(device, 100, 238);
2012     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2013     color = getPixelColor(device, 100, 241);
2014     ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
2015
2016     /* Not clipped, < z buffer clear value */
2017     color = getPixelColor(device, 104, 238);
2018     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2019     color = getPixelColor(device, 104, 241);
2020     ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color);
2021     color = getPixelColor(device, 318, 238);
2022     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2023     color = getPixelColor(device, 318, 241);
2024     ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color);
2025
2026     /* Clipped because z < 0.0 */
2027     color = getPixelColor(device, 321, 238);
2028     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2029     color = getPixelColor(device, 321, 241);
2030     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2031
2032     /* Test the shader path */
2033     IDirect3DDevice9_GetDeviceCaps(device, &caps);
2034     if (caps.VertexShaderVersion < D3DVS_VERSION(1, 1)) {
2035         skip("Vertex shaders not supported\n");
2036         goto out;
2037     }
2038     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
2039     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
2040     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
2041     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
2042
2043     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4, 0);
2044
2045     IDirect3DDevice9_SetVertexDeclaration(device, decl);
2046     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
2047     IDirect3DDevice9_SetVertexShader(device, shader);
2048     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
2049
2050     hr = IDirect3DDevice9_BeginScene(device);
2051     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2052     if(hr == D3D_OK)
2053     {
2054         float colorf[] = {1.0, 0.0, 0.0, 1.0};
2055         float colorf2[] = {0.0, 0.0, 1.0, 1.0};
2056         IDirect3DDevice9_SetVertexShaderConstantF(device, 0, colorf, 1);
2057         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
2058         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2059         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS);
2060         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2061         IDirect3DDevice9_SetVertexShaderConstantF(device, 0, colorf2, 1);
2062         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad2, sizeof(quad2[0]));
2063         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2064
2065         hr = IDirect3DDevice9_EndScene(device);
2066         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2067     }
2068
2069     IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2070     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
2071     IDirect3DDevice9_SetVertexShader(device, NULL);
2072     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
2073
2074     IDirect3DVertexDeclaration9_Release(decl);
2075     IDirect3DVertexShader9_Release(shader);
2076
2077     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2078     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2079     /* Z < 1.0 */
2080     color = getPixelColor(device, 28, 238);
2081     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2082
2083     /* 1.0 < z < 0.75 */
2084     color = getPixelColor(device, 31, 238);
2085     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2086     color = getPixelColor(device, 100, 238);
2087     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2088
2089     /* 0.75 < z < 0.0 */
2090     color = getPixelColor(device, 104, 238);
2091     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2092     color = getPixelColor(device, 318, 238);
2093     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2094
2095     /* 0.0 < z */
2096     color = getPixelColor(device, 321, 238);
2097     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2098
2099     out:
2100     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
2101     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2102     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
2103     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2104     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
2105     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2106 }
2107
2108 static void fill_surface(IDirect3DSurface9 *surface, DWORD color)
2109 {
2110     D3DSURFACE_DESC desc;
2111     D3DLOCKED_RECT l;
2112     HRESULT hr;
2113     unsigned int x, y;
2114     DWORD *mem;
2115
2116     memset(&desc, 0, sizeof(desc));
2117     memset(&l, 0, sizeof(l));
2118     hr = IDirect3DSurface9_GetDesc(surface, &desc);
2119     ok(hr == D3D_OK, "IDirect3DSurface9_GetDesc failed with %08x\n", hr);
2120     hr = IDirect3DSurface9_LockRect(surface, &l, NULL, 0);
2121     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed with %08x\n", hr);
2122     if(FAILED(hr)) return;
2123
2124     for(y = 0; y < desc.Height; y++)
2125     {
2126         mem = (DWORD *) ((BYTE *) l.pBits + y * l.Pitch);
2127         for(x = 0; x < l.Pitch / sizeof(DWORD); x++)
2128         {
2129             mem[x] = color;
2130         }
2131     }
2132     hr = IDirect3DSurface9_UnlockRect(surface);
2133     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed with %08x\n", hr);
2134 }
2135
2136 /* This tests a variety of possible StretchRect() situations */
2137 static void stretchrect_test(IDirect3DDevice9 *device)
2138 {
2139     HRESULT hr;
2140     IDirect3DTexture9 *tex_rt32 = NULL, *tex_rt64 = NULL, *tex_rt_dest64 = NULL;
2141     IDirect3DSurface9 *surf_tex_rt32 = NULL, *surf_tex_rt64 = NULL, *surf_tex_rt_dest64 = NULL;
2142     IDirect3DTexture9 *tex32 = NULL, *tex64 = NULL, *tex_dest64 = NULL;
2143     IDirect3DSurface9 *surf_tex32 = NULL, *surf_tex64 = NULL, *surf_tex_dest64 = NULL;
2144     IDirect3DSurface9 *surf_rt32 = NULL, *surf_rt64 = NULL, *surf_rt_dest64 = NULL;
2145     IDirect3DSurface9 *surf_offscreen32 = NULL, *surf_offscreen64 = NULL, *surf_offscreen_dest64 = NULL;
2146     IDirect3DSurface9 *surf_temp32 = NULL, *surf_temp64 = NULL;
2147     IDirect3DSurface9 *orig_rt = NULL;
2148     DWORD color;
2149
2150     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &orig_rt);
2151     ok(hr == D3D_OK, "Can't get render target, hr = %08x\n", hr);
2152     if(!orig_rt) {
2153         goto out;
2154     }
2155
2156     /* Create our temporary surfaces in system memory */
2157     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf_temp32, NULL);
2158     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2159     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf_temp64, NULL);
2160     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2161
2162     /* Create offscreen plain surfaces in D3DPOOL_DEFAULT */
2163     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_offscreen32, NULL);
2164     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2165     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_offscreen64, NULL);
2166     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2167     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_offscreen_dest64, NULL);
2168     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2169
2170     /* Create render target surfaces */
2171     hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &surf_rt32, NULL );
2172     ok(hr == D3D_OK, "Creating the render target surface failed with %08x\n", hr);
2173     hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &surf_rt64, NULL );
2174     ok(hr == D3D_OK, "Creating the render target surface failed with %08x\n", hr);
2175     hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &surf_rt_dest64, NULL );
2176     ok(hr == D3D_OK, "Creating the render target surface failed with %08x\n", hr);
2177
2178     /* Create render target textures */
2179     hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt32, NULL);
2180     ok(hr == D3D_OK, "Creating the render target texture failed with %08x\n", hr);
2181     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt64, NULL);
2182     ok(hr == D3D_OK, "Creating the render target texture failed with %08x\n", hr);
2183     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt_dest64, NULL);
2184     ok(hr == D3D_OK, "Creating the render target texture failed with %08x\n", hr);
2185     if (tex_rt32) {
2186         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt32, 0, &surf_tex_rt32);
2187         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2188     }
2189     if (tex_rt64) {
2190         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt64, 0, &surf_tex_rt64);
2191         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2192     }
2193     if (tex_rt_dest64) {
2194         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt_dest64, 0, &surf_tex_rt_dest64);
2195         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2196     }
2197
2198     /* Create regular textures in D3DPOOL_DEFAULT */
2199     hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex32, NULL);
2200     ok(hr == D3D_OK, "Creating the regular texture failed with %08x\n", hr);
2201     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex64, NULL);
2202     ok(hr == D3D_OK, "Creating the regular texture failed with %08x\n", hr);
2203     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_dest64, NULL);
2204     ok(hr == D3D_OK, "Creating the regular texture failed with %08x\n", hr);
2205     if (tex32) {
2206         hr = IDirect3DTexture9_GetSurfaceLevel(tex32, 0, &surf_tex32);
2207         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2208     }
2209     if (tex64) {
2210         hr = IDirect3DTexture9_GetSurfaceLevel(tex64, 0, &surf_tex64);
2211         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2212     }
2213     if (tex_dest64) {
2214         hr = IDirect3DTexture9_GetSurfaceLevel(tex_dest64, 0, &surf_tex_dest64);
2215         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2216     }
2217
2218     /*********************************************************************
2219      * Tests for when the source parameter is an offscreen plain surface *
2220      *********************************************************************/
2221
2222     /* Fill the offscreen 64x64 surface with green */
2223     if (surf_offscreen64)
2224         fill_surface(surf_offscreen64, 0xff00ff00);
2225
2226     /* offscreenplain ==> offscreenplain, same size */
2227     if(surf_offscreen64 && surf_offscreen_dest64) {
2228         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_offscreen_dest64, NULL, 0);
2229         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2230
2231         if (hr == D3D_OK) {
2232             color = getPixelColorFromSurface(surf_offscreen_dest64, 32, 32);
2233             ok(color == 0xff00ff00, "StretchRect offscreen ==> offscreen same size failed: Got color 0x%08x, expected 0xff00ff00.\n", color);
2234         }
2235     }
2236
2237     /* offscreenplain ==> rendertarget texture, same size */
2238     if(surf_offscreen64 && surf_tex_rt_dest64 && surf_temp64) {
2239         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_tex_rt_dest64, NULL, 0);
2240         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2241
2242         /* We can't lock rendertarget textures, so copy to our temp surface first */
2243         if (hr == D3D_OK) {
2244             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2245             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2246         }
2247
2248         if (hr == D3D_OK) {
2249             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2250             ok(color == 0xff00ff00, "StretchRect offscreen ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xff00ff00.\n", color);
2251         }
2252     }
2253
2254     /* offscreenplain ==> rendertarget surface, same size */
2255     if(surf_offscreen64 && surf_rt_dest64) {
2256         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_rt_dest64, NULL, 0);
2257         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2258
2259         if (hr == D3D_OK) {
2260             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2261             ok(color == 0xff00ff00, "StretchRect offscreen ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xff00ff00.\n", color);
2262         }
2263     }
2264
2265     /* offscreenplain ==> texture, same size (should fail) */
2266     if(surf_offscreen64 && surf_tex_dest64) {
2267         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_tex_dest64, NULL, 0);
2268         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2269     }
2270
2271     /* Fill the smaller offscreen surface with red */
2272     fill_surface(surf_offscreen32, 0xffff0000);
2273
2274     /* offscreenplain ==> offscreenplain, scaling (should fail) */
2275     if(surf_offscreen32 && surf_offscreen64) {
2276         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_offscreen64, NULL, 0);
2277         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2278     }
2279
2280     /* offscreenplain ==> rendertarget texture, scaling */
2281     if(surf_offscreen32 && surf_tex_rt_dest64 && surf_temp64) {
2282         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_tex_rt_dest64, NULL, 0);
2283         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2284
2285         /* We can't lock rendertarget textures, so copy to our temp surface first */
2286         if (hr == D3D_OK) {
2287             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2288             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2289         }
2290
2291         if (hr == D3D_OK) {
2292             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2293             ok(color == 0xffff0000, "StretchRect offscreen ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2294         }
2295     }
2296
2297     /* offscreenplain ==> rendertarget surface, scaling */
2298     if(surf_offscreen32 && surf_rt_dest64) {
2299         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_rt_dest64, NULL, 0);
2300         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2301
2302         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2303         ok(color == 0xffff0000, "StretchRect offscreen ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2304     }
2305
2306     /* offscreenplain ==> texture, scaling (should fail) */
2307     if(surf_offscreen32 && surf_tex_dest64) {
2308         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_tex_dest64, NULL, 0);
2309         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2310     }
2311
2312     /************************************************************
2313      * Tests for when the source parameter is a regular texture *
2314      ************************************************************/
2315
2316     /* Fill the surface of the regular texture with blue */
2317     if (surf_tex64 && surf_temp64) {
2318         /* Can't fill the surf_tex directly because it's created in D3DPOOL_DEFAULT */
2319         fill_surface(surf_temp64, 0xff0000ff);
2320         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp64, NULL, surf_tex64, NULL);
2321         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
2322     }
2323
2324     /* texture ==> offscreenplain, same size */
2325     if(surf_tex64 && surf_offscreen64) {
2326         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_offscreen64, NULL, 0);
2327         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2328     }
2329
2330     /* texture ==> rendertarget texture, same size */
2331     if(surf_tex64 && surf_tex_rt_dest64 && surf_temp64) {
2332         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_tex_rt_dest64, NULL, 0);
2333         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2334
2335         /* We can't lock rendertarget textures, so copy to our temp surface first */
2336         if (hr == D3D_OK) {
2337             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2338             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2339         }
2340
2341         if (hr == D3D_OK) {
2342             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2343             ok(color == 0xff0000ff, "StretchRect texture ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xff0000ff.\n", color);
2344         }
2345     }
2346
2347     /* texture ==> rendertarget surface, same size */
2348     if(surf_tex64 && surf_rt_dest64) {
2349         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_rt_dest64, NULL, 0);
2350         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2351
2352         if (hr == D3D_OK) {
2353             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2354             ok(color == 0xff0000ff, "StretchRect texture ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xff0000ff.\n", color);
2355         }
2356     }
2357
2358     /* texture ==> texture, same size (should fail) */
2359     if(surf_tex64 && surf_tex_dest64) {
2360         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_tex_dest64, NULL, 0);
2361         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2362     }
2363
2364     /* Fill the surface of the smaller regular texture with red */
2365     if (surf_tex32 && surf_temp32) {
2366         /* Can't fill the surf_tex directly because it's created in D3DPOOL_DEFAULT */
2367         fill_surface(surf_temp32, 0xffff0000);
2368         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp32, NULL, surf_tex32, NULL);
2369         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
2370     }
2371
2372     /* texture ==> offscreenplain, scaling (should fail) */
2373     if(surf_tex32 && surf_offscreen64) {
2374         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_offscreen64, NULL, 0);
2375         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2376     }
2377
2378     /* texture ==> rendertarget texture, scaling */
2379     if(surf_tex32 && surf_tex_rt_dest64 && surf_temp64) {
2380         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_tex_rt_dest64, NULL, 0);
2381         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2382
2383         /* We can't lock rendertarget textures, so copy to our temp surface first */
2384         if (hr == D3D_OK) {
2385             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2386             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2387         }
2388
2389         if (hr == D3D_OK) {
2390             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2391             ok(color == 0xffff0000, "StretchRect texture ==> rendertarget texture scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2392         }
2393     }
2394
2395     /* texture ==> rendertarget surface, scaling */
2396     if(surf_tex32 && surf_rt_dest64) {
2397         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_rt_dest64, NULL, 0);
2398         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2399
2400         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2401         ok(color == 0xffff0000, "StretchRect texture ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2402     }
2403
2404     /* texture ==> texture, scaling (should fail) */
2405     if(surf_tex32 && surf_tex_dest64) {
2406         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_tex_dest64, NULL, 0);
2407         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2408     }
2409
2410     /*****************************************************************
2411      * Tests for when the source parameter is a rendertarget texture *
2412      *****************************************************************/
2413
2414     /* Fill the surface of the rendertarget texture with white */
2415     if (surf_tex_rt64 && surf_temp64) {
2416         /* Can't fill the surf_tex_rt directly because it's created in D3DPOOL_DEFAULT */
2417         fill_surface(surf_temp64, 0xffffffff);
2418         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp64, NULL, surf_tex_rt64, NULL);
2419         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
2420     }
2421
2422     /* rendertarget texture ==> offscreenplain, same size */
2423     if(surf_tex_rt64 && surf_offscreen64) {
2424         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_offscreen64, NULL, 0);
2425         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2426     }
2427
2428     /* rendertarget texture ==> rendertarget texture, same size */
2429     if(surf_tex_rt64 && surf_tex_rt_dest64 && surf_temp64) {
2430         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_tex_rt_dest64, NULL, 0);
2431         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2432
2433         /* We can't lock rendertarget textures, so copy to our temp surface first */
2434         if (hr == D3D_OK) {
2435             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2436             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2437         }
2438
2439         if (hr == D3D_OK) {
2440             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2441             ok(color == 0xffffffff, "StretchRect rendertarget texture ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xffffffff.\n", color);
2442         }
2443     }
2444
2445     /* rendertarget texture ==> rendertarget surface, same size */
2446     if(surf_tex_rt64 && surf_rt_dest64) {
2447         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_rt_dest64, NULL, 0);
2448         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2449
2450         if (hr == D3D_OK) {
2451             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2452             ok(color == 0xffffffff, "StretchRect rendertarget texture ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xffffffff.\n", color);
2453         }
2454     }
2455
2456     /* rendertarget texture ==> texture, same size (should fail) */
2457     if(surf_tex_rt64 && surf_tex_dest64) {
2458         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_tex_dest64, NULL, 0);
2459         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2460     }
2461
2462     /* Fill the surface of the smaller rendertarget texture with red */
2463     if (surf_tex_rt32 && surf_temp32) {
2464         /* Can't fill the surf_tex_rt directly because it's created in D3DPOOL_DEFAULT */
2465         fill_surface(surf_temp32, 0xffff0000);
2466         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp32, NULL, surf_tex_rt32, NULL);
2467         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
2468     }
2469
2470     /* rendertarget texture ==> offscreenplain, scaling (should fail) */
2471     if(surf_tex_rt32 && surf_offscreen64) {
2472         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_offscreen64, NULL, 0);
2473         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2474     }
2475
2476     /* rendertarget texture ==> rendertarget texture, scaling */
2477     if(surf_tex_rt32 && surf_tex_rt_dest64 && surf_temp64) {
2478         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_tex_rt_dest64, NULL, 0);
2479         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2480
2481         /* We can't lock rendertarget textures, so copy to our temp surface first */
2482         if (hr == D3D_OK) {
2483             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2484             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2485         }
2486
2487         if (hr == D3D_OK) {
2488             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2489             ok(color == 0xffff0000, "StretchRect rendertarget texture ==> rendertarget texture scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2490         }
2491     }
2492
2493     /* rendertarget texture ==> rendertarget surface, scaling */
2494     if(surf_tex_rt32 && surf_rt_dest64) {
2495         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_rt_dest64, NULL, 0);
2496         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2497
2498         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2499         ok(color == 0xffff0000, "StretchRect rendertarget texture ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2500     }
2501
2502     /* rendertarget texture ==> texture, scaling (should fail) */
2503     if(surf_tex_rt32 && surf_tex_dest64) {
2504         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_tex_dest64, NULL, 0);
2505         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2506     }
2507
2508     /*****************************************************************
2509      * Tests for when the source parameter is a rendertarget surface *
2510      *****************************************************************/
2511
2512     /* Fill the surface of the rendertarget surface with black */
2513     if (surf_rt64)
2514         fill_surface(surf_rt64, 0xff000000);
2515
2516     /* rendertarget texture ==> offscreenplain, same size */
2517     if(surf_rt64 && surf_offscreen64) {
2518         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_offscreen64, NULL, 0);
2519         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2520     }
2521
2522     /* rendertarget surface ==> rendertarget texture, same size */
2523     if(surf_rt64 && surf_tex_rt_dest64 && surf_temp64) {
2524         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_tex_rt_dest64, NULL, 0);
2525         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2526
2527         /* We can't lock rendertarget textures, so copy to our temp surface first */
2528         if (hr == D3D_OK) {
2529             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2530             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2531         }
2532
2533         if (hr == D3D_OK) {
2534             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2535             ok(color == 0xff000000, "StretchRect rendertarget surface ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xff000000.\n", color);
2536         }
2537     }
2538
2539     /* rendertarget surface ==> rendertarget surface, same size */
2540     if(surf_rt64 && surf_rt_dest64) {
2541         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_rt_dest64, NULL, 0);
2542         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2543
2544         if (hr == D3D_OK) {
2545             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2546             ok(color == 0xff000000, "StretchRect rendertarget surface ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xff000000.\n", color);
2547         }
2548     }
2549
2550     /* rendertarget surface ==> texture, same size (should fail) */
2551     if(surf_rt64 && surf_tex_dest64) {
2552         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_tex_dest64, NULL, 0);
2553         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2554     }
2555
2556     /* Fill the surface of the smaller rendertarget texture with red */
2557     if (surf_rt32)
2558         fill_surface(surf_rt32, 0xffff0000);
2559
2560     /* rendertarget surface ==> offscreenplain, scaling (should fail) */
2561     if(surf_rt32 && surf_offscreen64) {
2562         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_offscreen64, NULL, 0);
2563         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2564     }
2565
2566     /* rendertarget surface ==> rendertarget texture, scaling */
2567     if(surf_rt32 && surf_tex_rt_dest64 && surf_temp64) {
2568         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_tex_rt_dest64, NULL, 0);
2569         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2570
2571         /* We can't lock rendertarget textures, so copy to our temp surface first */
2572         if (hr == D3D_OK) {
2573             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2574             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2575         }
2576
2577         if (hr == D3D_OK) {
2578             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2579             ok(color == 0xffff0000, "StretchRect rendertarget surface ==> rendertarget texture scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2580         }
2581     }
2582
2583     /* rendertarget surface ==> rendertarget surface, scaling */
2584     if(surf_rt32 && surf_rt_dest64) {
2585         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_rt_dest64, NULL, 0);
2586         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2587
2588         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2589         ok(color == 0xffff0000, "StretchRect rendertarget surface ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2590     }
2591
2592     /* rendertarget surface ==> texture, scaling (should fail) */
2593     if(surf_rt32 && surf_tex_dest64) {
2594         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_tex_dest64, NULL, 0);
2595         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2596     }
2597
2598     /* TODO: Test when source and destination RECT parameters are given... */
2599     /* TODO: Test format conversions */
2600
2601
2602 out:
2603     /* Clean up */
2604     if (surf_rt32)
2605         IDirect3DSurface9_Release(surf_rt32);
2606     if (surf_rt64)
2607         IDirect3DSurface9_Release(surf_rt64);
2608     if (surf_rt_dest64)
2609         IDirect3DSurface9_Release(surf_rt_dest64);
2610     if (surf_temp32)
2611         IDirect3DSurface9_Release(surf_temp32);
2612     if (surf_temp64)
2613         IDirect3DSurface9_Release(surf_temp64);
2614     if (surf_offscreen32)
2615         IDirect3DSurface9_Release(surf_offscreen32);
2616     if (surf_offscreen64)
2617         IDirect3DSurface9_Release(surf_offscreen64);
2618     if (surf_offscreen_dest64)
2619         IDirect3DSurface9_Release(surf_offscreen_dest64);
2620
2621     if (tex_rt32) {
2622         if (surf_tex_rt32)
2623             IDirect3DSurface9_Release(surf_tex_rt32);
2624         IDirect3DTexture9_Release(tex_rt32);
2625     }
2626     if (tex_rt64) {
2627         if (surf_tex_rt64)
2628             IDirect3DSurface9_Release(surf_tex_rt64);
2629         IDirect3DTexture9_Release(tex_rt64);
2630     }
2631     if (tex_rt_dest64) {
2632         if (surf_tex_rt_dest64)
2633             IDirect3DSurface9_Release(surf_tex_rt_dest64);
2634         IDirect3DTexture9_Release(tex_rt_dest64);
2635     }
2636     if (tex32) {
2637         if (surf_tex32)
2638             IDirect3DSurface9_Release(surf_tex32);
2639         IDirect3DTexture9_Release(tex32);
2640     }
2641     if (tex64) {
2642         if (surf_tex64)
2643             IDirect3DSurface9_Release(surf_tex64);
2644         IDirect3DTexture9_Release(tex64);
2645     }
2646     if (tex_dest64) {
2647         if (surf_tex_dest64)
2648             IDirect3DSurface9_Release(surf_tex_dest64);
2649         IDirect3DTexture9_Release(tex_dest64);
2650     }
2651
2652     if (orig_rt) {
2653         hr = IDirect3DDevice9_SetRenderTarget(device, 0, orig_rt);
2654         ok(hr == D3D_OK, "IDirect3DSetRenderTarget failed with %08x\n", hr);
2655         IDirect3DSurface9_Release(orig_rt);
2656     }
2657 }
2658
2659 static void maxmip_test(IDirect3DDevice9 *device)
2660 {
2661     IDirect3DTexture9 *texture = NULL;
2662     IDirect3DSurface9 *surface = NULL;
2663     HRESULT hr;
2664     DWORD color;
2665     const float quads[] = {
2666         -1.0,   -1.0,   0.0,    0.0,    0.0,
2667         -1.0,    0.0,   0.0,    0.0,    1.0,
2668          0.0,   -1.0,   0.0,    1.0,    0.0,
2669          0.0,    0.0,   0.0,    1.0,    1.0,
2670
2671          0.0,   -1.0,   0.0,    0.0,    0.0,
2672          0.0,    0.0,   0.0,    0.0,    1.0,
2673          1.0,   -1.0,   0.0,    1.0,    0.0,
2674          1.0,    0.0,   0.0,    1.0,    1.0,
2675
2676          0.0,    0.0,   0.0,    0.0,    0.0,
2677          0.0,    1.0,   0.0,    0.0,    1.0,
2678          1.0,    0.0,   0.0,    1.0,    0.0,
2679          1.0,    1.0,   0.0,    1.0,    1.0,
2680
2681         -1.0,    0.0,   0.0,    0.0,    0.0,
2682         -1.0,    1.0,   0.0,    0.0,    1.0,
2683          0.0,    0.0,   0.0,    1.0,    0.0,
2684          0.0,    1.0,   0.0,    1.0,    1.0,
2685     };
2686
2687     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
2688     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
2689
2690     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
2691                                         &texture, NULL);
2692     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
2693     if(!texture)
2694     {
2695         skip("Failed to create test texture\n");
2696         return;
2697     }
2698
2699     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
2700     fill_surface(surface, 0xffff0000);
2701     IDirect3DSurface9_Release(surface);
2702     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface);
2703     fill_surface(surface, 0xff00ff00);
2704     IDirect3DSurface9_Release(surface);
2705     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
2706     fill_surface(surface, 0xff0000ff);
2707     IDirect3DSurface9_Release(surface);
2708
2709     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
2710     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
2711     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2712     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
2713
2714     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
2715     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2716
2717     hr = IDirect3DDevice9_BeginScene(device);
2718     if(SUCCEEDED(hr))
2719     {
2720         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
2721         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2722         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[ 0], 5 * sizeof(float));
2723         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2724
2725         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
2726         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2727         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[20], 5 * sizeof(float));
2728         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2729
2730         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
2731         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2732         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[40], 5 * sizeof(float));
2733         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2734
2735         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
2736         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2737         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[60], 5 * sizeof(float));
2738         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2739         hr = IDirect3DDevice9_EndScene(device);
2740     }
2741
2742     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2743     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2744     /* With mipmapping disabled, the max mip level is ignored, only level 0 is used */
2745     color = getPixelColor(device, 160, 360);
2746     ok(color == 0x00FF0000, "MapMip 0, no mipfilter has color %08x\n", color);
2747     color = getPixelColor(device, 160, 120);
2748     ok(color == 0x00FF0000, "MapMip 3, no mipfilter has color %08x\n", color);
2749     color = getPixelColor(device, 480, 120);
2750     ok(color == 0x00FF0000, "MapMip 2, no mipfilter has color %08x\n", color);
2751     color = getPixelColor(device, 480, 360);
2752     ok(color == 0x00FF0000, "MapMip 1, no mipfilter has color %08x\n", color);
2753
2754     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
2755     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
2756
2757     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
2758     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2759
2760     hr = IDirect3DDevice9_BeginScene(device);
2761     if(SUCCEEDED(hr))
2762     {
2763         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
2764         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2765         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[ 0], 5 * sizeof(float));
2766         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2767
2768         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
2769         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2770         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[20], 5 * sizeof(float));
2771         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2772
2773         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
2774         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2775         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[40], 5 * sizeof(float));
2776         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2777
2778         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
2779         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2780         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[60], 5 * sizeof(float));
2781         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2782         hr = IDirect3DDevice9_EndScene(device);
2783     }
2784
2785     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
2786     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2787     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
2788     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2789
2790     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2791     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2792     /* Max Mip level 0-2 sample from the specified texture level, Max Mip level 3(> levels in texture)
2793      * samples from the highest level in the texture(level 2)
2794      */
2795     color = getPixelColor(device, 160, 360);
2796     ok(color == 0x00FF0000, "MapMip 0, point mipfilter has color %08x\n", color);
2797     color = getPixelColor(device, 160, 120);
2798     ok(color == 0x000000FF, "MapMip 3, point mipfilter has color %08x\n", color);
2799     color = getPixelColor(device, 480, 120);
2800     ok(color == 0x000000FF, "MapMip 2, point mipfilter has color %08x\n", color);
2801     color = getPixelColor(device, 480, 360);
2802     ok(color == 0x0000FF00, "MapMip 1, point mipfilter has color %08x\n", color);
2803
2804     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
2805     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
2806     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
2807     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2808     IDirect3DTexture9_Release(texture);
2809 }
2810
2811 static void release_buffer_test(IDirect3DDevice9 *device)
2812 {
2813     IDirect3DVertexBuffer9 *vb = NULL;
2814     IDirect3DIndexBuffer9 *ib = NULL;
2815     HRESULT hr;
2816     BYTE *data;
2817     long ref;
2818
2819     static const struct vertex quad[] = {
2820         {-1.0,      -1.0,       0.1,        0xffff0000},
2821         {-1.0,       1.0,       0.1,        0xffff0000},
2822         { 1.0,       1.0,       0.1,        0xffff0000},
2823
2824         {-1.0,      -1.0,       0.1,        0xff00ff00},
2825         {-1.0,       1.0,       0.1,        0xff00ff00},
2826         { 1.0,       1.0,       0.1,        0xff00ff00}
2827     };
2828     short indices[] = {3, 4, 5};
2829
2830     /* Index and vertex buffers should always be creatable */
2831     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, D3DFVF_XYZ | D3DFVF_DIFFUSE,
2832                                               D3DPOOL_MANAGED, &vb, NULL);
2833     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
2834     if(!vb) {
2835         skip("Failed to create a vertex buffer\n");
2836         return;
2837     }
2838     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, NULL);
2839     ok(hr == D3D_OK, "IDirect3DDevice9_CreateIndexBuffer failed with %08x\n", hr);
2840     if(!ib) {
2841         skip("Failed to create an index buffer\n");
2842         return;
2843     }
2844
2845     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), (void **) &data, 0);
2846     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
2847     memcpy(data, quad, sizeof(quad));
2848     hr = IDirect3DVertexBuffer9_Unlock(vb);
2849     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
2850
2851     hr = IDirect3DIndexBuffer9_Lock(ib, 0, sizeof(indices), (void **) &data, 0);
2852     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Lock failed with %08x\n", hr);
2853     memcpy(data, indices, sizeof(indices));
2854     hr = IDirect3DIndexBuffer9_Unlock(ib);
2855     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
2856
2857     hr = IDirect3DDevice9_SetIndices(device, ib);
2858     ok(hr == D3D_OK, "IDirect3DDevice9_SetIndices failed with %08x\n", hr);
2859     hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad[0]));
2860     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
2861     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
2862     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
2863
2864     /* Now destroy the bound index buffer and draw again */
2865     ref = IDirect3DIndexBuffer9_Release(ib);
2866     ok(ref == 0, "Index Buffer reference count is %08ld\n", ref);
2867
2868     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
2869     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2870
2871     hr = IDirect3DDevice9_BeginScene(device);
2872     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2873     if(SUCCEEDED(hr))
2874     {
2875         /* Deliberately using minvertexindex = 0 and numVertices = 6 to prevent d3d from
2876          * making assumptions about the indices or vertices
2877          */
2878         hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 3, 3, 0, 1);
2879         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitive failed with %08x\n", hr);
2880         hr = IDirect3DDevice9_EndScene(device);
2881         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2882     }
2883
2884     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2885     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
2886
2887     hr = IDirect3DDevice9_SetIndices(device, NULL);
2888     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
2889     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2890     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
2891
2892     /* Index buffer was already destroyed as part of the test */
2893     IDirect3DVertexBuffer9_Release(vb);
2894 }
2895
2896 static void float_texture_test(IDirect3DDevice9 *device)
2897 {
2898     IDirect3D9 *d3d = NULL;
2899     HRESULT hr;
2900     IDirect3DTexture9 *texture = NULL;
2901     D3DLOCKED_RECT lr;
2902     float *data;
2903     DWORD color;
2904     float quad[] = {
2905         -1.0,      -1.0,       0.1,     0.0,    0.0,
2906         -1.0,       1.0,       0.1,     0.0,    1.0,
2907          1.0,      -1.0,       0.1,     1.0,    0.0,
2908          1.0,       1.0,       0.1,     1.0,    1.0,
2909     };
2910
2911     memset(&lr, 0, sizeof(lr));
2912     IDirect3DDevice9_GetDirect3D(device, &d3d);
2913     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
2914                                      D3DRTYPE_TEXTURE, D3DFMT_R32F) != D3D_OK) {
2915         skip("D3DFMT_R32F textures not supported\n");
2916         goto out;
2917     }
2918
2919     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_R32F,
2920                                         D3DPOOL_MANAGED, &texture, NULL);
2921     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
2922     if(!texture) {
2923         skip("Failed to create R32F texture\n");
2924         goto out;
2925     }
2926
2927     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
2928     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %08x\n", hr);
2929     data = lr.pBits;
2930     *data = 0.0;
2931     hr = IDirect3DTexture9_UnlockRect(texture, 0);
2932     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %08x\n", hr);
2933
2934     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
2935     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
2936
2937     hr = IDirect3DDevice9_BeginScene(device);
2938     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2939     if(SUCCEEDED(hr))
2940     {
2941         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2942         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
2943
2944         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
2945         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2946
2947         hr = IDirect3DDevice9_EndScene(device);
2948         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2949     }
2950     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
2951     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
2952
2953     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2954     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
2955
2956     color = getPixelColor(device, 240, 320);
2957     ok(color == 0x0000FFFF, "R32F with value 0.0 has color %08x, expected 0x0000FFFF\n", color);
2958
2959 out:
2960     if(texture) IDirect3DTexture9_Release(texture);
2961     IDirect3D9_Release(d3d);
2962 }
2963
2964 static void g16r16_texture_test(IDirect3DDevice9 *device)
2965 {
2966     IDirect3D9 *d3d = NULL;
2967     HRESULT hr;
2968     IDirect3DTexture9 *texture = NULL;
2969     D3DLOCKED_RECT lr;
2970     DWORD *data;
2971     DWORD color, red, green, blue;
2972     float quad[] = {
2973        -1.0,      -1.0,       0.1,     0.0,    0.0,
2974        -1.0,       1.0,       0.1,     0.0,    1.0,
2975         1.0,      -1.0,       0.1,     1.0,    0.0,
2976         1.0,       1.0,       0.1,     1.0,    1.0,
2977     };
2978
2979     memset(&lr, 0, sizeof(lr));
2980     IDirect3DDevice9_GetDirect3D(device, &d3d);
2981     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
2982        D3DRTYPE_TEXTURE, D3DFMT_G16R16) != D3D_OK) {
2983            skip("D3DFMT_G16R16 textures not supported\n");
2984            goto out;
2985     }
2986
2987     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_G16R16,
2988                                         D3DPOOL_MANAGED, &texture, NULL);
2989     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
2990     if(!texture) {
2991         skip("Failed to create D3DFMT_G16R16 texture\n");
2992         goto out;
2993     }
2994
2995     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
2996     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %08x\n", hr);
2997     data = lr.pBits;
2998     *data = 0x0f00f000;
2999     hr = IDirect3DTexture9_UnlockRect(texture, 0);
3000     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %08x\n", hr);
3001
3002     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3003     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3004
3005     hr = IDirect3DDevice9_BeginScene(device);
3006     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3007     if(SUCCEEDED(hr))
3008     {
3009         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3010         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3011
3012         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
3013         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3014
3015         hr = IDirect3DDevice9_EndScene(device);
3016         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3017     }
3018     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3019     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3020
3021     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3022     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3023
3024     color = getPixelColor(device, 240, 320);
3025     red   = (color & 0x00ff0000) >> 16;
3026     green = (color & 0x0000ff00) >>  8;
3027     blue  = (color & 0x000000ff) >>  0;
3028     ok(blue == 0xff && red >= 0xef && red <= 0xf1 && green >= 0x0e && green <= 0x10,
3029        "D3DFMT_G16R16 with value 0x00ffff00 has color %08x, expected 0x00F00FFF\n", color);
3030
3031 out:
3032     if(texture) IDirect3DTexture9_Release(texture);
3033     IDirect3D9_Release(d3d);
3034 }
3035
3036 static void texture_transform_flags_test(IDirect3DDevice9 *device)
3037 {
3038     HRESULT hr;
3039     IDirect3D9 *d3d;
3040     D3DFORMAT fmt = D3DFMT_X8R8G8B8;
3041     D3DCAPS9 caps;
3042     IDirect3DTexture9 *texture = NULL;
3043     IDirect3DVolumeTexture9 *volume = NULL;
3044     unsigned int x, y, z;
3045     D3DLOCKED_RECT lr;
3046     D3DLOCKED_BOX lb;
3047     DWORD color;
3048     UINT w, h;
3049     IDirect3DVertexDeclaration9 *decl, *decl2, *decl3;
3050     float identity[16] = {1.0, 0.0, 0.0, 0.0,
3051                            0.0, 1.0, 0.0, 0.0,
3052                            0.0, 0.0, 1.0, 0.0,
3053                            0.0, 0.0, 0.0, 1.0};
3054     static const D3DVERTEXELEMENT9 decl_elements[] = {
3055         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3056         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3057         D3DDECL_END()
3058     };
3059     static const D3DVERTEXELEMENT9 decl_elements2[] = {
3060         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3061         {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3062         D3DDECL_END()
3063     };
3064     static const D3DVERTEXELEMENT9 decl_elements3[] = {
3065         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3066         {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3067         D3DDECL_END()
3068     };
3069     static const unsigned char proj_texdata[] = {0x00, 0x00, 0x00, 0x00,
3070                                                  0x00, 0xff, 0x00, 0x00,
3071                                                  0x00, 0x00, 0x00, 0x00,
3072                                                  0x00, 0x00, 0x00, 0x00};
3073
3074     memset(&lr, 0, sizeof(lr));
3075     memset(&lb, 0, sizeof(lb));
3076     IDirect3DDevice9_GetDirect3D(device, &d3d);
3077     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
3078                                      D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16) == D3D_OK) {
3079         fmt = D3DFMT_A16B16G16R16;
3080     }
3081     IDirect3D9_Release(d3d);
3082
3083     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
3084     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
3085     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements2, &decl2);
3086     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
3087     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements3, &decl3);
3088     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
3089     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, FALSE);
3090     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_SRGBTEXTURE) returned %08x\n", hr);
3091     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
3092     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MAGFILTER) returned %08x\n", hr);
3093     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
3094     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MINFILTER) returned %08x\n", hr);
3095     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
3096     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MIPFILTER) returned %08x\n", hr);
3097     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
3098     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSU) returned %08x\n", hr);
3099     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
3100     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSV) returned %08x\n", hr);
3101     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP);
3102     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSW) returned %08x\n", hr);
3103     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
3104     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState(D3DRS_LIGHTING) returned %08x\n", hr);
3105     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
3106     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3107
3108     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3109     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %08x\n", hr);
3110     w = min(1024, caps.MaxTextureWidth);
3111     h = min(1024, caps.MaxTextureHeight);
3112     hr = IDirect3DDevice9_CreateTexture(device, w, h, 1,
3113                                         0, fmt, D3DPOOL_MANAGED, &texture, NULL);
3114     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
3115     if(!texture) {
3116         skip("Failed to create the test texture\n");
3117         return;
3118     }
3119
3120     /* Unfortunately there is no easy way to set up a texture coordinate passthrough
3121      * in d3d fixed function pipeline, so create a texture that has a gradient from 0.0 to
3122      * 1.0 in red and green for the x and y coords
3123      */
3124     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
3125     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %08x\n", hr);
3126     for(y = 0; y < h; y++) {
3127         for(x = 0; x < w; x++) {
3128             double r_f = (double) y / (double) h;
3129             double g_f = (double) x / (double) w;
3130             if(fmt == D3DFMT_A16B16G16R16) {
3131                 unsigned short r, g;
3132                 unsigned short *dst = (unsigned short *) (((char *) lr.pBits) + y * lr.Pitch + x * 8);
3133                 r = (unsigned short) (r_f * 65536.0);
3134                 g = (unsigned short) (g_f * 65536.0);
3135                 dst[0] = r;
3136                 dst[1] = g;
3137                 dst[2] = 0;
3138                 dst[3] = 65535;
3139             } else {
3140                 unsigned char *dst = ((unsigned char *) lr.pBits) + y * lr.Pitch + x * 4;
3141                 unsigned char r = (unsigned char) (r_f * 255.0);
3142                 unsigned char g = (unsigned char) (g_f * 255.0);
3143                 dst[0] = 0;
3144                 dst[1] = g;
3145                 dst[2] = r;
3146                 dst[3] = 255;
3147             }
3148         }
3149     }
3150     hr = IDirect3DTexture9_UnlockRect(texture, 0);
3151     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect returned %08x\n", hr);
3152     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3153     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
3154
3155     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3156     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3157     hr = IDirect3DDevice9_BeginScene(device);
3158     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3159     if(SUCCEEDED(hr))
3160     {
3161         float quad1[] = {
3162             -1.0,      -1.0,       0.1,     1.0,    1.0,
3163             -1.0,       0.0,       0.1,     1.0,    1.0,
3164              0.0,      -1.0,       0.1,     1.0,    1.0,
3165              0.0,       0.0,       0.1,     1.0,    1.0,
3166         };
3167         float quad2[] = {
3168             -1.0,       0.0,       0.1,     1.0,    1.0,
3169             -1.0,       1.0,       0.1,     1.0,    1.0,
3170              0.0,       0.0,       0.1,     1.0,    1.0,
3171              0.0,       1.0,       0.1,     1.0,    1.0,
3172         };
3173         float quad3[] = {
3174              0.0,       0.0,       0.1,     0.5,    0.5,
3175              0.0,       1.0,       0.1,     0.5,    0.5,
3176              1.0,       0.0,       0.1,     0.5,    0.5,
3177              1.0,       1.0,       0.1,     0.5,    0.5,
3178         };
3179         float quad4[] = {
3180              320,       480,       0.1,     1.0,    0.0,    1.0,
3181              320,       240,       0.1,     1.0,    0.0,    1.0,
3182              640,       480,       0.1,     1.0,    0.0,    1.0,
3183              640,       240,       0.1,     1.0,    0.0,    1.0,
3184         };
3185         float mat[16] = {0.0, 0.0, 0.0, 0.0,
3186                           0.0, 0.0, 0.0, 0.0,
3187                           0.0, 0.0, 0.0, 0.0,
3188                           0.0, 0.0, 0.0, 0.0};
3189
3190         /* What happens with the texture matrix if D3DTSS_TEXTURETRANSFORMFLAGS is disabled? */
3191         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3192         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3193         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
3194         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3195
3196         /* What happens with transforms enabled? */
3197         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3198         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3199         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
3200         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3201
3202         /* What happens if 4 coords are used, but only 2 given ?*/
3203         mat[8] = 1.0;
3204         mat[13] = 1.0;
3205         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3206         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3207         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
3208         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3209         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
3210         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3211
3212         /* What happens with transformed geometry? This setup lead to 0/0 coords with untransformed
3213          * geometry. If the same applies to transformed vertices, the quad will be black, otherwise red,
3214          * due to the coords in the vertices. (turns out red, indeed)
3215          */
3216         memset(mat, 0, sizeof(mat));
3217         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3218         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3219         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_TEX1);
3220         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3221         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3222         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3223         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
3224         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3225
3226         hr = IDirect3DDevice9_EndScene(device);
3227         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3228     }
3229     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3230     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3231     color = getPixelColor(device, 160, 360);
3232     ok(color == 0x00FFFF00 || color == 0x00FEFE00, "quad 1 has color %08x, expected 0x00FFFF00\n", color);
3233     color = getPixelColor(device, 160, 120);
3234     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
3235     color = getPixelColor(device, 480, 120);
3236     ok(color == 0x0000FF00 || color == 0x0000FE00, "quad 3 has color %08x, expected 0x0000FF00\n", color);
3237     color = getPixelColor(device, 480, 360);
3238     ok(color == 0x00FF0000 || 0x00FE0000, "quad 4 has color %08x, expected 0x00FF0000\n", color);
3239
3240     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
3241     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3242
3243     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3244     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3245     hr = IDirect3DDevice9_BeginScene(device);
3246     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3247     if(SUCCEEDED(hr))
3248     {
3249         float quad1[] = {
3250             -1.0,      -1.0,       0.1,     0.8,    0.2,
3251             -1.0,       0.0,       0.1,     0.8,    0.2,
3252              0.0,      -1.0,       0.1,     0.8,    0.2,
3253              0.0,       0.0,       0.1,     0.8,    0.2,
3254         };
3255         float quad2[] = {
3256             -1.0,       0.0,       0.1,     0.5,    1.0,
3257             -1.0,       1.0,       0.1,     0.5,    1.0,
3258              0.0,       0.0,       0.1,     0.5,    1.0,
3259              0.0,       1.0,       0.1,     0.5,    1.0,
3260         };
3261         float quad3[] = {
3262              0.0,       0.0,       0.1,     0.5,    1.0,
3263              0.0,       1.0,       0.1,     0.5,    1.0,
3264              1.0,       0.0,       0.1,     0.5,    1.0,
3265              1.0,       1.0,       0.1,     0.5,    1.0,
3266         };
3267         float quad4[] = {
3268              0.0,      -1.0,       0.1,     0.8,    0.2,
3269              0.0,       0.0,       0.1,     0.8,    0.2,
3270              1.0,      -1.0,       0.1,     0.8,    0.2,
3271              1.0,       0.0,       0.1,     0.8,    0.2,
3272         };
3273         float mat[16] = {0.0, 0.0, 0.0, 0.0,
3274                           0.0, 0.0, 0.0, 0.0,
3275                           0.0, 1.0, 0.0, 0.0,
3276                           0.0, 0.0, 0.0, 0.0};
3277
3278         /* What happens to the default 1 in the 3rd coordinate if it is disabled?
3279          */
3280         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3281         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3282         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3283         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3284
3285         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
3286         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3287
3288         /* D3DTFF_COUNT1 does not work on Nvidia drivers. It behaves like D3DTTFF_DISABLE. On ATI drivers
3289          * it behaves like COUNT2 because normal textures require 2 coords
3290          */
3291         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
3292         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3293         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 5 * sizeof(float));
3294         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3295
3296         /* Just to be sure, the same as quad2 above */
3297         memset(mat, 0, sizeof(mat));
3298         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3299         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3300         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3301         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3302         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
3303         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3304
3305         /* Now, what happens to the 2nd coordinate(that is disabled in the matrix) if it is not
3306          * used? And what happens to the first?
3307          */
3308         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
3309         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3310         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
3311         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3312
3313         hr = IDirect3DDevice9_EndScene(device);
3314         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3315     }
3316     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3317     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3318     color = getPixelColor(device, 160, 360);
3319     ok(color == 0x00FF0000 || color == 0x00FE0000, "quad 1 has color %08x, expected 0x00FF0000\n", color);
3320     color = getPixelColor(device, 160, 120);
3321     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
3322     color = getPixelColor(device, 480, 120);
3323     ok(color == 0x00ff8000 || color == 0x00fe7f00 || color == 0x00000000,
3324        "quad 3 has color %08x, expected 0x00ff8000\n", color);
3325     color = getPixelColor(device, 480, 360);
3326     ok(color == 0x0033cc00 || color == 0x0032cb00 || color == 0x00FF0000 || color == 0x00FE0000,
3327        "quad 4 has color %08x, expected 0x0033cc00\n", color);
3328
3329     IDirect3DTexture9_Release(texture);
3330
3331     /* Test projected textures, without any fancy matrices */
3332     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff203040, 0.0, 0);
3333     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3334     hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_L8, D3DPOOL_MANAGED, &texture, NULL);
3335     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
3336     hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &identity);
3337     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3338     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl3);
3339     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
3340
3341     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
3342     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %08x\n", hr);
3343     for(x = 0; x < 4; x++) {
3344         memcpy(((BYTE *) lr.pBits) + lr.Pitch * x, proj_texdata + 4 * x, 4 * sizeof(proj_texdata[0]));
3345     }
3346     hr = IDirect3DTexture9_UnlockRect(texture, 0);
3347     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %08x\n", hr);
3348     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3349     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3350
3351     hr = IDirect3DDevice9_BeginScene(device);
3352     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3353     if(SUCCEEDED(hr))
3354     {
3355         const float proj_quads[] = {
3356            -1.0,   -1.0,    0.1,    0.0,    0.0,    4.0,    6.0,
3357             1.0,   -1.0,    0.1,    4.0,    0.0,    4.0,    6.0,
3358            -1.0,    0.0,    0.1,    0.0,    4.0,    4.0,    6.0,
3359             1.0,    0.0,    0.1,    4.0,    4.0,    4.0,    6.0,
3360            -1.0,    0.0,    0.1,    0.0,    0.0,    4.0,    6.0,
3361             1.0,    0.0,    0.1,    4.0,    0.0,    4.0,    6.0,
3362            -1.0,    1.0,    0.1,    0.0,    4.0,    4.0,    6.0,
3363             1.0,    1.0,    0.1,    4.0,    4.0,    4.0,    6.0,
3364         };
3365
3366         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4 | D3DTTFF_PROJECTED);
3367         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3368         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &proj_quads[0*7], 7 * sizeof(float));
3369         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3370
3371         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3 | D3DTTFF_PROJECTED);
3372         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3373         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &proj_quads[4*7], 7 * sizeof(float));
3374         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3375
3376         hr = IDirect3DDevice9_EndScene(device);
3377         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3378     }
3379
3380     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3381     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3382     IDirect3DTexture9_Release(texture);
3383
3384     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3385     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3386     color = getPixelColor(device, 158, 118);
3387     ok(color == 0x00000000, "proj: Pixel 158/118 has color 0x%08x, expected 0x00000000\n", color);
3388     color = getPixelColor(device, 162, 118);
3389     ok(color == 0x00000000, "proj: Pixel 162/118 has color 0x%08x, expected 0x00000000\n", color);
3390     color = getPixelColor(device, 158, 122);
3391     ok(color == 0x00000000, "proj: Pixel 158/122 has color 0x%08x, expected 0x00000000\n", color);
3392     color = getPixelColor(device, 162, 122);
3393     ok(color == 0x00FFFFFF, "proj: Pixel 162/122 has color 0x%08x, expected 0x00FFFFFF\n", color);
3394
3395     color = getPixelColor(device, 158, 178);
3396     ok(color == 0x00000000, "proj: Pixel 158/178 has color 0x%08x, expected 0x00000000\n", color);
3397     color = getPixelColor(device, 162, 178);
3398     ok(color == 0x00FFFFFF, "proj: Pixel 158/178 has color 0x%08x, expected 0x00FFFFFF\n", color);
3399     color = getPixelColor(device, 158, 182);
3400     ok(color == 0x00000000, "proj: Pixel 158/182 has color 0x%08x, expected 0x00000000\n", color);
3401     color = getPixelColor(device, 162, 182);
3402     ok(color == 0x00000000, "proj: Pixel 158/182 has color 0x%08x, expected 0x00000000\n", color);
3403
3404     color = getPixelColor(device, 318, 118);
3405     ok(color == 0x00000000, "proj: Pixel 318/118 has color 0x%08x, expected 0x00000000\n", color);
3406     color = getPixelColor(device, 322, 118);
3407     ok(color == 0x00000000, "proj: Pixel 322/118 has color 0x%08x, expected 0x00000000\n", color);
3408     color = getPixelColor(device, 318, 122);
3409     ok(color == 0x00FFFFFF, "proj: Pixel 318/122 has color 0x%08x, expected 0x00FFFFFF\n", color);
3410     color = getPixelColor(device, 322, 122);
3411     ok(color == 0x00000000, "proj: Pixel 322/122 has color 0x%08x, expected 0x00000000\n", color);
3412
3413     color = getPixelColor(device, 318, 178);
3414     ok(color == 0x00FFFFFF, "proj: Pixel 318/178 has color 0x%08x, expected 0x00FFFFFF\n", color);
3415     color = getPixelColor(device, 322, 178);
3416     ok(color == 0x00000000, "proj: Pixel 322/178 has color 0x%08x, expected 0x00000000\n", color);
3417     color = getPixelColor(device, 318, 182);
3418     ok(color == 0x00000000, "proj: Pixel 318/182 has color 0x%08x, expected 0x00000000\n", color);
3419     color = getPixelColor(device, 322, 182);
3420     ok(color == 0x00000000, "proj: Pixel 322/182 has color 0x%08x, expected 0x00000000\n", color);
3421
3422     color = getPixelColor(device, 238, 298);
3423     ok(color == 0x00000000, "proj: Pixel 238/298 has color 0x%08x, expected 0x00000000\n", color);
3424     color = getPixelColor(device, 242, 298);
3425     ok(color == 0x00000000, "proj: Pixel 242/298 has color 0x%08x, expected 0x00000000\n", color);
3426     color = getPixelColor(device, 238, 302);
3427     ok(color == 0x00000000, "proj: Pixel 238/302 has color 0x%08x, expected 0x00000000\n", color);
3428     color = getPixelColor(device, 242, 302);
3429     ok(color == 0x00FFFFFF, "proj: Pixel 242/302 has color 0x%08x, expected 0x00FFFFFF\n", color);
3430
3431     color = getPixelColor(device, 238, 388);
3432     ok(color == 0x00000000, "proj: Pixel 238/388 has color 0x%08x, expected 0x00000000\n", color);
3433     color = getPixelColor(device, 242, 388);
3434     ok(color == 0x00FFFFFF, "proj: Pixel 242/388 has color 0x%08x, expected 0x00FFFFFF\n", color);
3435     color = getPixelColor(device, 238, 392);
3436     ok(color == 0x00000000, "proj: Pixel 238/392 has color 0x%08x, expected 0x00000000\n", color);
3437     color = getPixelColor(device, 242, 392);
3438     ok(color == 0x00000000, "proj: Pixel 242/392 has color 0x%08x, expected 0x00000000\n", color);
3439
3440     color = getPixelColor(device, 478, 298);
3441     ok(color == 0x00000000, "proj: Pixel 478/298 has color 0x%08x, expected 0x00000000\n", color);
3442     color = getPixelColor(device, 482, 298);
3443     ok(color == 0x00000000, "proj: Pixel 482/298 has color 0x%08x, expected 0x00000000\n", color);
3444     color = getPixelColor(device, 478, 302);
3445     ok(color == 0x00FFFFFF, "proj: Pixel 478/302 has color 0x%08x, expected 0x00FFFFFF\n", color);
3446     color = getPixelColor(device, 482, 302);
3447     ok(color == 0x00000000, "proj: Pixel 482/302 has color 0x%08x, expected 0x00000000\n", color);
3448
3449     color = getPixelColor(device, 478, 388);
3450     ok(color == 0x00FFFFFF, "proj: Pixel 478/388 has color 0x%08x, expected 0x00FFFFFF\n", color);
3451     color = getPixelColor(device, 482, 388);
3452     ok(color == 0x00000000, "proj: Pixel 482/388 has color 0x%08x, expected 0x00000000\n", color);
3453     color = getPixelColor(device, 478, 392);
3454     ok(color == 0x00000000, "proj: Pixel 478/392 has color 0x%08x, expected 0x00000000\n", color);
3455     color = getPixelColor(device, 482, 392);
3456     ok(color == 0x00000000, "proj: Pixel 482/392 has color 0x%08x, expected 0x00000000\n", color);
3457
3458     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff203040, 0.0, 0);
3459     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3460     /* Use a smaller volume texture than the biggest possible size for memory and performance reasons
3461      * Thus watch out if sampling from texels between 0 and 1.
3462      */
3463     hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 32, 1, 0, fmt, D3DPOOL_MANAGED, &volume, 0);
3464     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
3465        "IDirect3DDevice9_CreateVolumeTexture failed with %08x\n", hr);
3466     if(!volume) {
3467         skip("Failed to create a volume texture\n");
3468         goto out;
3469     }
3470
3471     hr = IDirect3DVolumeTexture9_LockBox(volume, 0, &lb, NULL, 0);
3472     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_LockBox failed with %08x\n", hr);
3473     for(z = 0; z < 32; z++) {
3474         for(y = 0; y < 32; y++) {
3475             for(x = 0; x < 32; x++) {
3476                 char size = (fmt == D3DFMT_A16B16G16R16 ? 8 : 4);
3477                 void *mem = ((char *)  lb.pBits) + y * lb.RowPitch + z * lb.SlicePitch + x * size;
3478                 float r_f = (float) x / 31.0;
3479                 float g_f = (float) y / 31.0;
3480                 float b_f = (float) z / 31.0;
3481
3482                 if(fmt == D3DFMT_A16B16G16R16) {
3483                     unsigned short *mem_s = mem;
3484                     mem_s[0]  = r_f * 65535.0;
3485                     mem_s[1]  = g_f * 65535.0;
3486                     mem_s[2]  = b_f * 65535.0;
3487                     mem_s[3]  = 65535;
3488                 } else {
3489                     unsigned char *mem_c = mem;
3490                     mem_c[0]  = b_f * 255.0;
3491                     mem_c[1]  = g_f * 255.0;
3492                     mem_c[2]  = r_f * 255.0;
3493                     mem_c[3]  = 255;
3494                 }
3495             }
3496         }
3497     }
3498     hr = IDirect3DVolumeTexture9_UnlockBox(volume, 0);
3499     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %08x\n", hr);
3500
3501     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) volume);
3502     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %08x\n", hr);
3503
3504     hr = IDirect3DDevice9_BeginScene(device);
3505     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3506     if(SUCCEEDED(hr))
3507     {
3508         float quad1[] = {
3509             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3510             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
3511              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3512              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
3513         };
3514         float quad2[] = {
3515             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
3516             -1.0,       1.0,       0.1,     1.0,    1.0,    1.0,
3517              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
3518              0.0,       1.0,       0.1,     1.0,    1.0,    1.0
3519         };
3520         float quad3[] = {
3521              0.0,       0.0,       0.1,     0.0,    0.0,
3522              0.0,       1.0,       0.1,     0.0,    0.0,
3523              1.0,       0.0,       0.1,     0.0,    0.0,
3524              1.0,       1.0,       0.1,     0.0,    0.0
3525         };
3526         float quad4[] = {
3527              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3528              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
3529              1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3530              1.0,       0.0,       0.1,     1.0,    1.0,    1.0
3531         };
3532         float mat[16] = {1.0, 0.0, 0.0, 0.0,
3533                          0.0, 0.0, 1.0, 0.0,
3534                          0.0, 1.0, 0.0, 0.0,
3535                          0.0, 0.0, 0.0, 1.0};
3536         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3537         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
3538
3539         /* Draw a quad with all 3 coords enabled. Nothing fancy. v and w are swapped, but have the same
3540          * values
3541          */
3542         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
3543         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3544         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
3545         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3546         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
3547         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3548
3549         /* Now disable the w coordinate. Does that change the input, or the output. The coordinates
3550          * are swapped by the matrix. If it changes the input, the v coord will be missing(green),
3551          * otherwise the w will be missing(blue).
3552          * turns out that on nvidia cards the blue color is missing, so it is an output modification.
3553          * On ATI cards the COUNT2 is ignored, and it behaves in the same way as COUNT3.
3554          */
3555         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3556         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3557         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
3558         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3559
3560         /* default values? Set up the identity matrix, pass in 2 vertex coords, and enable 4 */
3561         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
3562         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3563         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
3564         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3565         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3566         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3567         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
3568         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3569
3570         /* D3DTTFF_COUNT1. Set a NULL matrix, and count1, pass in all values as 1.0. Nvidia has count1 ==
3571          * disable. ATI extends it up to the amount of values needed for the volume texture
3572          */
3573         memset(mat, 0, sizeof(mat));
3574         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
3575         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3576         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
3577         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3578         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3579         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
3580         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
3581         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3582
3583         hr = IDirect3DDevice9_EndScene(device);
3584         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3585     }
3586     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3587     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3588
3589     color = getPixelColor(device, 160, 360);
3590     ok(color == 0x00ffffff, "quad 1 has color %08x, expected 0x00ffffff\n", color);
3591     color = getPixelColor(device, 160, 120);
3592     ok(color == 0x00ffff00 /* NV*/ || color == 0x00ffffff /* ATI */,
3593        "quad 2 has color %08x, expected 0x00ffff00\n", color);
3594     color = getPixelColor(device, 480, 120);
3595     ok(color == 0x000000ff, "quad 3 has color %08x, expected 0x000000ff\n", color);
3596     color = getPixelColor(device, 480, 360);
3597     ok(color == 0x00ffffff || color == 0x0000ff00, "quad 4 has color %08x, expected 0x00ffffff\n", color);
3598
3599     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff303030, 0.0, 0);
3600     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3601     hr = IDirect3DDevice9_BeginScene(device);
3602     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3603     if(SUCCEEDED(hr))
3604     {
3605         float quad1[] = {
3606             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3607             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
3608              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3609              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
3610         };
3611         float quad2[] = {
3612             -1.0,       0.0,       0.1,
3613             -1.0,       1.0,       0.1,
3614              0.0,       0.0,       0.1,
3615              0.0,       1.0,       0.1,
3616         };
3617         float quad3[] = {
3618              0.0,       0.0,       0.1,     1.0,
3619              0.0,       1.0,       0.1,     1.0,
3620              1.0,       0.0,       0.1,     1.0,
3621              1.0,       1.0,       0.1,     1.0
3622         };
3623         float mat[16] =  {0.0, 0.0, 0.0, 0.0,
3624                            0.0, 0.0, 0.0, 0.0,
3625                            0.0, 0.0, 0.0, 0.0,
3626                            0.0, 1.0, 0.0, 0.0};
3627         float mat2[16] = {0.0, 0.0, 0.0, 1.0,
3628                            1.0, 0.0, 0.0, 0.0,
3629                            0.0, 1.0, 0.0, 0.0,
3630                            0.0, 0.0, 1.0, 0.0};
3631         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3632         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
3633
3634         /* Default values? 4 coords used, 3 passed. What happens to the 4th?
3635          */
3636         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
3637         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3638         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
3639         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3640         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
3641         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3642
3643         /* None passed */
3644         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
3645         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3646         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
3647         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3648         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
3649         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3650
3651         /* 4 used, 1 passed */
3652         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl2);
3653         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
3654         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat2);
3655         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3656         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 4 * sizeof(float));
3657         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3658
3659         hr = IDirect3DDevice9_EndScene(device);
3660         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3661     }
3662     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3663     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3664     color = getPixelColor(device, 160, 360);
3665     ok(color == 0x0000ff00, "quad 1 has color %08x, expected 0x0000ff00\n", color);
3666     color = getPixelColor(device, 160, 120);
3667     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x00000000\n", color);
3668     color = getPixelColor(device, 480, 120);
3669     ok(color == 0x00ff0000, "quad 3 has color %08x, expected 0x00ff0000\n", color);
3670     /* Quad4: unused */
3671
3672     IDirect3DVolumeTexture9_Release(volume);
3673
3674     out:
3675     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
3676     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
3677     IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
3678     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3679     hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &identity);
3680     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3681     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3682     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
3683     IDirect3DVertexDeclaration9_Release(decl);
3684     IDirect3DVertexDeclaration9_Release(decl2);
3685     IDirect3DVertexDeclaration9_Release(decl3);
3686 }
3687
3688 static void texdepth_test(IDirect3DDevice9 *device)
3689 {
3690     IDirect3DPixelShader9 *shader;
3691     HRESULT hr;
3692     const float texdepth_test_data1[] = { 0.25,  2.0, 0.0, 0.0};
3693     const float texdepth_test_data2[] = { 0.25,  0.5, 0.0, 0.0};
3694     const float texdepth_test_data3[] = {-1.00,  0.1, 0.0, 0.0};
3695     const float texdepth_test_data4[] = {-0.25, -0.5, 0.0, 0.0};
3696     const float texdepth_test_data5[] = { 1.00, -0.1, 0.0, 0.0};
3697     const float texdepth_test_data6[] = { 1.00,  0.5, 0.0, 0.0};
3698     const float texdepth_test_data7[] = { 0.50,  0.0, 0.0, 0.0};
3699     DWORD shader_code[] = {
3700         0xffff0104,                                                                 /* ps_1_4               */
3701         0x00000051, 0xa00f0001, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000,     /* def c1, 0, 0, 1, 1   */
3702         0x00000001, 0x800f0005, 0xa0e40000,                                         /* mov r5, c0           */
3703         0x0000fffd,                                                                 /* phase                */
3704         0x00000057, 0x800f0005,                                                     /* texdepth r5          */
3705         0x00000001, 0x800f0000, 0xa0e40001,                                         /* mov r0, c1           */
3706         0x0000ffff                                                                  /* end                  */
3707     };
3708     DWORD color;
3709     float vertex[] = {
3710        -1.0,   -1.0,    0.0,
3711         1.0,   -1.0,    1.0,
3712        -1.0,    1.0,    0.0,
3713         1.0,    1.0,    1.0
3714     };
3715
3716     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
3717     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
3718
3719     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffff00, 0.0, 0);
3720     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3721     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
3722     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
3723     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
3724     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
3725     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
3726     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
3727     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
3728
3729     /* Fill the depth buffer with a gradient */
3730     hr = IDirect3DDevice9_BeginScene(device);
3731     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3732     if(SUCCEEDED(hr))
3733     {
3734         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3735         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3736         hr = IDirect3DDevice9_EndScene(device);
3737         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3738     }
3739
3740     /* Now perform the actual tests. Same geometry, but with the shader */
3741     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
3742     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
3743     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
3744     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
3745     hr = IDirect3DDevice9_SetPixelShader(device, shader);
3746     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
3747
3748     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data1, 1);
3749     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
3750     hr = IDirect3DDevice9_BeginScene(device);
3751     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3752     if(SUCCEEDED(hr))
3753     {
3754         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3755         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3756
3757         hr = IDirect3DDevice9_EndScene(device);
3758         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3759     }
3760
3761     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3762     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3763     color = getPixelColor(device, 158, 240);
3764     ok(color == 0x000000ff, "Pixel 158(25%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
3765     color = getPixelColor(device, 162, 240);
3766     ok(color == 0x00ffffff, "Pixel 158(25%% + 2 pixel) has color %08x, expected 0x00ffffff\n", color);
3767
3768     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
3769
3770     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data2, 1);
3771     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
3772     hr = IDirect3DDevice9_BeginScene(device);
3773     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3774     if(SUCCEEDED(hr))
3775     {
3776         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3777         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3778
3779         hr = IDirect3DDevice9_EndScene(device);
3780         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3781     }
3782
3783     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3784     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3785     color = getPixelColor(device, 318, 240);
3786     ok(color == 0x000000ff, "Pixel 318(50%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
3787     color = getPixelColor(device, 322, 240);
3788     ok(color == 0x00ffff00, "Pixel 322(50%% + 2 pixel) has color %08x, expected 0x00ffff00\n", color);
3789
3790     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
3791
3792     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data3, 1);
3793     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
3794     hr = IDirect3DDevice9_BeginScene(device);
3795     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3796     if(SUCCEEDED(hr))
3797     {
3798         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3799         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3800
3801         hr = IDirect3DDevice9_EndScene(device);
3802         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3803     }
3804     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3805     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3806
3807     color = getPixelColor(device, 1, 240);
3808     ok(color == 0x00ff0000, "Pixel 1(0%% + 2 pixel) has color %08x, expected 0x00ff0000\n", color);
3809
3810     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
3811
3812     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data4, 1);
3813     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
3814     hr = IDirect3DDevice9_BeginScene(device);
3815     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3816     if(SUCCEEDED(hr))
3817     {
3818         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3819         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3820
3821         hr = IDirect3DDevice9_EndScene(device);
3822         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3823     }
3824     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3825     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3826     color = getPixelColor(device, 318, 240);
3827     ok(color == 0x000000ff, "Pixel 318(50%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
3828     color = getPixelColor(device, 322, 240);
3829     ok(color == 0x0000ff00, "Pixel 322(50%% + 2 pixel) has color %08x, expected 0x0000ff00\n", color);
3830
3831     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
3832
3833     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data5, 1);
3834     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
3835     hr = IDirect3DDevice9_BeginScene(device);
3836     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3837     if(SUCCEEDED(hr))
3838     {
3839         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3840         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3841
3842         hr = IDirect3DDevice9_EndScene(device);
3843         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3844     }
3845     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3846     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3847
3848     color = getPixelColor(device, 1, 240);
3849     ok(color == 0x00ffff00, "Pixel 1(0%% + 2 pixel) has color %08x, expected 0x00ffff00\n", color);
3850
3851     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
3852
3853     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data6, 1);
3854     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
3855     hr = IDirect3DDevice9_BeginScene(device);
3856     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3857     if(SUCCEEDED(hr))
3858     {
3859         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3860         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3861
3862         hr = IDirect3DDevice9_EndScene(device);
3863         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3864     }
3865     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3866     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3867
3868     color = getPixelColor(device, 638, 240);
3869     ok(color == 0x000000ff, "Pixel 638(100%% + 2 pixel) has color %08x, expected 0x000000ff\n", color);
3870
3871     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
3872
3873     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data7, 1);
3874     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
3875     hr = IDirect3DDevice9_BeginScene(device);
3876     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3877     if(SUCCEEDED(hr))
3878     {
3879         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3880         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3881
3882         hr = IDirect3DDevice9_EndScene(device);
3883         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3884     }
3885     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3886     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3887
3888     color = getPixelColor(device, 638, 240);
3889     ok(color == 0x000000ff, "Pixel 638(100%% + 2 pixel) has color %08x, expected 0x000000ff\n", color);
3890
3891     /* Cleanup */
3892     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
3893     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
3894     IDirect3DPixelShader9_Release(shader);
3895
3896     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
3897     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
3898     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
3899     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
3900 }
3901
3902 static void texkill_test(IDirect3DDevice9 *device)
3903 {
3904     IDirect3DPixelShader9 *shader;
3905     HRESULT hr;
3906     DWORD color;
3907
3908     const float vertex[] = {
3909     /*                          bottom  top    right    left */
3910         -1.0,   -1.0,   1.0,   -0.1,    0.9,    0.9,   -0.1,
3911          1.0,   -1.0,   0.0,    0.9,   -0.1,    0.9,   -0.1,
3912         -1.0,    1.0,   1.0,   -0.1,    0.9,   -0.1,    0.9,
3913          1.0,    1.0,   0.0,    0.9,   -0.1,   -0.1,    0.9,
3914     };
3915
3916     DWORD shader_code_11[] = {
3917     0xffff0101,                                                             /* ps_1_1                     */
3918     0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0 */
3919     0x00000041, 0xb00f0000,                                                 /* texkill t0                 */
3920     0x00000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                 */
3921     0x0000ffff                                                              /* end                        */
3922     };
3923     DWORD shader_code_20[] = {
3924     0xffff0200,                                                             /* ps_2_0                     */
3925     0x0200001f, 0x80000000, 0xb00f0000,                                     /* dcl t0                     */
3926     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c0, 0.0, 0.0, 1.0, 1.0 */
3927     0x01000041, 0xb00f0000,                                                 /* texkill t0                 */
3928     0x02000001, 0x800f0800, 0xa0e40000,                                     /* mov oC0, c0                */
3929     0x0000ffff                                                              /* end                        */
3930     };
3931
3932     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
3933     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
3934     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader);
3935     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
3936
3937     hr = IDirect3DDevice9_SetPixelShader(device, shader);
3938     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
3939     hr = IDirect3DDevice9_BeginScene(device);
3940     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3941     if(SUCCEEDED(hr))
3942     {
3943         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1);
3944         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
3945         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 7 * sizeof(float));
3946         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3947         hr = IDirect3DDevice9_EndScene(device);
3948         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3949     }
3950     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3951     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3952     color = getPixelColor(device, 63, 46);
3953     ok(color == 0x0000ff00, "Pixel 63/46 has color %08x, expected 0x0000ff00\n", color);
3954     color = getPixelColor(device, 66, 46);
3955     ok(color == 0x0000ff00, "Pixel 66/64 has color %08x, expected 0x0000ff00\n", color);
3956     color = getPixelColor(device, 63, 49);
3957     ok(color == 0x0000ff00, "Pixel 63/49 has color %08x, expected 0x0000ff00\n", color);
3958     color = getPixelColor(device, 66, 49);
3959     ok(color == 0x00ff0000, "Pixel 66/49 has color %08x, expected 0x00ff0000\n", color);
3960
3961     color = getPixelColor(device, 578, 46);
3962     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
3963     color = getPixelColor(device, 575, 46);
3964     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
3965     color = getPixelColor(device, 578, 49);
3966     ok(color == 0x0000ff00, "Pixel 578/49 has color %08x, expected 0x0000ff00\n", color);
3967     color = getPixelColor(device, 575, 49);
3968     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
3969
3970     color = getPixelColor(device, 63, 430);
3971     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
3972     color = getPixelColor(device, 63, 433);
3973     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
3974     color = getPixelColor(device, 66, 433);
3975     ok(color == 0x00ff0000, "Pixel 578/49 has color %08x, expected 0x00ff0000\n", color);
3976     color = getPixelColor(device, 66, 430);
3977     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
3978
3979     color = getPixelColor(device, 578, 430);
3980     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
3981     color = getPixelColor(device, 578, 433);
3982     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
3983     color = getPixelColor(device, 575, 433);
3984     ok(color == 0x00ff0000, "Pixel 578/49 has color %08x, expected 0x00ff0000\n", color);
3985     color = getPixelColor(device, 575, 430);
3986     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
3987
3988     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
3989     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
3990     IDirect3DPixelShader9_Release(shader);
3991
3992     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
3993     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
3994     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_20, &shader);
3995     if(FAILED(hr)) {
3996         skip("Failed to create 2.0 test shader, most likely not supported\n");
3997         return;
3998     }
3999
4000     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4001     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4002     hr = IDirect3DDevice9_BeginScene(device);
4003     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4004     if(SUCCEEDED(hr))
4005     {
4006         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 7 * sizeof(float));
4007         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4008         hr = IDirect3DDevice9_EndScene(device);
4009         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4010     }
4011     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4012
4013     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4014     color = getPixelColor(device, 63, 46);
4015     ok(color == 0x00ffff00, "Pixel 63/46 has color %08x, expected 0x00ffff00\n", color);
4016     color = getPixelColor(device, 66, 46);
4017     ok(color == 0x00ffff00, "Pixel 66/64 has color %08x, expected 0x00ffff00\n", color);
4018     color = getPixelColor(device, 63, 49);
4019     ok(color == 0x00ffff00, "Pixel 63/49 has color %08x, expected 0x00ffff00\n", color);
4020     color = getPixelColor(device, 66, 49);
4021     ok(color == 0x000000ff, "Pixel 66/49 has color %08x, expected 0x000000ff\n", color);
4022
4023     color = getPixelColor(device, 578, 46);
4024     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
4025     color = getPixelColor(device, 575, 46);
4026     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
4027     color = getPixelColor(device, 578, 49);
4028     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
4029     color = getPixelColor(device, 575, 49);
4030     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
4031
4032     color = getPixelColor(device, 63, 430);
4033     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
4034     color = getPixelColor(device, 63, 433);
4035     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
4036     color = getPixelColor(device, 66, 433);
4037     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
4038     color = getPixelColor(device, 66, 430);
4039     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
4040
4041     color = getPixelColor(device, 578, 430);
4042     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
4043     color = getPixelColor(device, 578, 433);
4044     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
4045     color = getPixelColor(device, 575, 433);
4046     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
4047     color = getPixelColor(device, 575, 430);
4048     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
4049
4050     /* Cleanup */
4051     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4052     ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
4053     IDirect3DPixelShader9_Release(shader);
4054 }
4055
4056 static void x8l8v8u8_test(IDirect3DDevice9 *device)
4057 {
4058     IDirect3D9 *d3d9;
4059     HRESULT hr;
4060     IDirect3DTexture9 *texture;
4061     IDirect3DPixelShader9 *shader;
4062     IDirect3DPixelShader9 *shader2;
4063     D3DLOCKED_RECT lr;
4064     DWORD color;
4065     DWORD shader_code[] = {
4066         0xffff0101,                             /* ps_1_1       */
4067         0x00000042, 0xb00f0000,                 /* tex t0       */
4068         0x00000001, 0x800f0000, 0xb0e40000,     /* mov r0, t0   */
4069         0x0000ffff                              /* end          */
4070     };
4071     DWORD shader_code2[] = {
4072         0xffff0101,                             /* ps_1_1       */
4073         0x00000042, 0xb00f0000,                 /* tex t0       */
4074         0x00000001, 0x800f0000, 0xb0ff0000,     /* mov r0, t0.w */
4075         0x0000ffff                              /* end          */
4076     };
4077
4078     float quad[] = {
4079        -1.0,   -1.0,   0.1,     0.5,    0.5,
4080         1.0,   -1.0,   0.1,     0.5,    0.5,
4081        -1.0,    1.0,   0.1,     0.5,    0.5,
4082         1.0,    1.0,   0.1,     0.5,    0.5,
4083     };
4084
4085     memset(&lr, 0, sizeof(lr));
4086     IDirect3DDevice9_GetDirect3D(device, &d3d9);
4087     hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4088                                       0,  D3DRTYPE_TEXTURE, D3DFMT_X8L8V8U8);
4089     IDirect3D9_Release(d3d9);
4090     if(FAILED(hr)) {
4091         skip("No D3DFMT_X8L8V8U8 support\n");
4092     };
4093
4094     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
4095     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4096
4097     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_X8L8V8U8, D3DPOOL_MANAGED, &texture, NULL);
4098     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed (%08x)\n", hr);
4099     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
4100     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed (%08x)\n", hr);
4101     *((DWORD *) lr.pBits) = 0x11ca3141;
4102     hr = IDirect3DTexture9_UnlockRect(texture, 0);
4103     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed (%08x)\n", hr);
4104
4105     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
4106     ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr);
4107     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code2, &shader2);
4108     ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr);
4109
4110     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4111     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed (%08x)\n", hr);
4112     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4113     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4114     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
4115     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
4116
4117     hr = IDirect3DDevice9_BeginScene(device);
4118     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4119     if(SUCCEEDED(hr))
4120     {
4121         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
4122         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4123
4124         hr = IDirect3DDevice9_EndScene(device);
4125         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4126     }
4127     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4128     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4129     color = getPixelColor(device, 578, 430);
4130     ok(color == 0x008262ca || color == 0x008363ca || color == 0x008362ca,
4131        "D3DFMT_X8L8V8U8 = 0x112131ca returns color %08x, expected 0x008262ca\n", color);
4132
4133     hr = IDirect3DDevice9_SetPixelShader(device, shader2);
4134     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4135     hr = IDirect3DDevice9_BeginScene(device);
4136     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4137     if(SUCCEEDED(hr))
4138     {
4139         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
4140         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4141
4142         hr = IDirect3DDevice9_EndScene(device);
4143         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4144     }
4145     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4146     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4147     color = getPixelColor(device, 578, 430);
4148     ok(color == 0x00ffffff, "w component of D3DFMT_X8L8V8U8 = 0x11ca3141 returns color %08x\n", color);
4149
4150     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4151     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4152     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4153     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
4154     IDirect3DPixelShader9_Release(shader);
4155     IDirect3DPixelShader9_Release(shader2);
4156     IDirect3DTexture9_Release(texture);
4157 }
4158
4159 static void autogen_mipmap_test(IDirect3DDevice9 *device)
4160 {
4161     HRESULT hr;
4162     IDirect3D9 *d3d;
4163     IDirect3DTexture9 *texture = NULL;
4164     IDirect3DSurface9 *surface;
4165     DWORD color;
4166     const RECT r1 = {256, 256, 512, 512};
4167     const RECT r2 = {512, 256, 768, 512};
4168     const RECT r3 = {256, 512, 512, 768};
4169     const RECT r4 = {512, 512, 768, 768};
4170     unsigned int x, y;
4171     D3DLOCKED_RECT lr;
4172     memset(&lr, 0, sizeof(lr));
4173
4174     IDirect3DDevice9_GetDirect3D(device, &d3d);
4175     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4176        D3DUSAGE_AUTOGENMIPMAP,  D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8) != D3D_OK) {
4177         skip("No autogenmipmap support\n");
4178         IDirect3D9_Release(d3d);
4179         return;
4180     }
4181     IDirect3D9_Release(d3d);
4182
4183     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
4184     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4185
4186     /* Make the mipmap big, so that a smaller mipmap is used
4187      */
4188     hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 0, D3DUSAGE_AUTOGENMIPMAP,
4189                                         D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4190     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
4191
4192     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
4193     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel returned %08x\n", hr);
4194     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
4195     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
4196     for(y = 0; y < 1024; y++) {
4197         for(x = 0; x < 1024; x++) {
4198             DWORD *dst = (DWORD *) (((BYTE *) lr.pBits) + y * lr.Pitch + x * 4);
4199             POINT pt;
4200
4201             pt.x = x;
4202             pt.y = y;
4203             if(PtInRect(&r1, pt)) {
4204                 *dst = 0xffff0000;
4205             } else if(PtInRect(&r2, pt)) {
4206                 *dst = 0xff00ff00;
4207             } else if(PtInRect(&r3, pt)) {
4208                 *dst = 0xff0000ff;
4209             } else if(PtInRect(&r4, pt)) {
4210                 *dst = 0xff000000;
4211             } else {
4212                 *dst = 0xffffffff;
4213             }
4214         }
4215     }
4216     hr = IDirect3DSurface9_UnlockRect(surface);
4217     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect returned %08x\n", hr);
4218     IDirect3DSurface9_Release(surface);
4219
4220     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
4221     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
4222     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
4223     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
4224
4225     hr = IDirect3DDevice9_BeginScene(device);
4226     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4227     if(SUCCEEDED(hr)) {
4228         const float quad[] =  {
4229            -0.5,   -0.5,    0.1,    0.0,    0.0,
4230            -0.5,    0.5,    0.1,    0.0,    1.0,
4231             0.5,   -0.5,    0.1,    1.0,    0.0,
4232             0.5,    0.5,    0.1,    1.0,    1.0
4233         };
4234
4235         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4236         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
4237         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
4238         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4239         hr = IDirect3DDevice9_EndScene(device);
4240         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4241     }
4242     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4243     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
4244     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
4245     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
4246     IDirect3DTexture9_Release(texture);
4247
4248     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4249     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4250     color = getPixelColor(device, 200, 200);
4251     ok(color == 0x00ffffff, "pixel 200/200 has color %08x, expected 0x00ffffff\n", color);
4252     color = getPixelColor(device, 280, 200);
4253     ok(color == 0x000000ff, "pixel 280/200 has color %08x, expected 0x000000ff\n", color);
4254     color = getPixelColor(device, 360, 200);
4255     ok(color == 0x00000000, "pixel 360/200 has color %08x, expected 0x00000000\n", color);
4256     color = getPixelColor(device, 440, 200);
4257     ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
4258     color = getPixelColor(device, 200, 270);
4259     ok(color == 0x00ffffff, "pixel 200/270 has color %08x, expected 0x00ffffff\n", color);
4260     color = getPixelColor(device, 280, 270);
4261     ok(color == 0x00ff0000, "pixel 280/270 has color %08x, expected 0x00ff0000\n", color);
4262     color = getPixelColor(device, 360, 270);
4263     ok(color == 0x0000ff00, "pixel 360/270 has color %08x, expected 0x0000ff00\n", color);
4264     color = getPixelColor(device, 440, 270);
4265     ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
4266 }
4267
4268 static void test_constant_clamp_vs(IDirect3DDevice9 *device)
4269 {
4270     IDirect3DVertexShader9 *shader_11, *shader_11_2, *shader_20, *shader_20_2;
4271     IDirect3DVertexDeclaration9 *decl;
4272     HRESULT hr;
4273     DWORD color;
4274     DWORD shader_code_11[] =  {
4275         0xfffe0101,                                         /* vs_1_1           */
4276         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4277         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4278         0x00000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4279         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4280         0x0000ffff                                          /* end              */
4281     };
4282     DWORD shader_code_11_2[] =  {
4283         0xfffe0101,                                         /* vs_1_1           */
4284         0x00000051, 0xa00f0001, 0x3fa00000, 0xbf000000, 0xbfc00000, 0x3f800000, /* dcl ... */
4285         0x00000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000, /* dcl ... */
4286         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4287         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4288         0x00000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4289         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4290         0x0000ffff                                          /* end              */
4291     };
4292     DWORD shader_code_20[] =  {
4293         0xfffe0200,                                         /* vs_2_0           */
4294         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4295         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4296         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4297         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4298         0x0000ffff                                          /* end              */
4299     };
4300     DWORD shader_code_20_2[] =  {
4301         0xfffe0200,                                         /* vs_2_0           */
4302         0x05000051, 0xa00f0001, 0x3fa00000, 0xbf000000, 0xbfc00000, 0x3f800000,
4303         0x05000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000,
4304         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4305         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4306         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4307         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4308         0x0000ffff                                          /* end              */
4309     };
4310     static const D3DVERTEXELEMENT9 decl_elements[] = {
4311         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4312         D3DDECL_END()
4313     };
4314     float quad1[] = {
4315         -1.0,   -1.0,   0.1,
4316          0.0,   -1.0,   0.1,
4317         -1.0,    0.0,   0.1,
4318          0.0,    0.0,   0.1
4319     };
4320     float quad2[] = {
4321          0.0,   -1.0,   0.1,
4322          1.0,   -1.0,   0.1,
4323          0.0,    0.0,   0.1,
4324          1.0,    0.0,   0.1
4325     };
4326     float quad3[] = {
4327          0.0,    0.0,   0.1,
4328          1.0,    0.0,   0.1,
4329          0.0,    1.0,   0.1,
4330          1.0,    1.0,   0.1
4331     };
4332     float quad4[] = {
4333         -1.0,    0.0,   0.1,
4334          0.0,    0.0,   0.1,
4335         -1.0,    1.0,   0.1,
4336          0.0,    1.0,   0.1
4337     };
4338     float test_data_c1[4] = {  1.25, -0.50, -1.50, 1.0};
4339     float test_data_c2[4] = { -0.50,  1.25,  2.00, 1.0};
4340
4341     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
4342     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4343
4344     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_11, &shader_11);
4345     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
4346     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_11_2, &shader_11_2);
4347     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
4348     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_20, &shader_20);
4349     if(FAILED(hr)) shader_20 = NULL;
4350     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_20_2, &shader_20_2);
4351     if(FAILED(hr)) shader_20_2 = NULL;
4352     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
4353     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
4354
4355     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, test_data_c1, 1);
4356     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned %08x\n", hr);
4357     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 2, test_data_c2, 1);
4358     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned %08x\n", hr);
4359     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
4360     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
4361
4362     hr = IDirect3DDevice9_BeginScene(device);
4363     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4364     if(SUCCEEDED(hr))
4365     {
4366         hr = IDirect3DDevice9_SetVertexShader(device, shader_11);
4367         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4368         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 3 * sizeof(float));
4369         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4370
4371         hr = IDirect3DDevice9_SetVertexShader(device, shader_11_2);
4372         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4373         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
4374         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4375
4376         if(shader_20) {
4377             hr = IDirect3DDevice9_SetVertexShader(device, shader_20);
4378             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4379             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 3 * sizeof(float));
4380             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4381         }
4382
4383         if(shader_20_2) {
4384             hr = IDirect3DDevice9_SetVertexShader(device, shader_20_2);
4385             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4386             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 3 * sizeof(float));
4387             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4388         }
4389
4390         hr = IDirect3DDevice9_EndScene(device);
4391         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4392     }
4393     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4394     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4395
4396     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
4397     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4398     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
4399     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
4400
4401     color = getPixelColor(device, 160, 360);
4402     ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
4403        "quad 1 has color %08x, expected 0x00bfbf80\n", color);
4404     color = getPixelColor(device, 480, 360);
4405     ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
4406        "quad 2 has color %08x, expected 0x00bfbf80\n", color);
4407     if(shader_20) {
4408         color = getPixelColor(device, 160, 120);
4409         ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
4410            "quad 3 has color %08x, expected 0x00bfbf80\n", color);
4411     }
4412     if(shader_20_2) {
4413         color = getPixelColor(device, 480, 120);
4414         ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
4415            "quad 4 has color %08x, expected 0x00bfbf80\n", color);
4416     }
4417
4418     IDirect3DVertexDeclaration9_Release(decl);
4419     if(shader_20_2) IDirect3DVertexShader9_Release(shader_20_2);
4420     if(shader_20) IDirect3DVertexShader9_Release(shader_20);
4421     IDirect3DVertexShader9_Release(shader_11_2);
4422     IDirect3DVertexShader9_Release(shader_11);
4423 }
4424
4425 static void constant_clamp_ps_test(IDirect3DDevice9 *device)
4426 {
4427     IDirect3DPixelShader9 *shader_11, *shader_12, *shader_14, *shader_20;
4428     HRESULT hr;
4429     DWORD color;
4430     DWORD shader_code_11[] =  {
4431         0xffff0101,                                         /* ps_1_1           */
4432         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4433         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
4434         0x0000ffff                                          /* end              */
4435     };
4436     DWORD shader_code_12[] =  {
4437         0xffff0102,                                         /* ps_1_2           */
4438         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4439         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
4440         0x0000ffff                                          /* end              */
4441     };
4442     /* Skip 1.3 shaders because we have only 4 quads(ok, could make them smaller if needed).
4443      * 1.2 and 1.4 shaders behave the same, so it's unlikely that 1.3 shaders are different.
4444      * During development of this test, 1.3 shaders were verified too
4445      */
4446     DWORD shader_code_14[] =  {
4447         0xffff0104,                                         /* ps_1_4           */
4448         /* Try to make one constant local. It gets clamped too, although the binary contains
4449          * the bigger numbers
4450          */
4451         0x00000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000, /* def c2, -0.5, 1.25, 2, 1 */
4452         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4453         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
4454         0x0000ffff                                          /* end              */
4455     };
4456     DWORD shader_code_20[] =  {
4457         0xffff0200,                                         /* ps_2_0           */
4458         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4459         0x03000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
4460         0x02000001, 0x800f0800, 0x80e40000,                 /* mov oC0, r0      */
4461         0x0000ffff                                          /* end              */
4462     };
4463     float quad1[] = {
4464         -1.0,   -1.0,   0.1,
4465          0.0,   -1.0,   0.1,
4466         -1.0,    0.0,   0.1,
4467          0.0,    0.0,   0.1
4468     };
4469     float quad2[] = {
4470          0.0,   -1.0,   0.1,
4471          1.0,   -1.0,   0.1,
4472          0.0,    0.0,   0.1,
4473          1.0,    0.0,   0.1
4474     };
4475     float quad3[] = {
4476          0.0,    0.0,   0.1,
4477          1.0,    0.0,   0.1,
4478          0.0,    1.0,   0.1,
4479          1.0,    1.0,   0.1
4480     };
4481     float quad4[] = {
4482         -1.0,    0.0,   0.1,
4483          0.0,    0.0,   0.1,
4484         -1.0,    1.0,   0.1,
4485          0.0,    1.0,   0.1
4486     };
4487     float test_data_c1[4] = {  1.25, -0.50, -1.50, 1.0};
4488     float test_data_c2[4] = { -0.50,  1.25,  2.00, 1.0};
4489
4490     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
4491     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4492
4493     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader_11);
4494     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4495     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12, &shader_12);
4496     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4497     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14, &shader_14);
4498     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4499     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_20, &shader_20);
4500     if(FAILED(hr)) shader_20 = NULL;
4501
4502     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1, 1);
4503     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4504     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2, 1);
4505     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4506     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4507     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
4508
4509     hr = IDirect3DDevice9_BeginScene(device);
4510     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4511     if(SUCCEEDED(hr))
4512     {
4513         hr = IDirect3DDevice9_SetPixelShader(device, shader_11);
4514         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4515         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 3 * sizeof(float));
4516         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4517
4518         hr = IDirect3DDevice9_SetPixelShader(device, shader_12);
4519         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4520         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
4521         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4522
4523         hr = IDirect3DDevice9_SetPixelShader(device, shader_14);
4524         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4525         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 3 * sizeof(float));
4526         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4527
4528         if(shader_20) {
4529             hr = IDirect3DDevice9_SetPixelShader(device, shader_20);
4530             ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4531             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 3 * sizeof(float));
4532             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4533         }
4534
4535         hr = IDirect3DDevice9_EndScene(device);
4536         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4537     }
4538     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4539     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4540
4541     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4542     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4543
4544     color = getPixelColor(device, 160, 360);
4545     ok(color == 0x00808000 || color == 0x007f7f00 || color == 0x00818100,
4546        "quad 1 has color %08x, expected 0x00808000\n", color);
4547     color = getPixelColor(device, 480, 360);
4548     ok(color == 0x00808000 || color == 0x007f7f00 || color == 0x00818100,
4549        "quad 2 has color %08x, expected 0x00808000\n", color);
4550     color = getPixelColor(device, 480, 120);
4551     ok(color == 0x00808000 || color == 0x007f7f00 || color == 0x00818100,
4552        "quad 3 has color %08x, expected 0x00808000\n", color);
4553     if(shader_20) {
4554         color = getPixelColor(device, 160, 120);
4555         ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
4556            "quad 4 has color %08x, expected 0x00bfbf80\n", color);
4557     }
4558
4559     if(shader_20) IDirect3DPixelShader9_Release(shader_20);
4560     IDirect3DPixelShader9_Release(shader_14);
4561     IDirect3DPixelShader9_Release(shader_12);
4562     IDirect3DPixelShader9_Release(shader_11);
4563 }
4564
4565 static void dp2add_ps_test(IDirect3DDevice9 *device)
4566 {
4567     IDirect3DPixelShader9 *shader_dp2add = NULL;
4568     IDirect3DPixelShader9 *shader_dp2add_sat = NULL;
4569     HRESULT hr;
4570     DWORD color;
4571
4572     /* DP2ADD is defined as:  (src0.r * src1.r) + (src0.g * src1.g) + src2.
4573      * One D3D restriction of all shader instructions except SINCOS is that no more than 2
4574      * source tokens can be constants.  So, for this exercise, we move contents of c0 to
4575      * r0 first.
4576      * The result here for the r,g,b components should be roughly 0.5:
4577      *   (0.5 * 0.5) + (0.5 * 0.5) + 0.0 = 0.5 */
4578     static const DWORD shader_code_dp2add[] =  {
4579         0xffff0200,                                                             /* ps_2_0                       */
4580         0x05000051, 0xa00f0000, 0x3f000000, 0x3f000000, 0x3f800000, 0x00000000, /* def c0, 0.5, 0.5, 1.0, 0     */
4581
4582         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                   */
4583         0x0400005a, 0x80070000, 0x80000000, 0x80000000, 0x80ff0000,             /* dp2add r0.rgb, r0, r0, r0.a  */
4584
4585         0x02000001, 0x80080000, 0xa0aa0000,                                     /* mov r0.a, c0.b               */
4586         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
4587         0x0000ffff                                                              /* end                          */
4588     };
4589
4590     /* Test the _sat modifier, too.  Result here should be:
4591      *   DP2: (-0.5 * -0.5) + (-0.5 * -0.5) + 2.0 = 2.5
4592      *      _SAT: ==> 1.0
4593      *   ADD: (1.0 + -0.5) = 0.5
4594      */
4595     static const DWORD shader_code_dp2add_sat[] =  {
4596         0xffff0200,                                                             /* ps_2_0                           */
4597         0x05000051, 0xa00f0000, 0xbf000000, 0xbf000000, 0x3f800000, 0x40000000, /* def c0, -0.5, -0.5, 1.0, 2.0     */
4598
4599         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                       */
4600         0x0400005a, 0x80170000, 0x80000000, 0x80000000, 0x80ff0000,             /* dp2add_sat r0.rgb, r0, r0, r0.a  */
4601         0x03000002, 0x80070000, 0x80e40000, 0xa0000000,                         /* add r0.rgb, r0, c0.r             */
4602
4603         0x02000001, 0x80080000, 0xa0aa0000,                                     /* mov r0.a, c0.b                   */
4604         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                      */
4605         0x0000ffff                                                              /* end                              */
4606     };
4607
4608     const float quad[] = {
4609         -1.0,   -1.0,   0.1,
4610          1.0,   -1.0,   0.1,
4611         -1.0,    1.0,   0.1,
4612          1.0,    1.0,   0.1
4613     };
4614
4615
4616     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
4617     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4618
4619     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_dp2add, &shader_dp2add);
4620     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4621
4622     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_dp2add_sat, &shader_dp2add_sat);
4623     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4624
4625     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4626     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
4627
4628     if (shader_dp2add) {
4629
4630         hr = IDirect3DDevice9_SetPixelShader(device, shader_dp2add);
4631         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4632
4633         hr = IDirect3DDevice9_BeginScene(device);
4634         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4635         if(SUCCEEDED(hr))
4636         {
4637             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
4638             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4639
4640             hr = IDirect3DDevice9_EndScene(device);
4641             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4642         }
4643         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4644         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4645
4646         color = getPixelColor(device, 360, 240);
4647         ok(color == 0x007f7f7f || color == 0x00808080, "dp2add pixel has color %08x, expected ~0x007f7f7f\n", color);
4648
4649         IDirect3DPixelShader9_Release(shader_dp2add);
4650     } else {
4651         skip("dp2add shader creation failed\n");
4652     }
4653
4654     if (shader_dp2add_sat) {
4655
4656         hr = IDirect3DDevice9_SetPixelShader(device, shader_dp2add_sat);
4657         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4658
4659         hr = IDirect3DDevice9_BeginScene(device);
4660         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4661         if(SUCCEEDED(hr))
4662         {
4663             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
4664             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4665
4666             hr = IDirect3DDevice9_EndScene(device);
4667             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4668         }
4669         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4670         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4671
4672         color = getPixelColor(device, 360, 240);
4673         ok(color == 0x007f7f7f || color == 0x00808080, "dp2add pixel has color %08x, expected ~0x007f7f7f\n", color);
4674
4675         IDirect3DPixelShader9_Release(shader_dp2add_sat);
4676     } else {
4677         skip("dp2add shader creation failed\n");
4678     }
4679
4680     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4681     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4682 }
4683
4684 static void cnd_test(IDirect3DDevice9 *device)
4685 {
4686     IDirect3DPixelShader9 *shader_11, *shader_12, *shader_13, *shader_14;
4687     IDirect3DPixelShader9 *shader_11_coissue, *shader_12_coissue, *shader_13_coissue, *shader_14_coissue;
4688     HRESULT hr;
4689     DWORD color;
4690     /* ps 1.x shaders are rather picky with writemasks and source swizzles. The dp3 is
4691      * used to copy r0.r to all components of r1, then copy r1.a to c0.a. Essentially it
4692      * does a mov r0.a, r0.r, which isn't allowed as-is in 1.x pixel shaders.
4693      */
4694     DWORD shader_code_11[] =  {
4695         0xffff0101,                                                                 /* ps_1_1               */
4696         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
4697         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
4698         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, ???(t0)      */
4699         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3 r1, r0, c0       */
4700         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
4701         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
4702         0x0000ffff                                                                  /* end                  */
4703     };
4704     DWORD shader_code_12[] =  {
4705         0xffff0102,                                                                 /* ps_1_2               */
4706         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
4707         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
4708         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, t0           */
4709         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3 r1, r0, c0       */
4710         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
4711         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
4712         0x0000ffff                                                                  /* end                  */
4713     };
4714     DWORD shader_code_13[] =  {
4715         0xffff0103,                                                                 /* ps_1_3               */
4716         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
4717         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
4718         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, t0           */
4719         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3, r1, r0, c0      */
4720         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
4721         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
4722         0x0000ffff                                                                  /* end                  */
4723     };
4724     DWORD shader_code_14[] =  {
4725         0xffff0104,                                                                 /* ps_1_3               */
4726         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,     /* def c0, 0, 0, 0, 1   */
4727         0x00000040, 0x80070000, 0xb0e40000,                                         /* texcrd r0, t0        */
4728         0x00000001, 0x80080000, 0xa0ff0000,                                         /* mov r0.a, c0.a       */
4729         0x00000050, 0x800f0000, 0x80e40000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0, c1, c2   */
4730         0x0000ffff                                                                  /* end                  */
4731     };
4732
4733     /* Special fun: The coissue flag on cnd: Apparently cnd always selects the 2nd source,
4734      * as if the src0 comparison against 0.5 always evaluates to true. The coissue flag isn't
4735      * set by the compiler, it was added manually after compilation. It isn't always allowed,
4736      * only if there's a mov r0.a, XXXX, and the cnd instruction writes to r0.xyz, otherwise
4737      * native CreatePixelShader returns an error.
4738      *
4739      * The shader attempts to test the range [-1;1] against coissued cnd, which is a bit tricky.
4740      * The input from t0 is [0;1]. 0.5 is substracted, then we have to multiply with 2. Since
4741      * constants are clamped to [-1;1], a 2.0 is constructed by adding c0.r(=1.0) to c0.r into r1.r,
4742      * then r1(2.0, 0.0, 0.0, 0.0) is passed to dp3(explained above).
4743      */
4744     DWORD shader_code_11_coissue[] =  {
4745         0xffff0101,                                                             /* ps_1_1                   */
4746         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
4747         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
4748         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
4749         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
4750         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
4751         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
4752         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
4753         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
4754         /* 0x40000000 = D3DSI_COISSUE */
4755         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
4756         0x0000ffff                                                              /* end                      */
4757     };
4758     DWORD shader_code_12_coissue[] =  {
4759         0xffff0102,                                                             /* ps_1_2                   */
4760         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
4761         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
4762         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
4763         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
4764         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
4765         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
4766         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
4767         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
4768         /* 0x40000000 = D3DSI_COISSUE */
4769         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
4770         0x0000ffff                                                              /* end                      */
4771     };
4772     DWORD shader_code_13_coissue[] =  {
4773         0xffff0103,                                                             /* ps_1_3                   */
4774         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
4775         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
4776         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
4777         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
4778         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
4779         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
4780         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
4781         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
4782         /* 0x40000000 = D3DSI_COISSUE */
4783         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
4784         0x0000ffff                                                              /* end                      */
4785     };
4786     /* ps_1_4 does not have a different cnd behavior, just pass the [0;1] texcrd result to cnd, it will
4787      * compare against 0.5
4788      */
4789     DWORD shader_code_14_coissue[] =  {
4790         0xffff0104,                                                             /* ps_1_4                   */
4791         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0, 0, 0, 1       */
4792         0x00000040, 0x80070000, 0xb0e40000,                                     /* texcrd r0, t0            */
4793         0x00000001, 0x80080000, 0xa0ff0000,                                     /* mov r0.a, c0.a           */
4794         /* 0x40000000 = D3DSI_COISSUE */
4795         0x40000050, 0x80070000, 0x80e40000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0, c1, c2   */
4796         0x0000ffff                                                              /* end                      */
4797     };
4798     float quad1[] = {
4799         -1.0,   -1.0,   0.1,     0.0,    0.0,    1.0,
4800          0.0,   -1.0,   0.1,     1.0,    0.0,    1.0,
4801         -1.0,    0.0,   0.1,     0.0,    1.0,    0.0,
4802          0.0,    0.0,   0.1,     1.0,    1.0,    0.0
4803     };
4804     float quad2[] = {
4805          0.0,   -1.0,   0.1,     0.0,    0.0,    1.0,
4806          1.0,   -1.0,   0.1,     1.0,    0.0,    1.0,
4807          0.0,    0.0,   0.1,     0.0,    1.0,    0.0,
4808          1.0,    0.0,   0.1,     1.0,    1.0,    0.0
4809     };
4810     float quad3[] = {
4811          0.0,    0.0,   0.1,     0.0,    0.0,    1.0,
4812          1.0,    0.0,   0.1,     1.0,    0.0,    1.0,
4813          0.0,    1.0,   0.1,     0.0,    1.0,    0.0,
4814          1.0,    1.0,   0.1,     1.0,    1.0,    0.0
4815     };
4816     float quad4[] = {
4817         -1.0,    0.0,   0.1,     0.0,    0.0,    1.0,
4818          0.0,    0.0,   0.1,     1.0,    0.0,    1.0,
4819         -1.0,    1.0,   0.1,     0.0,    1.0,    0.0,
4820          0.0,    1.0,   0.1,     1.0,    1.0,    0.0
4821     };
4822     float test_data_c1[4] = {  0.0, 0.0, 0.0, 0.0};
4823     float test_data_c2[4] = {  1.0, 1.0, 1.0, 1.0};
4824     float test_data_c1_coi[4] = {  0.0, 1.0, 0.0, 0.0};
4825     float test_data_c2_coi[4] = {  1.0, 0.0, 1.0, 1.0};
4826
4827     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
4828     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4829
4830     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader_11);
4831     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4832     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12, &shader_12);
4833     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4834     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_13, &shader_13);
4835     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4836     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14, &shader_14);
4837     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4838     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11_coissue, &shader_11_coissue);
4839     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4840     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12_coissue, &shader_12_coissue);
4841     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4842     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_13_coissue, &shader_13_coissue);
4843     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4844     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14_coissue, &shader_14_coissue);
4845     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4846
4847     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1, 1);
4848     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4849     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2, 1);
4850     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4851     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4852     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
4853
4854     hr = IDirect3DDevice9_BeginScene(device);
4855     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4856     if(SUCCEEDED(hr))
4857     {
4858         hr = IDirect3DDevice9_SetPixelShader(device, shader_11);
4859         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4860         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
4861         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4862
4863         hr = IDirect3DDevice9_SetPixelShader(device, shader_12);
4864         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4865         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
4866         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4867
4868         hr = IDirect3DDevice9_SetPixelShader(device, shader_13);
4869         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4870         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 6 * sizeof(float));
4871         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4872
4873         hr = IDirect3DDevice9_SetPixelShader(device, shader_14);
4874         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4875         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
4876         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4877
4878         hr = IDirect3DDevice9_EndScene(device);
4879         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4880     }
4881     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4882     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4883
4884     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4885     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4886
4887     /* This is the 1.4 test. Each component(r, g, b) is tested separately against 0.5 */
4888     color = getPixelColor(device, 158, 118);
4889     ok(color == 0x00ff00ff, "pixel 158, 118 has color %08x, expected 0x00ff00ff\n", color);
4890     color = getPixelColor(device, 162, 118);
4891     ok(color == 0x000000ff, "pixel 162, 118 has color %08x, expected 0x000000ff\n", color);
4892     color = getPixelColor(device, 158, 122);
4893     ok(color == 0x00ffffff, "pixel 162, 122 has color %08x, expected 0x00ffffff\n", color);
4894     color = getPixelColor(device, 162, 122);
4895     ok(color == 0x0000ffff, "pixel 162, 122 has color %08x, expected 0x0000ffff\n", color);
4896
4897     /* 1.1 shader. All 3 components get set, based on the .w comparison */
4898     color = getPixelColor(device, 158, 358);
4899     ok(color == 0x00ffffff, "pixel 158, 358 has color %08x, expected 0x00ffffff\n", color);
4900     color = getPixelColor(device, 162, 358);
4901     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4902         "pixel 162, 358 has color %08x, expected 0x00000000\n", color);
4903     color = getPixelColor(device, 158, 362);
4904     ok(color == 0x00ffffff, "pixel 158, 362 has color %08x, expected 0x00ffffff\n", color);
4905     color = getPixelColor(device, 162, 362);
4906     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4907         "pixel 162, 362 has color %08x, expected 0x00000000\n", color);
4908
4909     /* 1.2 shader */
4910     color = getPixelColor(device, 478, 358);
4911     ok(color == 0x00ffffff, "pixel 478, 358 has color %08x, expected 0x00ffffff\n", color);
4912     color = getPixelColor(device, 482, 358);
4913     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4914         "pixel 482, 358 has color %08x, expected 0x00000000\n", color);
4915     color = getPixelColor(device, 478, 362);
4916     ok(color == 0x00ffffff, "pixel 478, 362 has color %08x, expected 0x00ffffff\n", color);
4917     color = getPixelColor(device, 482, 362);
4918     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4919         "pixel 482, 362 has color %08x, expected 0x00000000\n", color);
4920
4921     /* 1.3 shader */
4922     color = getPixelColor(device, 478, 118);
4923     ok(color == 0x00ffffff, "pixel 478, 118 has color %08x, expected 0x00ffffff\n", color);
4924     color = getPixelColor(device, 482, 118);
4925     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4926         "pixel 482, 118 has color %08x, expected 0x00000000\n", color);
4927     color = getPixelColor(device, 478, 122);
4928     ok(color == 0x00ffffff, "pixel 478, 122 has color %08x, expected 0x00ffffff\n", color);
4929     color = getPixelColor(device, 482, 122);
4930     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4931         "pixel 482, 122 has color %08x, expected 0x00000000\n", color);
4932
4933     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
4934     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4935     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1_coi, 1);
4936     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4937     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2_coi, 1);
4938     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4939
4940     hr = IDirect3DDevice9_BeginScene(device);
4941     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4942     if(SUCCEEDED(hr))
4943     {
4944         hr = IDirect3DDevice9_SetPixelShader(device, shader_11_coissue);
4945         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4946         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
4947         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4948
4949         hr = IDirect3DDevice9_SetPixelShader(device, shader_12_coissue);
4950         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4951         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
4952         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4953
4954         hr = IDirect3DDevice9_SetPixelShader(device, shader_13_coissue);
4955         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4956         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 6 * sizeof(float));
4957         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4958
4959         hr = IDirect3DDevice9_SetPixelShader(device, shader_14_coissue);
4960         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4961         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
4962         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4963
4964         hr = IDirect3DDevice9_EndScene(device);
4965         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4966     }
4967     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4968     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4969
4970     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4971     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4972
4973     /* This is the 1.4 test. The coissue doesn't change the behavior here, but keep in mind
4974      * that we swapped the values in c1 and c2 to make the other tests return some color
4975      */
4976     color = getPixelColor(device, 158, 118);
4977     ok(color == 0x00ffffff, "pixel 158, 118 has color %08x, expected 0x00ffffff\n", color);
4978     color = getPixelColor(device, 162, 118);
4979     ok(color == 0x0000ffff, "pixel 162, 118 has color %08x, expected 0x0000ffff\n", color);
4980     color = getPixelColor(device, 158, 122);
4981     ok(color == 0x00ff00ff, "pixel 162, 122 has color %08x, expected 0x00ff00ff\n", color);
4982     color = getPixelColor(device, 162, 122);
4983     ok(color == 0x000000ff, "pixel 162, 122 has color %08x, expected 0x000000ff\n", color);
4984
4985     /* 1.1 shader. coissue flag changed the semantic of cnd, c1 is always selected */
4986     color = getPixelColor(device, 158, 358);
4987     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4988         "pixel 158, 358 has color %08x, expected 0x0000ff00\n", color);
4989     color = getPixelColor(device, 162, 358);
4990     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4991         "pixel 162, 358 has color %08x, expected 0x0000ff00\n", color);
4992     color = getPixelColor(device, 158, 362);
4993     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4994         "pixel 158, 362 has color %08x, expected 0x0000ff00\n", color);
4995     color = getPixelColor(device, 162, 362);
4996     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4997         "pixel 162, 362 has color %08x, expected 0x0000ff00\n", color);
4998
4999     /* 1.2 shader */
5000     color = getPixelColor(device, 478, 358);
5001     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5002         "pixel 478, 358 has color %08x, expected 0x0000ff00\n", color);
5003     color = getPixelColor(device, 482, 358);
5004     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5005         "pixel 482, 358 has color %08x, expected 0x0000ff00\n", color);
5006     color = getPixelColor(device, 478, 362);
5007     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5008         "pixel 478, 362 has color %08x, expected 0x0000ff00\n", color);
5009     color = getPixelColor(device, 482, 362);
5010     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5011         "pixel 482, 362 has color %08x, expected 0x0000ff00\n", color);
5012
5013     /* 1.3 shader */
5014     color = getPixelColor(device, 478, 118);
5015     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5016         "pixel 478, 118 has color %08x, expected 0x0000ff00\n", color);
5017     color = getPixelColor(device, 482, 118);
5018     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5019         "pixel 482, 118 has color %08x, expected 0x0000ff00\n", color);
5020     color = getPixelColor(device, 478, 122);
5021     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5022         "pixel 478, 122 has color %08x, expected 0x0000ff00\n", color);
5023     color = getPixelColor(device, 482, 122);
5024     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5025         "pixel 482, 122 has color %08x, expected 0x0000ff00\n", color);
5026
5027     IDirect3DPixelShader9_Release(shader_14_coissue);
5028     IDirect3DPixelShader9_Release(shader_13_coissue);
5029     IDirect3DPixelShader9_Release(shader_12_coissue);
5030     IDirect3DPixelShader9_Release(shader_11_coissue);
5031     IDirect3DPixelShader9_Release(shader_14);
5032     IDirect3DPixelShader9_Release(shader_13);
5033     IDirect3DPixelShader9_Release(shader_12);
5034     IDirect3DPixelShader9_Release(shader_11);
5035 }
5036
5037 static void nested_loop_test(IDirect3DDevice9 *device) {
5038     const DWORD shader_code[] = {
5039         0xffff0300,                                                             /* ps_3_0               */
5040         0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0, 0, 0, 1   */
5041         0x05000051, 0xa00f0001, 0x3d000000, 0x00000000, 0x00000000, 0x00000000, /* def c1, 1/32, 0, 0, 0*/
5042         0x05000030, 0xf00f0000, 0x00000004, 0x00000000, 0x00000002, 0x00000000, /* defi i0, 4, 0, 2, 0  */
5043         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0           */
5044         0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0          */
5045         0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0          */
5046         0x03000002, 0x800f0000, 0x80e40000, 0xa0e40001,                         /* add r0, r0, c1       */
5047         0x0000001d,                                                             /* endloop              */
5048         0x0000001d,                                                             /* endloop              */
5049         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0          */
5050         0x0000ffff                                                              /* end                  */
5051     };
5052     IDirect3DPixelShader9 *shader;
5053     HRESULT hr;
5054     DWORD color;
5055     const float quad[] = {
5056         -1.0,   -1.0,   0.1,
5057          1.0,   -1.0,   0.1,
5058         -1.0,    1.0,   0.1,
5059          1.0,    1.0,   0.1
5060     };
5061
5062     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
5063     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed with %08x\n", hr);
5064     hr = IDirect3DDevice9_SetPixelShader(device, shader);
5065     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with %08x\n", hr);
5066     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5067     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
5068     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 0.0, 0);
5069     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5070
5071     hr = IDirect3DDevice9_BeginScene(device);
5072     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5073     if(SUCCEEDED(hr))
5074     {
5075         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
5076         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5077         hr = IDirect3DDevice9_EndScene(device);
5078         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5079     }
5080     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5081     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5082
5083     color = getPixelColor(device, 360, 240);
5084     ok(color == 0x007f0000 || color == 0x00800000 || color == 0x00810000,
5085        "Nested loop test returned color 0x%08x, expected 0x00800000\n", color);
5086
5087     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5088     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with %08x\n", hr);
5089     IDirect3DPixelShader9_Release(shader);
5090 }
5091
5092 struct varying_test_struct
5093 {
5094     const DWORD             *shader_code;
5095     IDirect3DPixelShader9   *shader;
5096     DWORD                   color, color_rhw;
5097     const char              *name;
5098     BOOL                    todo, todo_rhw;
5099 };
5100
5101 struct hugeVertex
5102 {
5103     float pos_x,        pos_y,      pos_z,      rhw;
5104     float weight_1,     weight_2,   weight_3,   weight_4;
5105     float index_1,      index_2,    index_3,    index_4;
5106     float normal_1,     normal_2,   normal_3,   normal_4;
5107     float fog_1,        fog_2,      fog_3,      fog_4;
5108     float texcoord_1,   texcoord_2, texcoord_3, texcoord_4;
5109     float tangent_1,    tangent_2,  tangent_3,  tangent_4;
5110     float binormal_1,   binormal_2, binormal_3, binormal_4;
5111     float depth_1,      depth_2,    depth_3,    depth_4;
5112     DWORD diffuse, specular;
5113 };
5114
5115 static void fixed_function_varying_test(IDirect3DDevice9 *device) {
5116     /* dcl_position: fails to compile */
5117     const DWORD blendweight_code[] = {
5118         0xffff0300,                             /* ps_3_0                   */
5119         0x0200001f, 0x80000001, 0x900f0000,     /* dcl_blendweight, v0      */
5120         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5121         0x0000ffff                              /* end                      */
5122     };
5123     const DWORD blendindices_code[] = {
5124         0xffff0300,                             /* ps_3_0                   */
5125         0x0200001f, 0x80000002, 0x900f0000,     /* dcl_blendindices, v0     */
5126         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5127         0x0000ffff                              /* end                      */
5128     };
5129     const DWORD normal_code[] = {
5130         0xffff0300,                             /* ps_3_0                   */
5131         0x0200001f, 0x80000003, 0x900f0000,     /* dcl_normal, v0           */
5132         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5133         0x0000ffff                              /* end                      */
5134     };
5135     /* psize: fails? */
5136     const DWORD texcoord0_code[] = {
5137         0xffff0300,                             /* ps_3_0                   */
5138         0x0200001f, 0x80000005, 0x900f0000,     /* dcl_texcoord0, v0        */
5139         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5140         0x0000ffff                              /* end                      */
5141     };
5142     const DWORD tangent_code[] = {
5143         0xffff0300,                             /* ps_3_0                   */
5144         0x0200001f, 0x80000006, 0x900f0000,     /* dcl_tangent, v0          */
5145         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5146         0x0000ffff                              /* end                      */
5147     };
5148     const DWORD binormal_code[] = {
5149         0xffff0300,                             /* ps_3_0                   */
5150         0x0200001f, 0x80000007, 0x900f0000,     /* dcl_binormal, v0         */
5151         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5152         0x0000ffff                              /* end                      */
5153     };
5154     /* tessfactor: fails */
5155     /* positiont: fails */
5156     const DWORD color_code[] = {
5157         0xffff0300,                             /* ps_3_0                   */
5158         0x0200001f, 0x8000000a, 0x900f0000,     /* dcl_color0, v0           */
5159         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5160         0x0000ffff                              /* end                      */
5161     };
5162     const DWORD fog_code[] = {
5163         0xffff0300,                             /* ps_3_0                   */
5164         0x0200001f, 0x8000000b, 0x900f0000,     /* dcl_fog, v0              */
5165         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5166         0x0000ffff                              /* end                      */
5167     };
5168     const DWORD depth_code[] = {
5169         0xffff0300,                             /* ps_3_0                   */
5170         0x0200001f, 0x8000000c, 0x900f0000,     /* dcl_depth, v0            */
5171         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5172         0x0000ffff                              /* end                      */
5173     };
5174     const DWORD specular_code[] = {
5175         0xffff0300,                             /* ps_3_0                   */
5176         0x0200001f, 0x8001000a, 0x900f0000,     /* dcl_color1, v0           */
5177         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5178         0x0000ffff                              /* end                      */
5179     };
5180     /* sample: fails */
5181
5182     struct varying_test_struct tests[] = {
5183        {blendweight_code,       NULL,       0x00000000,     0x00191919,     "blendweight"   ,   FALSE,  TRUE  },
5184        {blendindices_code,      NULL,       0x00000000,     0x00000000,     "blendindices"  ,   FALSE,  FALSE },
5185        {normal_code,            NULL,       0x00000000,     0x004c4c4c,     "normal"        ,   FALSE,  TRUE  },
5186        /* Why does dx not forward the texcoord? */
5187        {texcoord0_code,         NULL,       0x00000000,     0x00808c8c,     "texcoord0"     ,   FALSE,  FALSE },
5188        {tangent_code,           NULL,       0x00000000,     0x00999999,     "tangent"       ,   FALSE,  TRUE  },
5189        {binormal_code,          NULL,       0x00000000,     0x00b2b2b2,     "binormal"      ,   FALSE,  TRUE  },
5190        {color_code,             NULL,       0x00e6e6e6,     0x00e6e6e6,     "color"         ,   FALSE,  FALSE },
5191        {fog_code,               NULL,       0x00000000,     0x00666666,     "fog"           ,   FALSE,  TRUE  },
5192        {depth_code,             NULL,       0x00000000,     0x00cccccc,     "depth"         ,   FALSE,  TRUE  },
5193        {specular_code,          NULL,       0x004488ff,     0x004488ff,     "specular"      ,   FALSE,  FALSE }
5194     };
5195     /* Declare a monster vertex type :-) */
5196     static const D3DVERTEXELEMENT9 decl_elements[] = {
5197         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
5198         {0,  16,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT,    0},
5199         {0,  32,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES,   0},
5200         {0,  48,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,         0},
5201         {0,  64,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_FOG,            0},
5202         {0,  80,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
5203         {0,  96,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT,        0},
5204         {0, 112,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL,       0},
5205         {0, 128,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_DEPTH,          0},
5206         {0, 144,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
5207         {0, 148,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          1},
5208         D3DDECL_END()
5209     };
5210     static const D3DVERTEXELEMENT9 decl_elements2[] = {
5211         {0,   0,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT,      0},
5212         {0,  16,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT,    0},
5213         {0,  32,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES,   0},
5214         {0,  48,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,         0},
5215         {0,  64,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_FOG,            0},
5216         {0,  80,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
5217         {0,  96,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT,        0},
5218         {0, 112,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL,       0},
5219         {0, 128,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_DEPTH,          0},
5220         {0, 144,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
5221         {0, 148,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          1},
5222         D3DDECL_END()
5223     };
5224     struct hugeVertex data[4] = {
5225         {
5226             -1.0,   -1.0,   0.1,    1.0,
5227              0.1,    0.1,   0.1,    0.1,
5228              0.2,    0.2,   0.2,    0.2,
5229              0.3,    0.3,   0.3,    0.3,
5230              0.4,    0.4,   0.4,    0.4,
5231              0.50,   0.55,  0.55,   0.55,
5232              0.6,    0.6,   0.6,    0.7,
5233              0.7,    0.7,   0.7,    0.6,
5234              0.8,    0.8,   0.8,    0.8,
5235              0xe6e6e6e6, /* 0.9 * 256 */
5236              0x224488ff  /* Nothing special */
5237         },
5238         {
5239              1.0,   -1.0,   0.1,    1.0,
5240              0.1,    0.1,   0.1,    0.1,
5241              0.2,    0.2,   0.2,    0.2,
5242              0.3,    0.3,   0.3,    0.3,
5243              0.4,    0.4,   0.4,    0.4,
5244              0.50,   0.55,  0.55,   0.55,
5245              0.6,    0.6,   0.6,    0.7,
5246              0.7,    0.7,   0.7,    0.6,
5247              0.8,    0.8,   0.8,    0.8,
5248              0xe6e6e6e6, /* 0.9 * 256 */
5249              0x224488ff /* Nothing special */
5250         },
5251         {
5252             -1.0,    1.0,   0.1,    1.0,
5253              0.1,    0.1,   0.1,    0.1,
5254              0.2,    0.2,   0.2,    0.2,
5255              0.3,    0.3,   0.3,    0.3,
5256              0.4,    0.4,   0.4,    0.4,
5257              0.50,   0.55,  0.55,   0.55,
5258              0.6,    0.6,   0.6,    0.7,
5259              0.7,    0.7,   0.7,    0.6,
5260              0.8,    0.8,   0.8,    0.8,
5261              0xe6e6e6e6, /* 0.9 * 256 */
5262              0x224488ff /* Nothing special */
5263         },
5264         {
5265              1.0,    1.0,   0.1,    1.0,
5266              0.1,    0.1,   0.1,    0.1,
5267              0.2,    0.2,   0.2,    0.2,
5268              0.3,    0.3,   0.3,    0.3,
5269              0.4,    0.4,   0.4,    0.4,
5270              0.50,   0.55,  0.55,   0.55,
5271              0.6,    0.6,   0.6,    0.7,
5272              0.7,    0.7,   0.7,    0.6,
5273              0.8,    0.8,   0.8,    0.8,
5274              0xe6e6e6e6, /* 0.9 * 256 */
5275              0x224488ff /* Nothing special */
5276         },
5277     };
5278     struct hugeVertex data2[4];
5279     IDirect3DVertexDeclaration9 *decl;
5280     IDirect3DVertexDeclaration9 *decl2;
5281     HRESULT hr;
5282     unsigned int i;
5283     DWORD color, r, g, b, r_e, g_e, b_e;
5284     BOOL drawok;
5285
5286     memcpy(data2, data, sizeof(data2));
5287     data2[0].pos_x = 0;     data2[0].pos_y = 0;
5288     data2[1].pos_x = 640;   data2[1].pos_y = 0;
5289     data2[2].pos_x = 0;     data2[2].pos_y = 480;
5290     data2[3].pos_x = 640;   data2[3].pos_y = 480;
5291
5292     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
5293     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
5294     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements2, &decl2);
5295     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
5296     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
5297     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
5298
5299     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
5300     {
5301         hr = IDirect3DDevice9_CreatePixelShader(device, tests[i].shader_code, &tests[i].shader);
5302         ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed for shader %s, hr = %08x\n",
5303            tests[i].name, hr);
5304     }
5305
5306     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
5307     {
5308         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
5309         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5310
5311         IDirect3DDevice9_SetPixelShader(device, tests[i].shader);
5312         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5313
5314         hr = IDirect3DDevice9_BeginScene(device);
5315         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5316         drawok = FALSE;
5317         if(SUCCEEDED(hr))
5318         {
5319             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, data, sizeof(data[0]));
5320             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed (%08x)\n", hr);
5321             drawok = SUCCEEDED(hr);
5322             hr = IDirect3DDevice9_EndScene(device);
5323             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5324         }
5325         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5326         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5327
5328         /* Some drivers reject the combination of ps_3_0 and fixed function vertex processing. Accept
5329          * the failure and do not check the color if it failed
5330          */
5331         if(!drawok) {
5332             continue;
5333         }
5334
5335         color = getPixelColor(device, 360, 240);
5336         r = color & 0x00ff0000 >> 16;
5337         g = color & 0x0000ff00 >>  8;
5338         b = color & 0x000000ff;
5339         r_e = tests[i].color & 0x00ff0000 >> 16;
5340         g_e = tests[i].color & 0x0000ff00 >>  8;
5341         b_e = tests[i].color & 0x000000ff;
5342
5343         if(tests[i].todo) {
5344             todo_wine ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
5345                          "Test %s returned color 0x%08x, expected 0x%08x(todo)\n",
5346                          tests[i].name, color, tests[i].color);
5347         } else {
5348             ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
5349                "Test %s returned color 0x%08x, expected 0x%08x\n",
5350                tests[i].name, color, tests[i].color);
5351         }
5352     }
5353
5354     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl2);
5355     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
5356     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
5357     {
5358         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
5359         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5360
5361         IDirect3DDevice9_SetPixelShader(device, tests[i].shader);
5362         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5363
5364         hr = IDirect3DDevice9_BeginScene(device);
5365         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5366         if(SUCCEEDED(hr))
5367         {
5368             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, data2, sizeof(data2[0]));
5369             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5370             hr = IDirect3DDevice9_EndScene(device);
5371             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5372         }
5373         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5374         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5375
5376         color = getPixelColor(device, 360, 240);
5377         r = color & 0x00ff0000 >> 16;
5378         g = color & 0x0000ff00 >>  8;
5379         b = color & 0x000000ff;
5380         r_e = tests[i].color_rhw & 0x00ff0000 >> 16;
5381         g_e = tests[i].color_rhw & 0x0000ff00 >>  8;
5382         b_e = tests[i].color_rhw & 0x000000ff;
5383
5384         if(tests[i].todo_rhw) {
5385             /* This isn't a weekend's job to fix, ignore the problem for now. Needs a replacement
5386              * pipeline
5387              */
5388             todo_wine ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
5389                          "Test %s returned color 0x%08x, expected 0x%08x(todo)\n",
5390                          tests[i].name, color, tests[i].color_rhw);
5391         } else {
5392             ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
5393                "Test %s returned color 0x%08x, expected 0x%08x\n",
5394                tests[i].name, color, tests[i].color_rhw);
5395         }
5396     }
5397
5398     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
5399     {
5400         IDirect3DPixelShader9_Release(tests[i].shader);
5401     }
5402
5403     IDirect3DVertexDeclaration9_Release(decl2);
5404     IDirect3DVertexDeclaration9_Release(decl);
5405 }
5406
5407 static void vshader_version_varying_test(IDirect3DDevice9 *device) {
5408     static const DWORD ps_code[] = {
5409     0xffff0300,                                                             /* ps_3_0                       */
5410     0x05000030, 0xf00f0000, 0x00000003, 0x00000003, 0x00000001, 0x00000000, /* defi i0, 3, 3, 1, 0          */
5411     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0   */
5412     0x0200001f, 0x8001000a, 0x900f0003,                                     /* dcl_color1 v3                */
5413     0x0200001f, 0x8000000b, 0x900f0004,                                     /* dcl_fog v4                   */
5414     0x0200001f, 0x80030005, 0x900f0005,                                     /* dcl_texcoord3 v5             */
5415     0x0200001f, 0x80000003, 0x900f0006,                                     /* dcl_normal v6                */
5416     0x0200001f, 0x80000006, 0x900f0007,                                     /* dcl_tangent v7               */
5417     0x0200001f, 0x80000001, 0x900f0008,                                     /* dcl_blendweight v8           */
5418     0x0200001f, 0x8000000c, 0x900f0009,                                     /* dcl_depth v9                 */
5419
5420     0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                   */
5421     0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0                  */
5422     0x04000002, 0x800f0000, 0x80e40000, 0x90e42000, 0xf0e40800,             /* add r0, r0, v0[aL]           */
5423     0x0000001d,                                                             /* endloop                      */
5424     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
5425     0x0000ffff                                                              /* end                          */
5426     };
5427     static const DWORD vs_1_code[] = {
5428     0xfffe0101,                                                             /* vs_1_1                       */
5429     0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
5430     0x00000051, 0xa00f0000, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.1, 0.0, 0.0, 0.0   */
5431     0x00000051, 0xa00f0001, 0x00000000, 0x3e4ccccd, 0x00000000, 0x00000000, /* def c1, 0.0, 0.2, 0.0, 0.0   */
5432     0x00000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3ecccccd, 0x00000000, /* def c2, 0.0, 0.0, 0.4, 0.0   */
5433     0x00000051, 0xa00f0003, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 1.0, 1.0, 1.0, 1.0   */
5434     0x00000001, 0xd00f0000, 0xa0e40002,                                     /* mov oD0, c2                  */
5435     0x00000001, 0xd00f0001, 0xa0e40000,                                     /* mov oD1, c0                  */
5436     0x00000001, 0xc00f0001, 0xa0550001,                                     /* mov oFog, c1.g               */
5437     0x00000001, 0xe00f0000, 0xa0e40003,                                     /* mov oT0, c3                  */
5438     0x00000001, 0xe00f0001, 0xa0e40003,                                     /* mov oT1, c3                  */
5439     0x00000001, 0xe00f0002, 0xa0e40003,                                     /* mov oT2, c3                  */
5440     0x00000001, 0xe00f0003, 0xa0e40002,                                     /* mov oT3, c2                  */
5441     0x00000001, 0xe00f0004, 0xa0e40003,                                     /* mov oT4, c3                  */
5442     0x00000001, 0xe00f0005, 0xa0e40003,                                     /* mov oT5, c3                  */
5443     0x00000001, 0xe00f0006, 0xa0e40003,                                     /* mov oT6, c3                  */
5444     0x00000001, 0xe00f0007, 0xa0e40003,                                     /* mov oT7, c3                  */
5445     0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
5446     0x0000ffff
5447     };
5448     DWORD vs_2_code[] = {
5449     0xfffe0200,                                                             /* vs_2_0                       */
5450     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
5451     0x05000051, 0xa00f0000, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.1, 0.0, 0.0, 0.0   */
5452     0x05000051, 0xa00f0001, 0x00000000, 0x3e4ccccd, 0x00000000, 0x00000000, /* def c1, 0.0, 0.2, 0.0, 0.0   */
5453     0x05000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3ecccccd, 0x00000000, /* def c2, 0.0, 0.0, 0.4, 0.0   */
5454     0x05000051, 0xa00f0003, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 1.0, 1.0, 1.0, 1.0   */
5455     0x02000001, 0xd00f0000, 0xa0e40002,                                     /* mov oD0, c2                  */
5456     0x02000001, 0xd00f0001, 0xa0e40000,                                     /* mov oD1, c0                  */
5457     0x02000001, 0xc00f0001, 0xa0550001,                                     /* mov oFog, c1.g               */
5458     0x02000001, 0xe00f0000, 0xa0e40003,                                     /* mov oT0, c3                  */
5459     0x02000001, 0xe00f0001, 0xa0e40003,                                     /* mov oT1, c3                  */
5460     0x02000001, 0xe00f0002, 0xa0e40003,                                     /* mov oT2, c3                  */
5461     0x02000001, 0xe00f0003, 0xa0e40002,                                     /* mov oT3, c2                  */
5462     0x02000001, 0xe00f0004, 0xa0e40003,                                     /* mov oT4, c3                  */
5463     0x02000001, 0xe00f0005, 0xa0e40003,                                     /* mov oT5, c3                  */
5464     0x02000001, 0xe00f0006, 0xa0e40003,                                     /* mov oT6, c3                  */
5465     0x02000001, 0xe00f0007, 0xa0e40003,                                     /* mov oT7, c3                  */
5466     0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
5467     0x0000ffff                                                              /* end                          */
5468     };
5469     /* TODO: Define normal, tangent, blendweight and depth here */
5470     static const DWORD vs_3_code[] = {
5471     0xfffe0300,                                                             /* vs_3_0                       */
5472     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
5473     0x0200001f, 0x8001000a, 0xe00f0009,                                     /* dcl_color1 o9                */
5474     0x0200001f, 0x8000000b, 0xe00f0002,                                     /* dcl_fog o2                   */
5475     0x0200001f, 0x80030005, 0xe00f0005,                                     /* dcl_texcoord3 o5             */
5476     0x0200001f, 0x80000000, 0xe00f000b,                                     /* dcl_position o11             */
5477     0x05000051, 0xa00f0000, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.1, 0.0, 0.0, 0.0   */
5478     0x05000051, 0xa00f0001, 0x00000000, 0x3e4ccccd, 0x00000000, 0x00000000, /* def c1, 0.0, 0.2, 0.0, 0.0   */
5479     0x05000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3ecccccd, 0x00000000, /* def c2, 0.0, 0.0, 0.4, 0.0   */
5480     0x05000051, 0xa00f0003, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 1.0, 1.0, 1.0, 1.0   */
5481     0x02000001, 0xe00f0009, 0xa0e40000,                                     /* mov o9, c0                   */
5482     0x02000001, 0xe00f0002, 0xa0e40001,                                     /* mov o2, c1                   */
5483     0x02000001, 0xe00f0005, 0xa0e40002,                                     /* mov o5, c2                   */
5484     0x02000001, 0xe00f000b, 0x90e40000,                                     /* mov o11, v0                  */
5485     0x0000ffff                                                              /* end                          */
5486     };
5487     float quad1[] =  {
5488         -1.0,   -1.0,   0.1,
5489          0.0,   -1.0,   0.1,
5490         -1.0,    0.0,   0.1,
5491          0.0,    0.0,   0.1
5492     };
5493     float quad2[] =  {
5494          0.0,   -1.0,   0.1,
5495          1.0,   -1.0,   0.1,
5496          0.0,    0.0,   0.1,
5497          1.0,    0.0,   0.1
5498     };
5499     float quad3[] =  {
5500         -1.0,    0.0,   0.1,
5501          0.0,    0.0,   0.1,
5502         -1.0,    1.0,   0.1,
5503          0.0,    1.0,   0.1
5504     };
5505
5506     HRESULT hr;
5507     DWORD color;
5508     IDirect3DPixelShader9 *pixelshader = NULL;
5509     IDirect3DVertexShader9 *vs_1_shader = NULL;
5510     IDirect3DVertexShader9 *vs_2_shader = NULL;
5511     IDirect3DVertexShader9 *vs_3_shader = NULL;
5512
5513     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff110000, 0.0, 0);
5514
5515     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code, &pixelshader);
5516     ok(hr == D3D_OK, "IDirect3DDevice_CreatePixelShader returned %08x\n", hr);
5517     hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_code, &vs_1_shader);
5518     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5519     hr = IDirect3DDevice9_CreateVertexShader(device, vs_2_code, &vs_2_shader);
5520     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5521     hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_code, &vs_3_shader);
5522     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5523     hr = IDirect3DDevice9_SetPixelShader(device, pixelshader);
5524     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5525     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5526
5527     hr = IDirect3DDevice9_BeginScene(device);
5528     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5529     if(SUCCEEDED(hr))
5530     {
5531         hr = IDirect3DDevice9_SetVertexShader(device, vs_1_shader);
5532         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5533         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 3);
5534         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5535
5536         hr = IDirect3DDevice9_SetVertexShader(device, vs_2_shader);
5537         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5538         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2,  quad2, sizeof(float) * 3);
5539         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5540
5541         hr = IDirect3DDevice9_SetVertexShader(device, vs_3_shader);
5542         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5543         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 3);
5544         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5545
5546         hr = IDirect3DDevice9_EndScene(device);
5547         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5548     }
5549     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5550     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5551
5552     color = getPixelColor(device, 160, 120);
5553     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x1a, 0x34, 0x67), 1),
5554        "vs_3_0 returned color 0x%08x, expected 0x00193366\n", color);
5555     color = getPixelColor(device, 160, 360);
5556     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x4d, 0x00, 0x67), 1),
5557        "vs_1_1 returned color 0x%08x, expected 0x004c0066\n", color);
5558     color = getPixelColor(device, 480, 360);
5559     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x4d, 0x00, 0x67), 1),
5560        "vs_2_0 returned color 0x%08x, expected 0x004c0066\n", color);
5561
5562     /* cleanup */
5563     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5564     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5565     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
5566     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5567     if(pixelshader) IDirect3DPixelShader9_Release(pixelshader);
5568     if(vs_1_shader) IDirect3DVertexShader9_Release(vs_1_shader);
5569     if(vs_2_shader) IDirect3DVertexShader9_Release(vs_2_shader);
5570     if(vs_3_shader) IDirect3DVertexShader9_Release(vs_3_shader);
5571 }
5572
5573 static void pshader_version_varying_test(IDirect3DDevice9 *device) {
5574     static const DWORD vs_code[] = {
5575     0xfffe0300,                                                             /* vs_3_0                       */
5576     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
5577     0x0200001f, 0x80000000, 0xe00f0000,                                     /* dcl_position o0              */
5578     0x0200001f, 0x8000000a, 0xe00f0001,                                     /* dcl_color0 o1                */
5579     0x0200001f, 0x80000005, 0xe00f0002,                                     /* dcl_texcoord0 o2             */
5580     0x0200001f, 0x8000000b, 0xe00f0003,                                     /* dcl_fog o3                   */
5581     0x0200001f, 0x80000003, 0xe00f0004,                                     /* dcl_normal o4                */
5582     0x0200001f, 0x8000000c, 0xe00f0005,                                     /* dcl_depth o5                 */
5583     0x0200001f, 0x80000006, 0xe00f0006,                                     /* dcl_tangent o6               */
5584     0x0200001f, 0x80000001, 0xe00f0007,                                     /* dcl_blendweight o7           */
5585     0x05000051, 0xa00f0001, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c1, 0.1, 0.0, 0.0, 0.0   */
5586     0x05000051, 0xa00f0002, 0x00000000, 0x3e4ccccd, 0x00000000, 0x3f800000, /* def c2, 0.0, 0.2, 0.0, 1.0   */
5587     0x05000051, 0xa00f0003, 0x3ecccccd, 0x3f59999a, 0x3f666666, 0x00000000, /* def c3, 0.4, 0.85,0.9, 0.0   */
5588     0x05000051, 0xa00f0000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c0, 1.0, 1.0, 1.0, 1.0   */
5589
5590     0x02000001, 0xe00f0000, 0x90e40000,                                     /* mov o0, v0                   */
5591     0x02000001, 0xe00f0001, 0xa0e40001,                                     /* mov o1, c1                   */
5592     0x02000001, 0xe00f0002, 0xa0e40002,                                     /* mov o2, c2                   */
5593     0x02000001, 0xe00f0003, 0xa0e40003,                                     /* mov o3, c3                   */
5594     0x02000001, 0xe00f0004, 0xa0e40000,                                     /* mov o4, c0                   */
5595     0x02000001, 0xe00f0005, 0xa0e40000,                                     /* mov o5, c0                   */
5596     0x02000001, 0xe00f0006, 0xa0e40000,                                     /* mov o6, c0                   */
5597     0x02000001, 0xe00f0007, 0xa0e40000,                                     /* mov o7, c0                   */
5598     0x0000ffff                                                              /* end                          */
5599     };
5600     static const DWORD ps_1_code[] = {
5601     0xffff0104,                                                             /* ps_1_4                       */
5602     0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0   */
5603     0x00000040, 0x80070001, 0xb0e40000,                                     /* texcrd r1.xyz, t0            */
5604     0x00000001, 0x80080001, 0xa0ff0000,                                     /* mov r1.a, c0.a               */
5605     0x00000002, 0x800f0000, 0x90e40000, 0x80e40001,                         /* add r0, v0, r1               */
5606     0x0000ffff                                                              /* end                          */
5607     };
5608     static const DWORD ps_2_code[] = {
5609     0xffff0200,                                                             /* ps_2_0                       */
5610     0x0200001f, 0x80000000, 0xb00f0000,                                     /* dcl t0                       */
5611     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl v0                       */
5612     0x0200001f, 0x80000000, 0x900f0001,                                     /* dcl v1                       */
5613
5614     0x02000001, 0x800f0000, 0x90e40000,                                     /* mov r0, v0                   */
5615     0x03000002, 0x800f0000, 0x80e40000,0xb0e40000,                          /* add r0, r0, t0               */
5616     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
5617     0x0000ffff                                                              /* end                          */
5618     };
5619     static const DWORD ps_3_code[] = {
5620     0xffff0300,                                                             /* ps_3_0                       */
5621     0x0200001f, 0x80000005, 0x900f0000,                                     /* dcl_texcoord0 v0             */
5622     0x0200001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                */
5623     0x0200001f, 0x8000000b, 0x900f0002,                                     /* dcl_fog v2                   */
5624
5625     0x02000001, 0x800f0000, 0x90e40000,                                     /* mov r0, v0                   */
5626     0x03000002, 0x800f0000, 0x80e40000, 0x90e40001,                         /* add r0, r0, v1               */
5627     0x03000002, 0x800f0000, 0x80e40000, 0x90e40002,                         /* mov r0, r0, v2               */
5628     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
5629     0x0000ffff                                                              /* end                          */
5630     };
5631
5632     float quad1[] =  {
5633         -1.0,   -1.0,   0.1,
5634          0.0,   -1.0,   0.1,
5635         -1.0,    0.0,   0.1,
5636          0.0,    0.0,   0.1
5637     };
5638     float quad2[] =  {
5639          0.0,   -1.0,   0.1,
5640          1.0,   -1.0,   0.1,
5641          0.0,    0.0,   0.1,
5642          1.0,    0.0,   0.1
5643     };
5644     float quad3[] =  {
5645         -1.0,    0.0,   0.1,
5646          0.0,    0.0,   0.1,
5647         -1.0,    1.0,   0.1,
5648          0.0,    1.0,   0.1
5649     };
5650     float quad4[] =  {
5651          0.0,    0.0,   0.1,
5652          1.0,    0.0,   0.1,
5653          0.0,    1.0,   0.1,
5654          1.0,    1.0,   0.1
5655     };
5656
5657     HRESULT hr;
5658     DWORD color;
5659     IDirect3DVertexShader9 *vertexshader = NULL;
5660     IDirect3DPixelShader9 *ps_1_shader = NULL;
5661     IDirect3DPixelShader9 *ps_2_shader = NULL;
5662     IDirect3DPixelShader9 *ps_3_shader = NULL;
5663     IDirect3DTexture9 *texture = NULL;
5664     D3DLOCKED_RECT lr;
5665     unsigned int x, y;
5666
5667     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
5668
5669     hr = IDirect3DDevice9_CreateTexture(device, 512,  512, 1, 0, D3DFMT_A16B16G16R16, D3DPOOL_MANAGED, &texture, NULL);
5670     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
5671     if(FAILED(hr)) {
5672         skip("D3DFMT_A16B16G16R16 textures not supported\n");
5673         return;
5674     }
5675     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
5676     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %08x\n", hr);
5677     for(y = 0; y < 512; y++) {
5678         for(x = 0; x < 512; x++) {
5679             double r_f = (double) x / (double) 512;
5680             double g_f = (double) y / (double) 512;
5681             unsigned short *dst = (unsigned short *) (((unsigned char *) lr.pBits) + y * lr.Pitch + x * 8);
5682             unsigned short r = (unsigned short) (r_f * 65535.0);
5683             unsigned short g = (unsigned short) (g_f * 65535.0);
5684             dst[0] = r;
5685             dst[1] = g;
5686             dst[2] = 0;
5687             dst[3] = 65535;
5688         }
5689     }
5690     hr = IDirect3DTexture9_UnlockRect(texture, 0);
5691     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect returned %08x\n", hr);
5692
5693     hr = IDirect3DDevice9_CreateVertexShader(device, vs_code, &vertexshader);
5694     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5695     hr = IDirect3DDevice9_CreatePixelShader(device, ps_1_code, &ps_1_shader);
5696     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5697     hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_code, &ps_2_shader);
5698     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5699     hr = IDirect3DDevice9_CreatePixelShader(device, ps_3_code, &ps_3_shader);
5700     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5701     hr = IDirect3DDevice9_SetVertexShader(device, vertexshader);
5702     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5703     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5704
5705     hr = IDirect3DDevice9_BeginScene(device);
5706     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5707     if(SUCCEEDED(hr))
5708     {
5709         hr = IDirect3DDevice9_SetPixelShader(device, ps_1_shader);
5710         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5711         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 3);
5712         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5713
5714         hr = IDirect3DDevice9_SetPixelShader(device, ps_2_shader);
5715         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5716         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2,  quad2, sizeof(float) * 3);
5717         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5718
5719         hr = IDirect3DDevice9_SetPixelShader(device, ps_3_shader);
5720         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5721         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 3);
5722         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5723
5724         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5725         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5726         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
5727         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
5728         hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
5729         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
5730         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
5731         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
5732         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 3);
5733         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5734
5735         hr = IDirect3DDevice9_EndScene(device);
5736         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5737     }
5738     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5739     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5740
5741     color = getPixelColor(device, 160, 120);
5742     ok((color & 0x00ff0000) >= 0x00790000 && (color & 0x00ff0000) <= 0x00810000 &&
5743        (color & 0x0000ff00) == 0x0000ff00 &&
5744        (color & 0x000000ff) >= 0x000000e4 && (color & 0x000000ff) <= 0x000000e6,
5745        "ps_3_0 returned color 0x%08x, expected 0x0080ffe5\n", color);
5746     color = getPixelColor(device, 160, 360);
5747     ok((color & 0x00ff0000) >= 0x00190000 && (color & 0x00ff0000) <= 0x00210000 &&
5748        (color & 0x0000ff00) >= 0x00003300 && (color & 0x0000ff00) <= 0x00003400 &&
5749        (color & 0x000000ff) == 0x00000000,
5750        "ps_1_4 returned color 0x%08x, expected 0x00203300\n", color);
5751     color = getPixelColor(device, 480, 360);
5752     ok((color & 0x00ff0000) >= 0x00190000 && (color & 0x00ff0000) <= 0x00210000 &&
5753        (color & 0x0000ff00) >= 0x00003200 && (color & 0x0000ff00) <= 0x00003400 &&
5754        (color & 0x000000ff) == 0x00000000,
5755        "ps_2_0 returned color 0x%08x, expected 0x00203300\n", color);
5756     color = getPixelColor(device, 480, 160);
5757     ok( color == 0x00ffffff /* Nvidia driver garbage with HW vp */ || (
5758        (color & 0x00ff0000) >= 0x00190000 && (color & 0x00ff0000) <= 0x00210000 &&
5759        (color & 0x0000ff00) >= 0x00003200 && (color & 0x0000ff00) <= 0x00003400 &&
5760        (color & 0x000000ff) == 0x00000000),
5761        "fixed function fragment processing returned color 0x%08x, expected 0x00203300\n", color);
5762
5763     /* cleanup */
5764     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
5765     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
5766     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5767     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5768     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
5769     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5770     if(vertexshader) IDirect3DVertexShader9_Release(vertexshader);
5771     if(ps_1_shader) IDirect3DPixelShader9_Release(ps_1_shader);
5772     if(ps_2_shader) IDirect3DPixelShader9_Release(ps_2_shader);
5773     if(ps_3_shader) IDirect3DPixelShader9_Release(ps_3_shader);
5774     if(texture) IDirect3DTexture9_Release(texture);
5775 }
5776
5777 static void test_compare_instructions(IDirect3DDevice9 *device)
5778 {
5779     DWORD shader_sge_vec_code[] = {
5780         0xfffe0101,                                         /* vs_1_1                   */
5781         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
5782         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
5783         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
5784         0x0000000d, 0xd00f0000, 0x80e40000, 0xa0e40001,     /* sge oD0, r0, c1          */
5785         0x0000ffff                                          /* end                      */
5786     };
5787     DWORD shader_slt_vec_code[] = {
5788         0xfffe0101,                                         /* vs_1_1                   */
5789         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
5790         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
5791         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
5792         0x0000000c, 0xd00f0000, 0x80e40000, 0xa0e40001,     /* slt oD0, r0, c1          */
5793         0x0000ffff                                          /* end                      */
5794     };
5795     DWORD shader_sge_scalar_code[] = {
5796         0xfffe0101,                                         /* vs_1_1                   */
5797         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
5798         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
5799         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
5800         0x0000000d, 0xd0010000, 0x80000000, 0xa0550001,     /* slt oD0.r, r0.r, c1.b    */
5801         0x0000000d, 0xd0020000, 0x80550000, 0xa0aa0001,     /* slt oD0.g, r0.g, c1.r    */
5802         0x0000000d, 0xd0040000, 0x80aa0000, 0xa0000001,     /* slt oD0.b, r0.b, c1.g    */
5803         0x0000ffff                                          /* end                      */
5804     };
5805     DWORD shader_slt_scalar_code[] = {
5806         0xfffe0101,                                         /* vs_1_1                   */
5807         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
5808         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
5809         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
5810         0x0000000c, 0xd0010000, 0x80000000, 0xa0aa0001,     /* slt oD0.r, r0.r, c1.b    */
5811         0x0000000c, 0xd0020000, 0x80550000, 0xa0000001,     /* slt oD0.g, r0.g, c1.r    */
5812         0x0000000c, 0xd0040000, 0x80aa0000, 0xa0550001,     /* slt oD0.b, r0.b, c1.g    */
5813         0x0000ffff                                          /* end                      */
5814     };
5815     IDirect3DVertexShader9 *shader_sge_vec;
5816     IDirect3DVertexShader9 *shader_slt_vec;
5817     IDirect3DVertexShader9 *shader_sge_scalar;
5818     IDirect3DVertexShader9 *shader_slt_scalar;
5819     HRESULT hr, color;
5820     float quad1[] =  {
5821         -1.0,   -1.0,   0.1,
5822          0.0,   -1.0,   0.1,
5823         -1.0,    0.0,   0.1,
5824          0.0,    0.0,   0.1
5825     };
5826     float quad2[] =  {
5827          0.0,   -1.0,   0.1,
5828          1.0,   -1.0,   0.1,
5829          0.0,    0.0,   0.1,
5830          1.0,    0.0,   0.1
5831     };
5832     float quad3[] =  {
5833         -1.0,    0.0,   0.1,
5834          0.0,    0.0,   0.1,
5835         -1.0,    1.0,   0.1,
5836          0.0,    1.0,   0.1
5837     };
5838     float quad4[] =  {
5839          0.0,    0.0,   0.1,
5840          1.0,    0.0,   0.1,
5841          0.0,    1.0,   0.1,
5842          1.0,    1.0,   0.1
5843     };
5844     const float const0[4] = {0.8, 0.2, 0.2, 0.2};
5845     const float const1[4] = {0.2, 0.8, 0.2, 0.2};
5846
5847     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
5848
5849     hr = IDirect3DDevice9_CreateVertexShader(device, shader_sge_vec_code, &shader_sge_vec);
5850     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5851     hr = IDirect3DDevice9_CreateVertexShader(device, shader_slt_vec_code, &shader_slt_vec);
5852     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5853     hr = IDirect3DDevice9_CreateVertexShader(device, shader_sge_scalar_code, &shader_sge_scalar);
5854     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5855     hr = IDirect3DDevice9_CreateVertexShader(device, shader_slt_scalar_code, &shader_slt_scalar);
5856     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5857     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, const0, 1);
5858     ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
5859     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, const1, 1);
5860     ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
5861     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5862     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetFVF failed (%08x)\n", hr);
5863
5864     hr = IDirect3DDevice9_BeginScene(device);
5865     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5866     if(SUCCEEDED(hr))
5867     {
5868         hr = IDirect3DDevice9_SetVertexShader(device, shader_sge_vec);
5869         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5870         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 3);
5871         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5872
5873         hr = IDirect3DDevice9_SetVertexShader(device, shader_slt_vec);
5874         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5875         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2,  quad2, sizeof(float) * 3);
5876         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5877
5878         hr = IDirect3DDevice9_SetVertexShader(device, shader_sge_scalar);
5879         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5880         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 3);
5881         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5882
5883         hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, const0, 1);
5884         ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
5885
5886         hr = IDirect3DDevice9_SetVertexShader(device, shader_slt_scalar);
5887         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5888         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 3);
5889         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5890
5891         hr = IDirect3DDevice9_EndScene(device);
5892         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5893     }
5894
5895     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5896     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5897     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
5898     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5899
5900     color = getPixelColor(device, 160, 360);
5901     ok(color == 0x00FF00FF, "Compare test: Quad 1(sge vec) returned color 0x%08x, expected 0x00FF00FF\n", color);
5902     color = getPixelColor(device, 480, 360);
5903     ok(color == 0x0000FF00, "Compare test: Quad 2(slt vec) returned color 0x%08x, expected 0x0000FF00\n", color);
5904     color = getPixelColor(device, 160, 120);
5905     ok(color == 0x00FFFFFF, "Compare test: Quad 3(sge scalar) returned color 0x%08x, expected 0x00FFFFFF\n", color);
5906     color = getPixelColor(device, 480, 160);
5907     ok(color == 0x000000ff, "Compare test: Quad 4(slt scalar) returned color 0x%08x, expected 0x000000ff\n", color);
5908
5909     IDirect3DVertexShader9_Release(shader_sge_vec);
5910     IDirect3DVertexShader9_Release(shader_slt_vec);
5911     IDirect3DVertexShader9_Release(shader_sge_scalar);
5912     IDirect3DVertexShader9_Release(shader_slt_scalar);
5913 }
5914
5915 static void test_vshader_input(IDirect3DDevice9 *device)
5916 {
5917     DWORD swapped_shader_code_3[] = {
5918         0xfffe0300,                                         /* vs_3_0               */
5919         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
5920         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
5921         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5922         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
5923         0x0200001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
5924         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
5925         0x02000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
5926         0x03000002, 0xe00f0001, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
5927         0x0000ffff                                          /* end                  */
5928     };
5929     DWORD swapped_shader_code_1[] = {
5930         0xfffe0101,                                         /* vs_1_1               */
5931         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5932         0x0000001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
5933         0x0000001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
5934         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov o0, v0           */
5935         0x00000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
5936         0x00000002, 0xd00f0000, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
5937         0x0000ffff                                          /* end                  */
5938     };
5939     DWORD swapped_shader_code_2[] = {
5940         0xfffe0200,                                         /* vs_2_0               */
5941         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5942         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
5943         0x0200001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
5944         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov o0, v0           */
5945         0x02000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
5946         0x03000002, 0xd00f0000, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
5947         0x0000ffff                                          /* end                  */
5948     };
5949     DWORD texcoord_color_shader_code_3[] = {
5950         0xfffe0300,                                         /* vs_3_0               */
5951         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
5952         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
5953         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5954         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
5955         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
5956         0x02000001, 0xe00f0001, 0x90e40001,                 /* mov o1, v1           */
5957         0x0000ffff                                          /* end                  */
5958     };
5959     DWORD texcoord_color_shader_code_2[] = {
5960         0xfffe0200,                                         /* vs_2_0               */
5961         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5962         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
5963         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
5964         0x02000001, 0xd00f0000, 0x90e40001,                 /* mov oD0, v1          */
5965         0x0000ffff                                          /* end                  */
5966     };
5967     DWORD texcoord_color_shader_code_1[] = {
5968         0xfffe0101,                                         /* vs_1_1               */
5969         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5970         0x0000001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
5971         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
5972         0x00000001, 0xd00f0000, 0x90e40001,                 /* mov oD0, v1          */
5973         0x0000ffff                                          /* end                  */
5974     };
5975     DWORD color_color_shader_code_3[] = {
5976         0xfffe0300,                                         /* vs_3_0               */
5977         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
5978         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
5979         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5980         0x0200001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
5981         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
5982         0x03000005, 0xe00f0001, 0xa0e40000, 0x90e40001,     /* mul o1, c0, v1       */
5983         0x0000ffff                                          /* end                  */
5984     };
5985     DWORD color_color_shader_code_2[] = {
5986         0xfffe0200,                                         /* vs_2_0               */
5987         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5988         0x0200001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
5989         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
5990         0x03000005, 0xd00f0000, 0xa0e40000, 0x90e40001,     /* mul oD0, c0, v1       */
5991         0x0000ffff                                          /* end                  */
5992     };
5993     DWORD color_color_shader_code_1[] = {
5994         0xfffe0101,                                         /* vs_1_1               */
5995         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5996         0x0000001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
5997         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
5998         0x00000005, 0xd00f0000, 0xa0e40000, 0x90e40001,     /* mul oD0, c0, v1       */
5999         0x0000ffff                                          /* end                  */
6000     };
6001     IDirect3DVertexShader9 *swapped_shader, *texcoord_color_shader, *color_color_shader;
6002     HRESULT hr;
6003     DWORD color;
6004     float quad1[] =  {
6005         -1.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6006          0.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6007         -1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6008          0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6009     };
6010     float quad2[] =  {
6011          0.0,   -1.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6012          1.0,   -1.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6013          0.0,    0.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6014          1.0,    0.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6015     };
6016     float quad3[] =  {
6017         -1.0,    0.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    1.0,    -1.0,   0.0,    0.0,
6018          0.0,    0.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    1.0,     0.0,   0.0,    0.0,
6019         -1.0,    1.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    0.0,    -1.0,   1.0,    0.0,
6020          0.0,    1.0,   0.1,   -1.0,    0.0,    0.0,    0.0,   -1.0,     0.0,   0.0,    0.0,
6021     };
6022     float quad4[] =  {
6023          0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6024          1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6025          0.0,    1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6026          1.0,    1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6027     };
6028     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd[] = {
6029         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6030         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6031         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
6032         D3DDECL_END()
6033     };
6034     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd_rightorder[] = {
6035         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6036         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
6037         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6038         D3DDECL_END()
6039     };
6040     static const D3DVERTEXELEMENT9 decl_elements_onetexcrd[] = {
6041         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6042         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6043         D3DDECL_END()
6044     };
6045     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd_wrongidx[] = {
6046         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6047         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
6048         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       2},
6049         D3DDECL_END()
6050     };
6051     static const D3DVERTEXELEMENT9 decl_elements_texcoord_color[] = {
6052         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6053         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6054         D3DDECL_END()
6055     };
6056     static const D3DVERTEXELEMENT9 decl_elements_color_color[] = {
6057         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6058         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6059         D3DDECL_END()
6060     };
6061     static const D3DVERTEXELEMENT9 decl_elements_color_ubyte[] = {
6062         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6063         {0,  12,  D3DDECLTYPE_UBYTE4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6064         D3DDECL_END()
6065     };
6066     static const D3DVERTEXELEMENT9 decl_elements_color_float[] = {
6067         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6068         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6069         D3DDECL_END()
6070     };
6071     IDirect3DVertexDeclaration9 *decl_twotexcrd, *decl_onetexcrd, *decl_twotex_wrongidx, *decl_twotexcrd_rightorder;
6072     IDirect3DVertexDeclaration9 *decl_texcoord_color, *decl_color_color, *decl_color_ubyte, *decl_color_float;
6073     unsigned int i;
6074     float normalize[4] = {1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0};
6075     float no_normalize[4] = {1.0, 1.0, 1.0, 1.0};
6076
6077     struct vertex quad1_color[] =  {
6078        {-1.0,   -1.0,   0.1,    0x00ff8040},
6079        { 0.0,   -1.0,   0.1,    0x00ff8040},
6080        {-1.0,    0.0,   0.1,    0x00ff8040},
6081        { 0.0,    0.0,   0.1,    0x00ff8040}
6082     };
6083     struct vertex quad2_color[] =  {
6084        { 0.0,   -1.0,   0.1,    0x00ff8040},
6085        { 1.0,   -1.0,   0.1,    0x00ff8040},
6086        { 0.0,    0.0,   0.1,    0x00ff8040},
6087        { 1.0,    0.0,   0.1,    0x00ff8040}
6088     };
6089     struct vertex quad3_color[] =  {
6090        {-1.0,    0.0,   0.1,    0x00ff8040},
6091        { 0.0,    0.0,   0.1,    0x00ff8040},
6092        {-1.0,    1.0,   0.1,    0x00ff8040},
6093        { 0.0,    1.0,   0.1,    0x00ff8040}
6094     };
6095     float quad4_color[] =  {
6096          0.0,    0.0,   0.1,    1.0,    1.0,    0.0,    0.0,
6097          1.0,    0.0,   0.1,    1.0,    1.0,    0.0,    1.0,
6098          0.0,    1.0,   0.1,    1.0,    1.0,    0.0,    0.0,
6099          1.0,    1.0,   0.1,    1.0,    1.0,    0.0,    1.0,
6100     };
6101
6102     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd, &decl_twotexcrd);
6103     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6104     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_onetexcrd, &decl_onetexcrd);
6105     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6106     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd_wrongidx, &decl_twotex_wrongidx);
6107     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6108     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd_rightorder, &decl_twotexcrd_rightorder);
6109     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6110
6111     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_texcoord_color, &decl_texcoord_color);
6112     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6113     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_color, &decl_color_color);
6114     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6115     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_ubyte, &decl_color_ubyte);
6116     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6117     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_float, &decl_color_float);
6118     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6119
6120     for(i = 1; i <= 3; i++) {
6121         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
6122         if(i == 3) {
6123             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_3, &swapped_shader);
6124             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6125         } else if(i == 2){
6126             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_2, &swapped_shader);
6127             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6128         } else if(i == 1) {
6129             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_1, &swapped_shader);
6130             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6131         }
6132
6133         hr = IDirect3DDevice9_BeginScene(device);
6134         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6135         if(SUCCEEDED(hr))
6136         {
6137             hr = IDirect3DDevice9_SetVertexShader(device, swapped_shader);
6138             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6139
6140             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd);
6141             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6142             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 11);
6143             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6144
6145             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_onetexcrd);
6146             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6147             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(float) * 11);
6148             if(i == 3 || i == 2) {
6149                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
6150             } else if(i == 1) {
6151                 /* Succeeds or fails, depending on SW or HW vertex processing */
6152                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x), i = 1\n", hr);
6153             }
6154
6155             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd_rightorder);
6156             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6157             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 11);
6158             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6159
6160             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotex_wrongidx);
6161             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6162             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 11);
6163             if(i == 3 || i == 2) {
6164                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
6165             } else if(i == 1) {
6166                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = 1\n", hr);
6167             }
6168
6169             hr = IDirect3DDevice9_EndScene(device);
6170             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6171         }
6172
6173         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6174         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6175
6176         if(i == 3 || i == 2) {
6177             color = getPixelColor(device, 160, 360);
6178             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x80), 1),
6179                "Input test: Quad 1(2crd) returned color 0x%08x, expected 0x00FFFF80\n", color);
6180
6181             /* The last value of the read but undefined stream is used, it is 0x00. The defined input is vec4(1, 0, 0, 0) */
6182             color = getPixelColor(device, 480, 360);
6183             ok(color == 0x00FFFF00 || color ==0x00FF0000,
6184                "Input test: Quad 2(1crd) returned color 0x%08x, expected 0x00FFFF00\n", color);
6185             color = getPixelColor(device, 160, 120);
6186             /* Same as above, accept both the last used value and 0.0 for the undefined streams */
6187             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x80), 1) || color == D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00),
6188                "Input test: Quad 3(2crd-wrongidx) returned color 0x%08x, expected 0x00FF0080\n", color);
6189
6190             color = getPixelColor(device, 480, 160);
6191             ok(color == 0x00000000, "Input test: Quad 4(2crd-rightorder) returned color 0x%08x, expected 0x00000000\n", color);
6192         } else if(i == 1) {
6193             color = getPixelColor(device, 160, 360);
6194             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x80), 1),
6195                "Input test: Quad 1(2crd) returned color 0x%08x, expected 0x00FFFF80\n", color);
6196             color = getPixelColor(device, 480, 360);
6197             /* Accept the clear color as well in this case, since SW VP returns an error */
6198             ok(color == 0x00FFFF00 || color == 0x00FF0000, "Input test: Quad 2(1crd) returned color 0x%08x, expected 0x00FFFF00\n", color);
6199             color = getPixelColor(device, 160, 120);
6200             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x80), 1) || color == D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00),
6201                "Input test: Quad 3(2crd-wrongidx) returned color 0x%08x, expected 0x00FF0080\n", color);
6202             color = getPixelColor(device, 480, 160);
6203             ok(color == 0x00000000, "Input test: Quad 4(2crd-rightorder) returned color 0x%08x, expected 0x00000000\n", color);
6204         }
6205
6206         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff808080, 0.0, 0);
6207         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
6208
6209         /* Now find out if the whole streams are re-read, or just the last active value for the
6210          * vertices is used.
6211          */
6212         hr = IDirect3DDevice9_BeginScene(device);
6213         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6214         if(SUCCEEDED(hr))
6215         {
6216             float quad1_modified[] =  {
6217                 -1.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,   -1.0,     0.0,   0.0,    0.0,
6218                  0.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.0,    0.0,
6219                 -1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,     0.0,  -1.0,    0.0,
6220                  0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,   -1.0,    -1.0,  -1.0,    0.0,
6221             };
6222             float quad2_modified[] =  {
6223                  0.0,   -1.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6224                  1.0,   -1.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6225                  0.0,    0.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6226                  1.0,    0.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6227             };
6228
6229             hr = IDirect3DDevice9_SetVertexShader(device, swapped_shader);
6230             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6231
6232             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd);
6233             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6234             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 3, quad1_modified, sizeof(float) * 11);
6235             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6236
6237             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_onetexcrd);
6238             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6239             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2_modified, sizeof(float) * 11);
6240             if(i == 3 || i == 2) {
6241                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
6242             } else if(i == 1) {
6243                 /* Succeeds or fails, depending on SW or HW vertex processing */
6244                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x), i = 1\n", hr);
6245             }
6246
6247             hr = IDirect3DDevice9_EndScene(device);
6248             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6249         }
6250         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6251         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6252
6253         color = getPixelColor(device, 480, 350);
6254         /* vs_1_1 may fail, accept the clear color. Some drivers also set the undefined streams to 0, accept that
6255          * as well.
6256          *
6257          * NOTE: This test fails on the reference rasterizer. In the refrast, the 4 vertices have different colors,
6258          * i.e., the whole old stream is read, and not just the last used attribute. Some games require that this
6259          * does *not* happen, otherwise they can crash because of a read from a bad pointer, so do not accept the
6260          * refrast's result.
6261          *
6262          * A test app for this behavior is Half Life 2 Episode 2 in dxlevel 95, and related games(Portal, TF2).
6263          */
6264         ok(color == 0x000000FF || color == 0x00808080 || color == 0x00000000,
6265            "Input test: Quad 2(different colors) returned color 0x%08x, expected 0x000000FF, 0x00808080 or 0x00000000\n", color);
6266         color = getPixelColor(device, 160, 120);
6267
6268         IDirect3DDevice9_SetVertexShader(device, NULL);
6269         IDirect3DDevice9_SetVertexDeclaration(device, NULL);
6270
6271         IDirect3DVertexShader9_Release(swapped_shader);
6272     }
6273
6274     for(i = 1; i <= 3; i++) {
6275         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
6276         if(i == 3) {
6277             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_3, &texcoord_color_shader);
6278             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6279             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_3, &color_color_shader);
6280             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6281         } else if(i == 2){
6282             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_2, &texcoord_color_shader);
6283             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6284             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_2, &color_color_shader);
6285             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6286         } else if(i == 1) {
6287             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_1, &texcoord_color_shader);
6288             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6289             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_1, &color_color_shader);
6290             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6291         }
6292
6293         hr = IDirect3DDevice9_BeginScene(device);
6294         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6295         if(SUCCEEDED(hr))
6296         {
6297             hr = IDirect3DDevice9_SetVertexShader(device, texcoord_color_shader);
6298             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6299             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_texcoord_color);
6300             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6301             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1_color, sizeof(quad1_color[0]));
6302             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6303
6304             hr = IDirect3DDevice9_SetVertexShader(device, color_color_shader);
6305             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6306
6307             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, normalize, 1);
6308             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6309             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_ubyte);
6310             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6311             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2_color, sizeof(quad2_color[0]));
6312             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6313
6314             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, no_normalize, 1);
6315             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6316             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_color);
6317             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6318             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3_color, sizeof(quad3_color[0]));
6319             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6320
6321             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_float);
6322             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6323             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4_color, sizeof(float) * 7);
6324             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6325
6326             hr = IDirect3DDevice9_EndScene(device);
6327             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6328         }
6329         IDirect3DDevice9_SetVertexShader(device, NULL);
6330         IDirect3DDevice9_SetVertexDeclaration(device, NULL);
6331
6332         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6333         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6334
6335         color = getPixelColor(device, 160, 360);
6336         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x80, 0x40), 1),
6337            "Input test: Quad 1(color-texcoord) returned color 0x%08x, expected 0x00ff8040\n", color);
6338         color = getPixelColor(device, 480, 360);
6339         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x40, 0x80, 0xff), 1),
6340            "Input test: Quad 2(color-ubyte) returned color 0x%08x, expected 0x004080ff\n", color);
6341         color = getPixelColor(device, 160, 120);
6342         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x80, 0x40), 1),
6343            "Input test: Quad 3(color-color) returned color 0x%08x, expected 0x00ff8040\n", color);
6344         color = getPixelColor(device, 480, 160);
6345         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00), 1),
6346            "Input test: Quad 4(color-float) returned color 0x%08x, expected 0x00FFFF00\n", color);
6347
6348         IDirect3DVertexShader9_Release(texcoord_color_shader);
6349         IDirect3DVertexShader9_Release(color_color_shader);
6350     }
6351
6352     IDirect3DVertexDeclaration9_Release(decl_twotexcrd);
6353     IDirect3DVertexDeclaration9_Release(decl_onetexcrd);
6354     IDirect3DVertexDeclaration9_Release(decl_twotex_wrongidx);
6355     IDirect3DVertexDeclaration9_Release(decl_twotexcrd_rightorder);
6356
6357     IDirect3DVertexDeclaration9_Release(decl_texcoord_color);
6358     IDirect3DVertexDeclaration9_Release(decl_color_color);
6359     IDirect3DVertexDeclaration9_Release(decl_color_ubyte);
6360     IDirect3DVertexDeclaration9_Release(decl_color_float);
6361 }
6362
6363 static void srgbtexture_test(IDirect3DDevice9 *device)
6364 {
6365     /* Fill a texture with 0x7f (~ .5), and then turn on the D3DSAMP_SRGBTEXTURE
6366      * texture stage state to render a quad using that texture.  The resulting
6367      * color components should be 0x36 (~ 0.21), per this formula:
6368      *    linear_color = ((srgb_color + 0.055) / 1.055) ^ 2.4
6369      * This is true where srgb_color > 0.04045.
6370      */
6371     IDirect3D9 *d3d = NULL;
6372     HRESULT hr;
6373     LPDIRECT3DTEXTURE9 texture = NULL;
6374     LPDIRECT3DSURFACE9 surface = NULL;
6375     D3DLOCKED_RECT lr;
6376     DWORD color;
6377     float quad[] = {
6378         -1.0,       1.0,       0.0,     0.0,    0.0,
6379          1.0,       1.0,       0.0,     1.0,    0.0,
6380         -1.0,      -1.0,       0.0,     0.0,    1.0,
6381          1.0,      -1.0,       0.0,     1.0,    1.0,
6382     };
6383
6384
6385     memset(&lr, 0, sizeof(lr));
6386     IDirect3DDevice9_GetDirect3D(device, &d3d);
6387     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6388                                     D3DUSAGE_QUERY_SRGBREAD, D3DRTYPE_TEXTURE,
6389                                     D3DFMT_A8R8G8B8) != D3D_OK) {
6390         skip("D3DFMT_A8R8G8B8 textures with SRGBREAD not supported\n");
6391         goto out;
6392     }
6393
6394     hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0,
6395                                         D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
6396                                         &texture, NULL);
6397     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
6398     if(!texture) {
6399         skip("Failed to create A8R8G8B8 texture with SRGBREAD\n");
6400         goto out;
6401     }
6402     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
6403     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
6404
6405     fill_surface(surface, 0xff7f7f7f);
6406     IDirect3DSurface9_Release(surface);
6407
6408     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
6409     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6410     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
6411     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
6412
6413     hr = IDirect3DDevice9_BeginScene(device);
6414     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
6415     if(SUCCEEDED(hr))
6416     {
6417         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, TRUE);
6418         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
6419
6420         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
6421         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
6422
6423
6424         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
6425         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with %08x\n", hr);
6426
6427         hr = IDirect3DDevice9_EndScene(device);
6428         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
6429     }
6430
6431     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6432     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
6433     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, FALSE);
6434     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
6435
6436     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6437     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6438
6439     color = getPixelColor(device, 320, 240);
6440     ok(color == 0x00363636 || color == 0x00373737, "srgb quad has color %08x, expected 0x00363636\n", color);
6441
6442 out:
6443     if(texture) IDirect3DTexture9_Release(texture);
6444     IDirect3D9_Release(d3d);
6445 }
6446
6447 static void shademode_test(IDirect3DDevice9 *device)
6448 {
6449     /* Render a quad and try all of the different fixed function shading models. */
6450     HRESULT hr;
6451     DWORD color0, color1;
6452     DWORD color0_gouraud = 0, color1_gouraud = 0;
6453     DWORD shademode = D3DSHADE_FLAT;
6454     DWORD primtype = D3DPT_TRIANGLESTRIP;
6455     LPVOID data = NULL;
6456     LPDIRECT3DVERTEXBUFFER9 vb_strip = NULL;
6457     LPDIRECT3DVERTEXBUFFER9 vb_list = NULL;
6458     UINT i, j;
6459     struct vertex quad_strip[] =
6460     {
6461         {-1.0f, -1.0f,  0.0f, 0xffff0000  },
6462         {-1.0f,  1.0f,  0.0f, 0xff00ff00  },
6463         { 1.0f, -1.0f,  0.0f, 0xff0000ff  },
6464         { 1.0f,  1.0f,  0.0f, 0xffffffff  }
6465     };
6466     struct vertex quad_list[] =
6467     {
6468         {-1.0f, -1.0f,  0.0f, 0xffff0000  },
6469         {-1.0f,  1.0f,  0.0f, 0xff00ff00  },
6470         { 1.0f, -1.0f,  0.0f, 0xff0000ff  },
6471
6472         {-1.0f,  1.0f,  0.0f, 0xff00ff00  },
6473         { 1.0f, -1.0f,  0.0f, 0xff0000ff  },
6474         { 1.0f,  1.0f,  0.0f, 0xffffffff  }
6475     };
6476
6477     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad_strip),
6478                                              0, 0, D3DPOOL_MANAGED, &vb_strip, NULL);
6479     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
6480     if (FAILED(hr)) goto bail;
6481
6482     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad_list),
6483                                              0, 0, D3DPOOL_MANAGED, &vb_list, NULL);
6484     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
6485     if (FAILED(hr)) goto bail;
6486
6487     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
6488     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6489
6490     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
6491     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
6492
6493     hr = IDirect3DVertexBuffer9_Lock(vb_strip, 0, sizeof(quad_strip), (void **) &data, 0);
6494     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
6495     memcpy(data, quad_strip, sizeof(quad_strip));
6496     hr = IDirect3DVertexBuffer9_Unlock(vb_strip);
6497     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
6498
6499     hr = IDirect3DVertexBuffer9_Lock(vb_list, 0, sizeof(quad_list), (void **) &data, 0);
6500     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
6501     memcpy(data, quad_list, sizeof(quad_list));
6502     hr = IDirect3DVertexBuffer9_Unlock(vb_list);
6503     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
6504
6505     /* Try it first with a TRIANGLESTRIP.  Do it with different geometry because
6506      * the color fixups we have to do for FLAT shading will be dependent on that. */
6507     hr = IDirect3DDevice9_SetStreamSource(device, 0, vb_strip, 0, sizeof(quad_strip[0]));
6508     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
6509
6510     /* First loop uses a TRIANGLESTRIP geometry, 2nd uses a TRIANGLELIST */
6511     for (j=0; j<2; j++) {
6512
6513         /* Inner loop just changes the D3DRS_SHADEMODE */
6514         for (i=0; i<3; i++) {
6515             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
6516             ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
6517
6518             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SHADEMODE, shademode);
6519             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6520
6521             hr = IDirect3DDevice9_BeginScene(device);
6522             ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
6523             if(SUCCEEDED(hr))
6524             {
6525                 hr = IDirect3DDevice9_DrawPrimitive(device, primtype, 0, 2);
6526                 ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed with %08x\n", hr);
6527
6528                 hr = IDirect3DDevice9_EndScene(device);
6529                 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
6530             }
6531
6532             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6533             ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6534
6535             /* Sample two spots from the output */
6536             color0 = getPixelColor(device, 100, 100); /* Inside first triangle */
6537             color1 = getPixelColor(device, 500, 350); /* Inside second triangle */
6538             switch(shademode) {
6539                 case D3DSHADE_FLAT:
6540                     /* Should take the color of the first vertex of each triangle */
6541                     todo_wine ok(color0 == 0x00ff0000, "FLAT shading has color0 %08x, expected 0x00ff0000 (todo)\n", color0);
6542                     todo_wine ok(color1 == 0x0000ff00, "FLAT shading has color1 %08x, expected 0x0000ff00 (todo)\n", color1);
6543                     shademode = D3DSHADE_GOURAUD;
6544                     break;
6545                 case D3DSHADE_GOURAUD:
6546                     /* Should be an interpolated blend */
6547
6548                     ok(color_match(color0, D3DCOLOR_ARGB(0x00, 0x0d, 0xca, 0x28), 2),
6549                        "GOURAUD shading has color0 %08x, expected 0x00dca28\n", color0);
6550                     ok(color_match(color1, D3DCOLOR_ARGB(0x00, 0x0d, 0x45, 0xc7), 2),
6551                        "GOURAUD shading has color1 %08x, expected 0x000d45c7\n", color1);
6552
6553                     color0_gouraud = color0;
6554                     color1_gouraud = color1;
6555
6556                     shademode = D3DSHADE_PHONG;
6557                     break;
6558                 case D3DSHADE_PHONG:
6559                     /* Should be the same as GOURAUD, since no hardware implements this */
6560                     ok(color_match(color0, D3DCOLOR_ARGB(0x00, 0x0d, 0xca, 0x28), 2),
6561                        "PHONG shading has color0 %08x, expected 0x000dca28\n", color0);
6562                     ok(color_match(color1, D3DCOLOR_ARGB(0x00, 0x0d, 0x45, 0xc7), 2),
6563                        "PHONG shading has color1 %08x, expected 0x000d45c7\n", color1);
6564
6565                     ok(color0 == color0_gouraud, "difference between GOURAUD and PHONG shading detected: %08x %08x\n",
6566                             color0_gouraud, color0);
6567                     ok(color1 == color1_gouraud, "difference between GOURAUD and PHONG shading detected: %08x %08x\n",
6568                             color1_gouraud, color1);
6569                     break;
6570             }
6571         }
6572         /* Now, do it all over again with a TRIANGLELIST */
6573         hr = IDirect3DDevice9_SetStreamSource(device, 0, vb_list, 0, sizeof(quad_list[0]));
6574         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
6575         primtype = D3DPT_TRIANGLELIST;
6576         shademode = D3DSHADE_FLAT;
6577     }
6578
6579 bail:
6580     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
6581     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
6582     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
6583     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6584
6585     if (vb_strip)
6586         IDirect3DVertexBuffer9_Release(vb_strip);
6587     if (vb_list)
6588         IDirect3DVertexBuffer9_Release(vb_list);
6589 }
6590
6591
6592 static void fog_srgbwrite_test(IDirect3DDevice9 *device)
6593 {
6594     /* Draw a black quad, half fogged with white fog -> grey color. Enable sRGB writing.
6595      * if sRGB writing is applied before fogging, the 0.0 will be multiplied with ~ 12.92, so still
6596      * stay 0.0. After that the fog gives 0.5. If sRGB writing is applied after fogging, the
6597      * 0.5 will run through the alternative path(0^5 ^ 0.41666 * 1.055 - 0.055), resulting in approx.
6598      * 0.73
6599      *
6600      * At the time of this writing, wined3d could not apply sRGB correction to fixed function rendering,
6601      * so use shaders for this task
6602      */
6603     IDirect3DPixelShader9 *pshader;
6604     IDirect3DVertexShader9 *vshader;
6605     IDirect3D9 *d3d;
6606     DWORD vshader_code[] = {
6607         0xfffe0101,                                                             /* vs_1_1                       */
6608         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
6609         0x00000051, 0xa00f0000, 0x3f000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.5, 0.0, 0.0, 0.0   */
6610         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
6611         0x00000001, 0xc00f0001, 0xa0000000,                                     /* mov oFog, c0.x               */
6612         0x0000ffff                                                              /* end                          */
6613     };
6614     DWORD pshader_code[] = {
6615         0xffff0101,                                                             /* ps_1_1                       */
6616         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0   */
6617         0x00000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                   */
6618         0x0000ffff                                                              /* end                          */
6619     };
6620     const float quad[] = {
6621        -1.0,   -1.0,    0.1,
6622         1.0,   -1.0,    0.1,
6623        -1.0,    1.0,    0.1,
6624         1.0,    1.0,    0.1
6625     };
6626     HRESULT hr;
6627     DWORD color;
6628
6629     IDirect3DDevice9_GetDirect3D(device, &d3d);
6630     /* Ask for srgb writing on D3DRTYPE_TEXTURE. Some Windows drivers do not report it on surfaces.
6631      * For some not entirely understood reasons D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE
6632      * passes on surfaces, while asking for SRGBWRITE alone fails. Textures advertize srgb writing
6633      * alone as well, so use that since it is not the point of this test to show how CheckDeviceFormat
6634      * works
6635      */
6636     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6637                                     D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE,
6638                                     D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8) != D3D_OK) {
6639         skip("No SRGBWRITEENABLE support on D3DFMT_X8R8G8B8\n");
6640         IDirect3D9_Release(d3d);
6641         return;
6642     }
6643     IDirect3D9_Release(d3d);
6644
6645     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
6646     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
6647
6648     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
6649     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6650     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
6651     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6652     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
6653     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6654     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xffffffff);
6655     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6656     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, TRUE);
6657     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6658
6659     hr = IDirect3DDevice9_CreateVertexShader(device, vshader_code, &vshader);
6660     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6661     hr = IDirect3DDevice9_CreatePixelShader(device, pshader_code, &pshader);
6662     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
6663     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
6664     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
6665     hr = IDirect3DDevice9_SetVertexShader(device, vshader);
6666     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6667     hr = IDirect3DDevice9_SetPixelShader(device, pshader);
6668     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
6669
6670     hr = IDirect3DDevice9_BeginScene(device);
6671     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6672     if(SUCCEEDED(hr)) {
6673         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 3);
6674         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6675
6676         hr = IDirect3DDevice9_EndScene(device);
6677         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6678     }
6679
6680     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
6681     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6682     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
6683     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
6684     IDirect3DPixelShader9_Release(pshader);
6685     IDirect3DVertexShader9_Release(vshader);
6686
6687     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
6688     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6689     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, FALSE);
6690     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6691
6692     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6693     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6694     color = getPixelColor(device, 160, 360);
6695     ok(color == 0x00808080 || color == 0x007f7f7f || color == 0x00818181,
6696        "Fog with D3DRS_SRGBWRITEENABLE returned color 0x%08x, expected 0x00808080\n", color);
6697 }
6698
6699 static void alpha_test(IDirect3DDevice9 *device)
6700 {
6701     HRESULT hr;
6702     IDirect3DTexture9 *offscreenTexture;
6703     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
6704     DWORD color;
6705
6706     struct vertex quad1[] =
6707     {
6708         {-1.0f, -1.0f,   0.1f,                          0x4000ff00},
6709         {-1.0f,  0.0f,   0.1f,                          0x4000ff00},
6710         { 1.0f, -1.0f,   0.1f,                          0x4000ff00},
6711         { 1.0f,  0.0f,   0.1f,                          0x4000ff00},
6712     };
6713     struct vertex quad2[] =
6714     {
6715         {-1.0f,  0.0f,   0.1f,                          0xc00000ff},
6716         {-1.0f,  1.0f,   0.1f,                          0xc00000ff},
6717         { 1.0f,  0.0f,   0.1f,                          0xc00000ff},
6718         { 1.0f,  1.0f,   0.1f,                          0xc00000ff},
6719     };
6720     static const float composite_quad[][5] = {
6721         { 0.0f, -1.0f, 0.1f, 0.0f, 1.0f},
6722         { 0.0f,  1.0f, 0.1f, 0.0f, 0.0f},
6723         { 1.0f, -1.0f, 0.1f, 1.0f, 1.0f},
6724         { 1.0f,  1.0f, 0.1f, 1.0f, 0.0f},
6725     };
6726
6727     /* Clear the render target with alpha = 0.5 */
6728     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
6729     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
6730
6731     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
6732     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr);
6733
6734     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
6735     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
6736     if(!backbuffer) {
6737         goto out;
6738     }
6739
6740     hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
6741     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %08x\n", hr);
6742     if(!offscreen) {
6743         goto out;
6744     }
6745
6746     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
6747     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr);
6748
6749     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
6750     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
6751     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
6752     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
6753     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
6754     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
6755     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
6756     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
6757     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
6758     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6759
6760     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
6761     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6762     if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
6763
6764         /* Draw two quads, one with src alpha blending, one with dest alpha blending. */
6765         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
6766         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6767         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
6768         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6769         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
6770         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6771
6772         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
6773         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6774         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
6775         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6776         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
6777         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6778
6779         /* Switch to the offscreen buffer, and redo the testing. The offscreen render target
6780          * doesn't have an alpha channel. DESTALPHA and INVDESTALPHA "don't work" on render
6781          * targets without alpha channel, they give essentially ZERO and ONE blend factors. */
6782         hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
6783         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
6784         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
6785         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
6786
6787         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
6788         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6789         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
6790         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6791         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
6792         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6793
6794         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
6795         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6796         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
6797         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6798         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
6799         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6800
6801         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
6802         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
6803
6804         /* Render the offscreen texture onto the frame buffer to be able to compare it regularly.
6805          * Disable alpha blending for the final composition
6806          */
6807         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
6808         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6809         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
6810         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr);
6811
6812         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
6813         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr = %08x\n", hr);
6814         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, composite_quad, sizeof(float) * 5);
6815         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6816         hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6817         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr = %08x\n", hr);
6818
6819         hr = IDirect3DDevice9_EndScene(device);
6820         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
6821     }
6822
6823     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6824
6825     color = getPixelColor(device, 160, 360);
6826     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1),
6827        "SRCALPHA on frame buffer returned color %08x, expected 0x00bf4000\n", color);
6828
6829     color = getPixelColor(device, 160, 120);
6830     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x7f, 0x00, 0x80), 2),
6831        "DSTALPHA on frame buffer returned color %08x, expected 0x007f0080\n", color);
6832
6833     color = getPixelColor(device, 480, 360);
6834     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1),
6835        "SRCALPHA on texture returned color %08x, expected 0x00bf4000\n", color);
6836
6837     color = getPixelColor(device, 480, 120);
6838     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xff), 1),
6839        "DSTALPHA on texture returned color %08x, expected 0x000000ff\n", color);
6840
6841     out:
6842     /* restore things */
6843     if(backbuffer) {
6844         IDirect3DSurface9_Release(backbuffer);
6845     }
6846     if(offscreenTexture) {
6847         IDirect3DTexture9_Release(offscreenTexture);
6848     }
6849     if(offscreen) {
6850         IDirect3DSurface9_Release(offscreen);
6851     }
6852 }
6853
6854 struct vertex_shortcolor {
6855     float x, y, z;
6856     unsigned short r, g, b, a;
6857 };
6858 struct vertex_floatcolor {
6859     float x, y, z;
6860     float r, g, b, a;
6861 };
6862
6863 static void fixed_function_decl_test(IDirect3DDevice9 *device)
6864 {
6865     HRESULT hr;
6866     BOOL s_ok, ub_ok, f_ok;
6867     DWORD color, size, i;
6868     void *data;
6869     static const D3DVERTEXELEMENT9 decl_elements_d3dcolor[] = {
6870         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6871         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6872         D3DDECL_END()
6873     };
6874     static const D3DVERTEXELEMENT9 decl_elements_d3dcolor_2streams[] = {
6875         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6876         {1,   0,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6877         D3DDECL_END()
6878     };
6879     static const D3DVERTEXELEMENT9 decl_elements_ubyte4n[] = {
6880         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6881         {0,  12,  D3DDECLTYPE_UBYTE4N,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6882         D3DDECL_END()
6883     };
6884     static const D3DVERTEXELEMENT9 decl_elements_ubyte4n_2streams[] = {
6885         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6886         {1,   0,  D3DDECLTYPE_UBYTE4N,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6887         D3DDECL_END()
6888     };
6889     static const D3DVERTEXELEMENT9 decl_elements_short4[] = {
6890         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6891         {0,  12,  D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6892         D3DDECL_END()
6893     };
6894     static const D3DVERTEXELEMENT9 decl_elements_float[] = {
6895         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6896         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6897         D3DDECL_END()
6898     };
6899     static const D3DVERTEXELEMENT9 decl_elements_positiont[] = {
6900         {0,   0,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT,      0},
6901         {0,  16,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6902         D3DDECL_END()
6903     };
6904     IDirect3DVertexDeclaration9 *dcl_float = NULL, *dcl_short = NULL, *dcl_ubyte = NULL, *dcl_color = NULL;
6905     IDirect3DVertexDeclaration9 *dcl_color_2 = NULL, *dcl_ubyte_2 = NULL, *dcl_positiont;
6906     IDirect3DVertexBuffer9 *vb, *vb2;
6907     struct vertex quad1[] =                             /* D3DCOLOR */
6908     {
6909         {-1.0f, -1.0f,   0.1f,                          0x00ffff00},
6910         {-1.0f,  0.0f,   0.1f,                          0x00ffff00},
6911         { 0.0f, -1.0f,   0.1f,                          0x00ffff00},
6912         { 0.0f,  0.0f,   0.1f,                          0x00ffff00},
6913     };
6914     struct vertex quad2[] =                             /* UBYTE4N */
6915     {
6916         {-1.0f,  0.0f,   0.1f,                          0x00ffff00},
6917         {-1.0f,  1.0f,   0.1f,                          0x00ffff00},
6918         { 0.0f,  0.0f,   0.1f,                          0x00ffff00},
6919         { 0.0f,  1.0f,   0.1f,                          0x00ffff00},
6920     };
6921     struct vertex_shortcolor quad3[] =                  /* short */
6922     {
6923         { 0.0f, -1.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
6924         { 0.0f,  0.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
6925         { 1.0f, -1.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
6926         { 1.0f,  0.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
6927     };
6928     struct vertex_floatcolor quad4[] =
6929     {
6930         { 0.0f,  0.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
6931         { 0.0f,  1.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
6932         { 1.0f,  0.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
6933         { 1.0f,  1.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
6934     };
6935     DWORD colors[] = {
6936         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6937         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6938         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6939         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6940         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6941         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6942         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6943         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6944         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6945         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6946         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6947         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6948         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6949         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6950         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6951         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6952     };
6953     float quads[] = {
6954         -1.0,   -1.0,     0.1,
6955         -1.0,    0.0,     0.1,
6956          0.0,   -1.0,     0.1,
6957          0.0,    0.0,     0.1,
6958
6959          0.0,   -1.0,     0.1,
6960          0.0,    0.0,     0.1,
6961          1.0,   -1.0,     0.1,
6962          1.0,    0.0,     0.1,
6963
6964          0.0,    0.0,     0.1,
6965          0.0,    1.0,     0.1,
6966          1.0,    0.0,     0.1,
6967          1.0,    1.0,     0.1,
6968
6969         -1.0,    0.0,     0.1,
6970         -1.0,    1.0,     0.1,
6971          0.0,    0.0,     0.1,
6972          0.0,    1.0,     0.1
6973     };
6974     struct tvertex quad_transformed[] = {
6975        {  90,    110,     0.1,      2.0,        0x00ffff00},
6976        { 570,    110,     0.1,      2.0,        0x00ffff00},
6977        {  90,    300,     0.1,      2.0,        0x00ffff00},
6978        { 570,    300,     0.1,      2.0,        0x00ffff00}
6979     };
6980     D3DCAPS9 caps;
6981
6982     memset(&caps, 0, sizeof(caps));
6983     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6984     ok(hr == D3D_OK, "GetDeviceCaps failed, hr = %08x\n", hr);
6985
6986     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
6987     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
6988
6989     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_d3dcolor, &dcl_color);
6990     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
6991     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_short4, &dcl_short);
6992     ok(SUCCEEDED(hr) || hr == E_FAIL, "CreateVertexDeclaration failed (%08x)\n", hr);
6993     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_float, &dcl_float);
6994     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
6995     if(caps.DeclTypes & D3DDTCAPS_UBYTE4N) {
6996         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_ubyte4n_2streams, &dcl_ubyte_2);
6997         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
6998         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_ubyte4n, &dcl_ubyte);
6999         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7000     } else {
7001         trace("D3DDTCAPS_UBYTE4N not supported\n");
7002         dcl_ubyte_2 = NULL;
7003         dcl_ubyte = NULL;
7004     }
7005     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_d3dcolor_2streams, &dcl_color_2);
7006     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7007     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_positiont, &dcl_positiont);
7008     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7009
7010     size = max(sizeof(quad1), max(sizeof(quad2), max(sizeof(quad3), max(sizeof(quad4), sizeof(quads)))));
7011     hr = IDirect3DDevice9_CreateVertexBuffer(device, size,
7012                                              0, 0, D3DPOOL_MANAGED, &vb, NULL);
7013     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
7014
7015     hr = IDirect3DDevice9_BeginScene(device);
7016     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
7017     f_ok = FALSE; s_ok = FALSE; ub_ok = FALSE;
7018     if(SUCCEEDED(hr)) {
7019         if(dcl_color) {
7020             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color);
7021             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7022             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
7023             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7024         }
7025
7026         /* Tests with non-standard fixed function types fail on the refrast. The ATI driver partially
7027          * accepts them, the nvidia driver accepts them all. All those differences even though we're
7028          * using software vertex processing. Doh!
7029          */
7030         if(dcl_ubyte) {
7031             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte);
7032             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7033             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
7034             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7035             ub_ok = SUCCEEDED(hr);
7036         }
7037
7038         if(dcl_short) {
7039             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_short);
7040             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7041             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(quad3[0]));
7042             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7043             s_ok = SUCCEEDED(hr);
7044         }
7045
7046         if(dcl_float) {
7047             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_float);
7048             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7049             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(quad4[0]));
7050             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7051             f_ok = SUCCEEDED(hr);
7052         }
7053
7054         hr = IDirect3DDevice9_EndScene(device);
7055         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr = %#08x\n", hr);
7056     }
7057
7058     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7059     if(dcl_short) {
7060         color = getPixelColor(device, 480, 360);
7061         ok(color == 0x000000ff || !s_ok,
7062            "D3DDECLTYPE_USHORT4N returned color %08x, expected 0x000000ff\n", color);
7063     }
7064     if(dcl_ubyte) {
7065         color = getPixelColor(device, 160, 120);
7066         ok(color == 0x0000ffff || !ub_ok,
7067            "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x0000ffff\n", color);
7068     }
7069     if(dcl_color) {
7070         color = getPixelColor(device, 160, 360);
7071         ok(color == 0x00ffff00,
7072            "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ffff00\n", color);
7073     }
7074     if(dcl_float) {
7075         color = getPixelColor(device, 480, 120);
7076         ok(color == 0x00ff0000 || !f_ok,
7077            "D3DDECLTYPE_FLOAT4 returned color %08x, expected 0x00ff0000\n", color);
7078     }
7079
7080     /* The following test with vertex buffers doesn't serve to find out new information from windows.
7081      * It is a plain regression test because wined3d uses different codepaths for attribute conversion
7082      * with vertex buffers. It makes sure that the vertex buffer one works, while the above tests
7083      * whether the immediate mode code works
7084      */
7085     f_ok = FALSE; s_ok = FALSE; ub_ok = FALSE;
7086     hr = IDirect3DDevice9_BeginScene(device);
7087     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
7088     if(SUCCEEDED(hr)) {
7089         if(dcl_color) {
7090             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad1), (void **) &data, 0);
7091             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7092             memcpy(data, quad1, sizeof(quad1));
7093             hr = IDirect3DVertexBuffer9_Unlock(vb);
7094             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7095             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color);
7096             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7097             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad1[0]));
7098             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7099             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7100             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7101         }
7102
7103         if(dcl_ubyte) {
7104             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad2), (void **) &data, 0);
7105             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7106             memcpy(data, quad2, sizeof(quad2));
7107             hr = IDirect3DVertexBuffer9_Unlock(vb);
7108             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7109             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte);
7110             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7111             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad2[0]));
7112             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7113             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7114             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7115                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7116             ub_ok = SUCCEEDED(hr);
7117         }
7118
7119         if(dcl_short) {
7120             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad3), (void **) &data, 0);
7121             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7122             memcpy(data, quad3, sizeof(quad3));
7123             hr = IDirect3DVertexBuffer9_Unlock(vb);
7124             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7125             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_short);
7126             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7127             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad3[0]));
7128             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7129             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7130             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7131                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7132             s_ok = SUCCEEDED(hr);
7133         }
7134
7135         if(dcl_float) {
7136             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad4), (void **) &data, 0);
7137             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7138             memcpy(data, quad4, sizeof(quad4));
7139             hr = IDirect3DVertexBuffer9_Unlock(vb);
7140             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7141             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_float);
7142             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7143             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad4[0]));
7144             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7145             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7146             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7147                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7148             f_ok = SUCCEEDED(hr);
7149         }
7150
7151         hr = IDirect3DDevice9_EndScene(device);
7152         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr = %#08x\n", hr);
7153     }
7154
7155     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
7156     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7157     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
7158     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7159
7160     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7161     if(dcl_short) {
7162         color = getPixelColor(device, 480, 360);
7163         ok(color == 0x000000ff || !s_ok,
7164            "D3DDECLTYPE_USHORT4N returned color %08x, expected 0x000000ff\n", color);
7165     }
7166     if(dcl_ubyte) {
7167         color = getPixelColor(device, 160, 120);
7168         ok(color == 0x0000ffff || !ub_ok,
7169            "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x0000ffff\n", color);
7170     }
7171     if(dcl_color) {
7172         color = getPixelColor(device, 160, 360);
7173         ok(color == 0x00ffff00,
7174            "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ffff00\n", color);
7175     }
7176     if(dcl_float) {
7177         color = getPixelColor(device, 480, 120);
7178         ok(color == 0x00ff0000 || !f_ok,
7179            "D3DDECLTYPE_FLOAT4 returned color %08x, expected 0x00ff0000\n", color);
7180     }
7181
7182     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
7183     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
7184
7185     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad_transformed), (void **) &data, 0);
7186     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7187     memcpy(data, quad_transformed, sizeof(quad_transformed));
7188     hr = IDirect3DVertexBuffer9_Unlock(vb);
7189     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7190
7191     hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_positiont);
7192     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7193
7194     hr = IDirect3DDevice9_BeginScene(device);
7195     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7196     if(SUCCEEDED(hr)) {
7197         hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad_transformed[0]));
7198         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7199         hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7200         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7201
7202         hr = IDirect3DDevice9_EndScene(device);
7203         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7204     }
7205
7206     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7207     color = getPixelColor(device, 88, 108);
7208     ok(color == 0x000000ff,
7209        "pixel 88/108 has color %08x, expected 0x000000ff\n", color);
7210     color = getPixelColor(device, 92, 108);
7211     ok(color == 0x000000ff,
7212        "pixel 92/108 has color %08x, expected 0x000000ff\n", color);
7213     color = getPixelColor(device, 88, 112);
7214     ok(color == 0x000000ff,
7215        "pixel 88/112 has color %08x, expected 0x000000ff\n", color);
7216     color = getPixelColor(device, 92, 112);
7217     ok(color == 0x00ffff00,
7218        "pixel 92/112 has color %08x, expected 0x00ffff00\n", color);
7219
7220     color = getPixelColor(device, 568, 108);
7221     ok(color == 0x000000ff,
7222        "pixel 568/108 has color %08x, expected 0x000000ff\n", color);
7223     color = getPixelColor(device, 572, 108);
7224     ok(color == 0x000000ff,
7225        "pixel 572/108 has color %08x, expected 0x000000ff\n", color);
7226     color = getPixelColor(device, 568, 112);
7227     ok(color == 0x00ffff00,
7228        "pixel 568/112 has color %08x, expected 0x00ffff00\n", color);
7229     color = getPixelColor(device, 572, 112);
7230     ok(color == 0x000000ff,
7231        "pixel 572/112 has color %08x, expected 0x000000ff\n", color);
7232
7233     color = getPixelColor(device, 88, 298);
7234     ok(color == 0x000000ff,
7235        "pixel 88/298 has color %08x, expected 0x000000ff\n", color);
7236     color = getPixelColor(device, 92, 298);
7237     ok(color == 0x00ffff00,
7238        "pixel 92/298 has color %08x, expected 0x00ffff00\n", color);
7239     color = getPixelColor(device, 88, 302);
7240     ok(color == 0x000000ff,
7241        "pixel 88/302 has color %08x, expected 0x000000ff\n", color);
7242     color = getPixelColor(device, 92, 302);
7243     ok(color == 0x000000ff,
7244        "pixel 92/302 has color %08x, expected 0x000000ff\n", color);
7245
7246     color = getPixelColor(device, 568, 298);
7247     ok(color == 0x00ffff00,
7248        "pixel 568/298 has color %08x, expected 0x00ffff00\n", color);
7249     color = getPixelColor(device, 572, 298);
7250     ok(color == 0x000000ff,
7251        "pixel 572/298 has color %08x, expected 0x000000ff\n", color);
7252     color = getPixelColor(device, 568, 302);
7253     ok(color == 0x000000ff,
7254        "pixel 568/302 has color %08x, expected 0x000000ff\n", color);
7255     color = getPixelColor(device, 572, 302);
7256     ok(color == 0x000000ff,
7257        "pixel 572/302 has color %08x, expected 0x000000ff\n", color);
7258
7259     /* This test is pointless without those two declarations: */
7260     if((!dcl_color_2) || (!dcl_ubyte_2)) {
7261         skip("color-ubyte switching test declarations aren't supported\n");
7262         goto out;
7263     }
7264
7265     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quads), (void **) &data, 0);
7266     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7267     memcpy(data, quads, sizeof(quads));
7268     hr = IDirect3DVertexBuffer9_Unlock(vb);
7269     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7270     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(colors),
7271                                              0, 0, D3DPOOL_MANAGED, &vb2, NULL);
7272     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
7273     hr = IDirect3DVertexBuffer9_Lock(vb2, 0, sizeof(colors), (void **) &data, 0);
7274     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7275     memcpy(data, colors, sizeof(colors));
7276     hr = IDirect3DVertexBuffer9_Unlock(vb2);
7277     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7278
7279     for(i = 0; i < 2; i++) {
7280         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
7281         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
7282
7283         hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(float) * 3);
7284         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7285         if(i == 0) {
7286             hr = IDirect3DDevice9_SetStreamSource(device, 1, vb2, 0, sizeof(DWORD) * 4);
7287         } else {
7288             hr = IDirect3DDevice9_SetStreamSource(device, 1, vb2, 8, sizeof(DWORD) * 4);
7289         }
7290         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7291
7292         hr = IDirect3DDevice9_BeginScene(device);
7293         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
7294         ub_ok = FALSE;
7295         if(SUCCEEDED(hr)) {
7296             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2);
7297             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7298             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7299             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7300                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7301             ub_ok = SUCCEEDED(hr);
7302
7303             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color_2);
7304             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7305             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 4, 2);
7306             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7307
7308             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2);
7309             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7310             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 8, 2);
7311             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7312                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7313             ub_ok = (SUCCEEDED(hr) && ub_ok);
7314
7315             hr = IDirect3DDevice9_EndScene(device);
7316             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
7317         }
7318
7319         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7320         if(i == 0) {
7321             color = getPixelColor(device, 480, 360);
7322             ok(color == 0x00ff0000,
7323                "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ff0000\n", color);
7324             color = getPixelColor(device, 160, 120);
7325             ok(color == 0x00ffffff,
7326                 "Unused quad returned color %08x, expected 0x00ffffff\n", color);
7327             color = getPixelColor(device, 160, 360);
7328             ok(color == 0x000000ff || !ub_ok,
7329                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x000000ff\n", color);
7330             color = getPixelColor(device, 480, 120);
7331             ok(color == 0x000000ff || !ub_ok,
7332                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x000000ff\n", color);
7333         } else {
7334             color = getPixelColor(device, 480, 360);
7335             ok(color == 0x000000ff,
7336                "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x000000ff\n", color);
7337             color = getPixelColor(device, 160, 120);
7338             ok(color == 0x00ffffff,
7339                "Unused quad returned color %08x, expected 0x00ffffff\n", color);
7340             color = getPixelColor(device, 160, 360);
7341             ok(color == 0x00ff0000 || !ub_ok,
7342                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x00ff0000\n", color);
7343             color = getPixelColor(device, 480, 120);
7344             ok(color == 0x00ff0000 || !ub_ok,
7345                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x00ff0000\n", color);
7346         }
7347     }
7348
7349     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
7350     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7351     hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
7352     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7353     IDirect3DVertexBuffer9_Release(vb2);
7354
7355     out:
7356     IDirect3DVertexBuffer9_Release(vb);
7357     if(dcl_float) IDirect3DVertexDeclaration9_Release(dcl_float);
7358     if(dcl_short) IDirect3DVertexDeclaration9_Release(dcl_short);
7359     if(dcl_ubyte) IDirect3DVertexDeclaration9_Release(dcl_ubyte);
7360     if(dcl_color) IDirect3DVertexDeclaration9_Release(dcl_color);
7361     if(dcl_color_2) IDirect3DVertexDeclaration9_Release(dcl_color_2);
7362     if(dcl_ubyte_2) IDirect3DVertexDeclaration9_Release(dcl_ubyte_2);
7363     if(dcl_positiont) IDirect3DVertexDeclaration9_Release(dcl_positiont);
7364 }
7365
7366 struct vertex_float16color {
7367     float x, y, z;
7368     DWORD c1, c2;
7369 };
7370
7371 static void test_vshader_float16(IDirect3DDevice9 *device)
7372 {
7373     HRESULT hr;
7374     DWORD color;
7375     void *data;
7376     static const D3DVERTEXELEMENT9 decl_elements[] = {
7377         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7378         {0,  12,  D3DDECLTYPE_FLOAT16_4,D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7379         D3DDECL_END()
7380     };
7381     IDirect3DVertexDeclaration9 *vdecl = NULL;
7382     IDirect3DVertexBuffer9 *buffer = NULL;
7383     IDirect3DVertexShader9 *shader;
7384     DWORD shader_code[] = {
7385         0xfffe0101, 0x0000001f, 0x80000000, 0x900f0000, 0x0000001f, 0x8000000a,
7386         0x900f0001, 0x00000001, 0xc00f0000, 0x90e40000, 0x00000001, 0xd00f0000,
7387         0x90e40001, 0x0000ffff
7388     };
7389     struct vertex_float16color quad[] = {
7390         { -1.0,   -1.0,     0.1,        0x3c000000, 0x00000000 }, /* green */
7391         { -1.0,    0.0,     0.1,        0x3c000000, 0x00000000 },
7392         {  0.0,   -1.0,     0.1,        0x3c000000, 0x00000000 },
7393         {  0.0,    0.0,     0.1,        0x3c000000, 0x00000000 },
7394
7395         {  0.0,   -1.0,     0.1,        0x00003c00, 0x00000000 }, /* red */
7396         {  0.0,    0.0,     0.1,        0x00003c00, 0x00000000 },
7397         {  1.0,   -1.0,     0.1,        0x00003c00, 0x00000000 },
7398         {  1.0,    0.0,     0.1,        0x00003c00, 0x00000000 },
7399
7400         {  0.0,    0.0,     0.1,        0x00000000, 0x00003c00 }, /* blue */
7401         {  0.0,    1.0,     0.1,        0x00000000, 0x00003c00 },
7402         {  1.0,    0.0,     0.1,        0x00000000, 0x00003c00 },
7403         {  1.0,    1.0,     0.1,        0x00000000, 0x00003c00 },
7404
7405         { -1.0,    0.0,     0.1,        0x00000000, 0x3c000000 }, /* alpha */
7406         { -1.0,    1.0,     0.1,        0x00000000, 0x3c000000 },
7407         {  0.0,    0.0,     0.1,        0x00000000, 0x3c000000 },
7408         {  0.0,    1.0,     0.1,        0x00000000, 0x3c000000 },
7409     };
7410
7411     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff102030, 0.0, 0);
7412     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7413
7414     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vdecl);
7415     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed hr=%08x\n", hr);
7416     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
7417     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexShader failed hr=%08x\n", hr);
7418     hr = IDirect3DDevice9_SetVertexShader(device, shader);
7419     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
7420
7421     hr = IDirect3DDevice9_BeginScene(device);
7422     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
7423     if(SUCCEEDED(hr)) {
7424         hr = IDirect3DDevice9_SetVertexDeclaration(device, vdecl);
7425         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%08x\n", hr);
7426         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad +  0, sizeof(quad[0]));
7427         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7428         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad +  4, sizeof(quad[0]));
7429         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7430         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad +  8, sizeof(quad[0]));
7431         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7432         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad + 12, sizeof(quad[0]));
7433         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7434
7435         hr = IDirect3DDevice9_EndScene(device);
7436         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%08x\n", hr);
7437     }
7438     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7439     color = getPixelColor(device, 480, 360);
7440     ok(color == 0x00ff0000,
7441        "Input 0x00003c00, 0x00000000 returned color %08x, expected 0x00ff0000\n", color);
7442     color = getPixelColor(device, 160, 120);
7443     ok(color == 0x00000000,
7444        "Input 0x00000000, 0x3c000000 returned color %08x, expected 0x00000000\n", color);
7445     color = getPixelColor(device, 160, 360);
7446     ok(color == 0x0000ff00,
7447        "Input 0x3c000000, 0x00000000 returned color %08x, expected 0x0000ff00\n", color);
7448     color = getPixelColor(device, 480, 120);
7449     ok(color == 0x000000ff,
7450        "Input 0x00000000, 0x00003c00 returned color %08x, expected 0x000000ff\n", color);
7451
7452     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff102030, 0.0, 0);
7453     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7454
7455     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0,
7456                                              D3DPOOL_MANAGED, &buffer, NULL);
7457     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexBuffer failed, hr=%08x\n", hr);
7458     hr = IDirect3DVertexBuffer9_Lock(buffer, 0, sizeof(quad), (void **) &data, 0);
7459     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed, hr=%08x\n", hr);
7460     memcpy(data, quad, sizeof(quad));
7461     hr = IDirect3DVertexBuffer9_Unlock(buffer);
7462     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed, hr=%08x\n", hr);
7463     hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(quad[0]));
7464     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed, hr=%08x\n", hr);
7465
7466     hr = IDirect3DDevice9_BeginScene(device);
7467     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
7468     if(SUCCEEDED(hr)) {
7469             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,  0, 2);
7470             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7471             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,  4, 2);
7472             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7473             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,  8, 2);
7474             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7475             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 12, 2);
7476             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7477
7478             hr = IDirect3DDevice9_EndScene(device);
7479             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%08x\n", hr);
7480     }
7481
7482     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7483     color = getPixelColor(device, 480, 360);
7484     ok(color == 0x00ff0000,
7485        "Input 0x00003c00, 0x00000000 returned color %08x, expected 0x00ff0000\n", color);
7486     color = getPixelColor(device, 160, 120);
7487     ok(color == 0x00000000,
7488        "Input 0x00000000, 0x3c000000 returned color %08x, expected 0x00000000\n", color);
7489     color = getPixelColor(device, 160, 360);
7490     ok(color == 0x0000ff00,
7491        "Input 0x3c000000, 0x00000000 returned color %08x, expected 0x0000ff00\n", color);
7492     color = getPixelColor(device, 480, 120);
7493     ok(color == 0x000000ff,
7494        "Input 0x00000000, 0x00003c00 returned color %08x, expected 0x000000ff\n", color);
7495
7496     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
7497     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed, hr=%08x\n", hr);
7498     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
7499     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%08x\n", hr);
7500     IDirect3DDevice9_SetVertexShader(device, NULL);
7501     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
7502
7503     IDirect3DVertexDeclaration9_Release(vdecl);
7504     IDirect3DVertexShader9_Release(shader);
7505     IDirect3DVertexBuffer9_Release(buffer);
7506 }
7507
7508 static void conditional_np2_repeat_test(IDirect3DDevice9 *device)
7509 {
7510     D3DCAPS9 caps;
7511     IDirect3DTexture9 *texture;
7512     HRESULT hr;
7513     D3DLOCKED_RECT rect;
7514     unsigned int x, y;
7515     DWORD *dst, color;
7516     const float quad[] = {
7517         -1.0,   -1.0,   0.1,   -0.2,   -0.2,
7518          1.0,   -1.0,   0.1,    1.2,   -0.2,
7519         -1.0,    1.0,   0.1,   -0.2,    1.2,
7520          1.0,    1.0,   0.1,    1.2,    1.2
7521     };
7522     memset(&caps, 0, sizeof(caps));
7523
7524     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7525     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%08x\n", hr);
7526     if(!(caps.TextureCaps & D3DPTEXTURECAPS_POW2)) {
7527         /* NP2 conditional requires the POW2 flag. Check that while we're at it */
7528         ok((caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) == 0,
7529            "Card has conditional NP2 support without power of two restriction set\n");
7530         skip("Card has unconditional pow2 support, skipping conditional NP2 tests\n");
7531         return;
7532     } else if(!(caps.TextureCaps & D3DPTEXTURECAPS_POW2)) {
7533         skip("No conditional NP2 support, skipping conditional NP2 tests\n");
7534         return;
7535     }
7536
7537     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
7538     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7539
7540     hr = IDirect3DDevice9_CreateTexture(device, 10, 10, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7541     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed hr=%08x\n", hr);
7542
7543     memset(&rect, 0, sizeof(rect));
7544     hr = IDirect3DTexture9_LockRect(texture, 0, &rect, NULL, 0);
7545     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed hr=%08x\n", hr);
7546     for(y = 0; y < 10; y++) {
7547         for(x = 0; x < 10; x++) {
7548             dst = (DWORD *) ((BYTE *) rect.pBits + y * rect.Pitch + x * sizeof(DWORD));
7549             if(x == 0 || x == 9 || y == 0 || y == 9) {
7550                 *dst = 0x00ff0000;
7551             } else {
7552                 *dst = 0x000000ff;
7553             }
7554         }
7555     }
7556     hr = IDirect3DTexture9_UnlockRect(texture, 0);
7557     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed hr=%08x\n", hr);
7558
7559     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
7560     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
7561     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
7562     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed hr=%08x\n", hr);
7563     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
7564     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed hr=%08x\n", hr);
7565     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7566     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%08x\n", hr);
7567
7568     hr = IDirect3DDevice9_BeginScene(device);
7569     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
7570     if(SUCCEEDED(hr)) {
7571         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
7572         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7573
7574         hr = IDirect3DDevice9_EndScene(device);
7575         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
7576     }
7577
7578     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7579
7580     color = getPixelColor(device,    1,  1);
7581     ok(color == 0x00ff0000, "NP2: Pixel   1,  1 has color %08x, expected 0x00ff0000\n", color);
7582     color = getPixelColor(device, 639, 479);
7583     ok(color == 0x00ff0000, "NP2: Pixel 639, 479 has color %08x, expected 0x00ff0000\n", color);
7584
7585     color = getPixelColor(device, 135, 101);
7586     ok(color == 0x00ff0000, "NP2: Pixel 135, 101 has color %08x, expected 0x00ff0000\n", color);
7587     color = getPixelColor(device, 140, 101);
7588     ok(color == 0x00ff0000, "NP2: Pixel 140, 101 has color %08x, expected 0x00ff0000\n", color);
7589     color = getPixelColor(device, 135, 105);
7590     ok(color == 0x00ff0000, "NP2: Pixel 135, 105 has color %08x, expected 0x00ff0000\n", color);
7591     color = getPixelColor(device, 140, 105);
7592     ok(color == 0x000000ff, "NP2: Pixel 140, 105 has color %08x, expected 0x000000ff\n", color);
7593
7594     color = getPixelColor(device, 135, 376);
7595     ok(color == 0x00ff0000, "NP2: Pixel 135, 376 has color %08x, expected 0x00ff0000\n", color);
7596     color = getPixelColor(device, 140, 376);
7597     ok(color == 0x000000ff, "NP2: Pixel 140, 376 has color %08x, expected 0x000000ff\n", color);
7598     color = getPixelColor(device, 135, 379);
7599     ok(color == 0x00ff0000, "NP2: Pixel 135, 379 has color %08x, expected 0x00ff0000\n", color);
7600     color = getPixelColor(device, 140, 379);
7601     ok(color == 0x00ff0000, "NP2: Pixel 140, 379 has color %08x, expected 0x00ff0000\n", color);
7602
7603     color = getPixelColor(device, 500, 101);
7604     ok(color == 0x00ff0000, "NP2: Pixel 500, 101 has color %08x, expected 0x00ff0000\n", color);
7605     color = getPixelColor(device, 504, 101);
7606     ok(color == 0x00ff0000, "NP2: Pixel 504, 101 has color %08x, expected 0x00ff0000\n", color);
7607     color = getPixelColor(device, 500, 105);
7608     ok(color == 0x000000ff, "NP2: Pixel 500, 105 has color %08x, expected 0x000000ff\n", color);
7609     color = getPixelColor(device, 504, 105);
7610     ok(color == 0x00ff0000, "NP2: Pixel 504, 105 has color %08x, expected 0x00ff0000\n", color);
7611
7612     color = getPixelColor(device, 500, 376);
7613     ok(color == 0x000000ff, "NP2: Pixel 500, 376 has color %08x, expected 0x000000ff\n", color);
7614     color = getPixelColor(device, 504, 376);
7615     ok(color == 0x00ff0000, "NP2: Pixel 504, 376 has color %08x, expected 0x00ff0000\n", color);
7616     color = getPixelColor(device, 500, 380);
7617     ok(color == 0x00ff0000, "NP2: Pixel 500, 380 has color %08x, expected 0x00ff0000\n", color);
7618     color = getPixelColor(device, 504, 380);
7619     ok(color == 0x00ff0000, "NP2: Pixel 504, 380 has color %08x, expected 0x00ff0000\n", color);
7620
7621     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7622     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
7623     IDirect3DTexture9_Release(texture);
7624 }
7625
7626 static void vFace_register_test(IDirect3DDevice9 *device)
7627 {
7628     HRESULT hr;
7629     DWORD color;
7630     const DWORD shader_code[] = {
7631         0xffff0300,                                                             /* ps_3_0                     */
7632         0x05000051, 0xa00f0000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c0, 0.0, 1.0, 0.0, 0.0 */
7633         0x05000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1, 1.0, 0.0, 0.0, 0.0 */
7634         0x0200001f, 0x80000000, 0x900f1001,                                     /* dcl vFace                  */
7635         0x02000001, 0x800f0001, 0xa0e40001,                                     /* mov r1, c1                 */
7636         0x04000058, 0x800f0000, 0x90e41001, 0xa0e40000, 0x80e40001,             /* cmp r0, vFace, c0, r1      */
7637         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                */
7638         0x0000ffff                                                              /* END                        */
7639     };
7640     IDirect3DPixelShader9 *shader;
7641     IDirect3DTexture9 *texture;
7642     IDirect3DSurface9 *surface, *backbuffer;
7643     const float quad[] = {
7644         -1.0,   -1.0,   0.1,
7645          1.0,   -1.0,   0.1,
7646         -1.0,    0.0,   0.1,
7647
7648          1.0,   -1.0,   0.1,
7649          1.0,    0.0,   0.1,
7650         -1.0,    0.0,   0.1,
7651
7652         -1.0,    0.0,   0.1,
7653         -1.0,    1.0,   0.1,
7654          1.0,    0.0,   0.1,
7655
7656          1.0,    0.0,   0.1,
7657         -1.0,    1.0,   0.1,
7658          1.0,    1.0,   0.1,
7659     };
7660     const float blit[] = {
7661          0.0,   -1.0,   0.1,    0.0,    0.0,
7662          1.0,   -1.0,   0.1,    1.0,    0.0,
7663          0.0,    1.0,   0.1,    0.0,    1.0,
7664          1.0,    1.0,   0.1,    1.0,    1.0,
7665     };
7666
7667     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
7668     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed hr=%08x\n", hr);
7669     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7670     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed hr=%08x\n", hr);
7671     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7672     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed hr=%08x\n", hr);
7673     hr = IDirect3DDevice9_SetPixelShader(device, shader);
7674     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
7675     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
7676     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
7677     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7678     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed hr=%08x\n", hr);
7679
7680     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
7681     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7682
7683     hr = IDirect3DDevice9_BeginScene(device);
7684     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
7685     if(SUCCEEDED(hr)) {
7686         /* First, draw to the texture and the back buffer to test both offscreen and onscreen cases */
7687         hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
7688         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
7689         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
7690         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7691         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 4, quad, sizeof(float) * 3);
7692         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7693         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
7694         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
7695         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 4, quad, sizeof(float) * 3);
7696         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7697
7698         /* Blit the texture onto the back buffer to make it visible */
7699         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
7700         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed, hr=%08x\n", hr);
7701         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
7702         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
7703         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
7704         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed, hr=%08x\n", hr);
7705         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
7706         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed, hr=%08x\n", hr);
7707         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7708         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
7709
7710         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, blit, sizeof(float) * 5);
7711         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7712
7713         hr = IDirect3DDevice9_EndScene(device);
7714         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
7715     }
7716
7717     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7718     color = getPixelColor(device, 160, 360);
7719     ok(color == 0x00ff0000, "vFace: Onscreen rendered front facing quad has color 0x%08x, expected 0x00ff0000\n", color);
7720     color = getPixelColor(device, 160, 120);
7721     ok(color == 0x0000ff00, "vFace: Onscreen rendered back facing quad has color 0x%08x, expected 0x0000ff00\n", color);
7722     color = getPixelColor(device, 480, 360);
7723     ok(color == 0x0000ff00, "vFace: Offscreen rendered back facing quad has color 0x%08x, expected 0x0000ff00\n", color);
7724     color = getPixelColor(device, 480, 120);
7725     ok(color == 0x00ff0000, "vFace: Offscreen rendered front facing quad has color 0x%08x, expected 0x00ff0000\n", color);
7726
7727     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
7728     IDirect3DDevice9_SetTexture(device, 0, NULL);
7729     IDirect3DPixelShader9_Release(shader);
7730     IDirect3DSurface9_Release(surface);
7731     IDirect3DSurface9_Release(backbuffer);
7732     IDirect3DTexture9_Release(texture);
7733 }
7734
7735 static void fixed_function_bumpmap_test(IDirect3DDevice9 *device)
7736 {
7737     HRESULT hr;
7738     DWORD color;
7739     int i;
7740     D3DCAPS9 caps;
7741     BOOL L6V5U5_supported = FALSE;
7742     IDirect3DTexture9 *tex1, *tex2;
7743     D3DLOCKED_RECT locked_rect;
7744
7745     static const float quad[][7] = {
7746         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f},
7747         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f},
7748         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 1.0f, 0.0f},
7749         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 1.0f, 1.0f},
7750     };
7751
7752     static const D3DVERTEXELEMENT9 decl_elements[] = {
7753         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7754         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
7755         {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
7756         D3DDECL_END()
7757     };
7758
7759     /* use asymmetric matrix to test loading */
7760     float bumpenvmat[4] = {0.0,0.5,-0.5,0.0};
7761     float scale, offset;
7762
7763     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
7764     IDirect3DTexture9           *texture            = NULL;
7765
7766     memset(&caps, 0, sizeof(caps));
7767     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7768     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%08x\n", hr);
7769     if(!(caps.TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAP)) {
7770         skip("D3DTEXOPCAPS_BUMPENVMAP not set, skipping bumpmap tests\n");
7771         return;
7772     } else {
7773         /* This check is disabled, some Windows drivers do not handle D3DUSAGE_QUERY_LEGACYBUMPMAP properly.
7774          * They report that it is not supported, but after that bump mapping works properly. So just test
7775          * if the format is generally supported, and check the BUMPENVMAP flag
7776          */
7777         IDirect3D9 *d3d9;
7778
7779         IDirect3DDevice9_GetDirect3D(device, &d3d9);
7780         hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
7781                                           D3DRTYPE_TEXTURE, D3DFMT_L6V5U5);
7782         L6V5U5_supported = SUCCEEDED(hr);
7783         hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
7784                                           D3DRTYPE_TEXTURE, D3DFMT_V8U8);
7785         IDirect3D9_Release(d3d9);
7786         if(FAILED(hr)) {
7787             skip("D3DFMT_V8U8 not supported for legacy bump mapping\n");
7788             return;
7789         }
7790     }
7791
7792     /* Generate the textures */
7793     generate_bumpmap_textures(device);
7794
7795     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
7796     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7797     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
7798     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7799     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
7800     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7801     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
7802     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7803
7804     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BUMPENVMAP);
7805     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7806     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
7807     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7808     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_CURRENT );
7809     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7810
7811     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
7812     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7813     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
7814     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7815     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
7816     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7817
7818     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
7819     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7820
7821     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
7822     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
7823
7824     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
7825     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
7826
7827
7828     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
7829     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
7830     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
7831     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
7832
7833     hr = IDirect3DDevice9_BeginScene(device);
7834     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
7835
7836     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
7837     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
7838
7839     hr = IDirect3DDevice9_EndScene(device);
7840     ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
7841
7842     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7843     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
7844
7845     /* on MacOS(10.5.4, radeon X1600), the white dots are have color 0x00fbfbfb rather than 0x00ffffff. This is
7846      * kinda strange since no calculations are done on the sampled colors, only on the texture coordinates.
7847      * But since testing the color match is not the purpose of the test don't be too picky
7848      */
7849     color = getPixelColor(device, 320-32, 240);
7850     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
7851     color = getPixelColor(device, 320+32, 240);
7852     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
7853     color = getPixelColor(device, 320, 240-32);
7854     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
7855     color = getPixelColor(device, 320, 240+32);
7856     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
7857     color = getPixelColor(device, 320, 240);
7858     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
7859     color = getPixelColor(device, 320+32, 240+32);
7860     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
7861     color = getPixelColor(device, 320-32, 240+32);
7862     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
7863     color = getPixelColor(device, 320+32, 240-32);
7864     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
7865     color = getPixelColor(device, 320-32, 240-32);
7866     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
7867
7868     for(i = 0; i < 2; i++) {
7869         hr = IDirect3DDevice9_GetTexture(device, i, (IDirect3DBaseTexture9 **) &texture);
7870         ok(SUCCEEDED(hr), "IDirect3DDevice9_GetTexture failed (0x%08x)\n", hr);
7871         IDirect3DTexture9_Release(texture); /* For the GetTexture */
7872         hr = IDirect3DDevice9_SetTexture(device, i, NULL);
7873         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
7874         IDirect3DTexture9_Release(texture); /* To destroy it */
7875     }
7876
7877     if(!(caps.TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAPLUMINANCE)) {
7878         skip("D3DTOP_BUMPENVMAPLUMINANCE not supported, skipping\n");
7879         goto cleanup;
7880     }
7881     if(L6V5U5_supported == FALSE) {
7882         skip("L6V5U5_supported not supported, skipping D3DTOP_BUMPENVMAPLUMINANCE test\n");
7883         goto cleanup;
7884     }
7885
7886     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0, 0x8);
7887     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
7888     /* This test only tests the luminance part. The bumpmapping part was already tested above and
7889      * would only make this test more complicated
7890      */
7891     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_L6V5U5, D3DPOOL_MANAGED, &tex1, NULL);
7892     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
7893     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &tex2, NULL);
7894     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
7895
7896     memset(&locked_rect, 0, sizeof(locked_rect));
7897     hr = IDirect3DTexture9_LockRect(tex1, 0, &locked_rect, NULL, 0);
7898     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
7899     *((DWORD *)locked_rect.pBits) = 0x4000; /* L = 0.25, V = 0.0, U = 0.0 */
7900     hr = IDirect3DTexture9_UnlockRect(tex1, 0);
7901     ok(SUCCEEDED(hr), "UnlockRect failed with 0x%08x\n", hr);
7902
7903     memset(&locked_rect, 0, sizeof(locked_rect));
7904     hr = IDirect3DTexture9_LockRect(tex2, 0, &locked_rect, NULL, 0);
7905     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
7906     *((DWORD *)locked_rect.pBits) = 0x00ff80c0;
7907     hr = IDirect3DTexture9_UnlockRect(tex2, 0);
7908     ok(SUCCEEDED(hr), "UnlockRect failed with 0x%08x\n", hr);
7909
7910     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex1);
7911     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
7912     hr = IDirect3DDevice9_SetTexture(device, 1, (IDirect3DBaseTexture9 *) tex2);
7913     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
7914
7915     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BUMPENVMAPLUMINANCE);
7916     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7917     scale = 2.0;
7918     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLSCALE, *((DWORD *)&scale));
7919     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7920     offset = 0.1;
7921     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLOFFSET, *((DWORD *)&offset));
7922     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7923
7924     hr = IDirect3DDevice9_BeginScene(device);
7925     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
7926     if(SUCCEEDED(hr)) {
7927         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
7928         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
7929         hr = IDirect3DDevice9_EndScene(device);
7930         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
7931     }
7932
7933     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7934     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
7935     color = getPixelColor(device, 320, 240);
7936     /* red:   1.0  * (0.25 * 2.0 + 0.1) = 1.0  * 0.6 = 0.6  = 0x99
7937      * green: 0.5  * (0.25 * 2.0 + 0.1) = 0.5  * 0.6 = 0.3  = 0x4c
7938      * green: 0.75 * (0.25 * 2.0 + 0.1) = 0.75 * 0.6 = 0.45 = 0x72
7939      */
7940     ok(color_match(color, 0x00994c72, 3), "bumpmap failed: Got color 0x%08x, expected 0x00994c72.\n", color);
7941
7942     /* Check a result scale factor > 1.0 */
7943     scale = 10;
7944     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLSCALE, *((DWORD *)&scale));
7945     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7946     offset = 10;
7947     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLOFFSET, *((DWORD *)&offset));
7948     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7949
7950     hr = IDirect3DDevice9_BeginScene(device);
7951     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
7952     if(SUCCEEDED(hr)) {
7953         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
7954         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
7955         hr = IDirect3DDevice9_EndScene(device);
7956         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
7957     }
7958     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7959     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
7960     color = getPixelColor(device, 320, 240);
7961     ok(color_match(color, 0x00ff80c0, 1), "bumpmap failed: Got color 0x%08x, expected 0x00ff80c0.\n", color);
7962
7963     /* Check clamping in the scale factor calculation */
7964     scale = 1000;
7965     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLSCALE, *((DWORD *)&scale));
7966     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7967     offset = -1;
7968     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLOFFSET, *((DWORD *)&offset));
7969     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7970
7971     hr = IDirect3DDevice9_BeginScene(device);
7972     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
7973     if(SUCCEEDED(hr)) {
7974         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
7975         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
7976         hr = IDirect3DDevice9_EndScene(device);
7977         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
7978     }
7979     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7980     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
7981     color = getPixelColor(device, 320, 240);
7982     ok(color_match(color, 0x00ff80c0, 1), "bumpmap failed: Got color 0x%08x, expected 0x00ff80c0.\n", color);
7983
7984     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7985     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
7986     hr = IDirect3DDevice9_SetTexture(device, 1, NULL);
7987     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
7988
7989     IDirect3DTexture9_Release(tex1);
7990     IDirect3DTexture9_Release(tex2);
7991
7992 cleanup:
7993     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
7994     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7995     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
7996     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7997
7998     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
7999     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
8000     IDirect3DVertexDeclaration9_Release(vertex_declaration);
8001 }
8002
8003 static void stencil_cull_test(IDirect3DDevice9 *device) {
8004     HRESULT hr;
8005     IDirect3DSurface9 *depthstencil = NULL;
8006     D3DSURFACE_DESC desc;
8007     float quad1[] = {
8008         -1.0,   -1.0,   0.1,
8009          0.0,   -1.0,   0.1,
8010         -1.0,    0.0,   0.1,
8011          0.0,    0.0,   0.1,
8012     };
8013     float quad2[] = {
8014          0.0,   -1.0,   0.1,
8015          1.0,   -1.0,   0.1,
8016          0.0,    0.0,   0.1,
8017          1.0,    0.0,   0.1,
8018     };
8019     float quad3[] = {
8020         0.0,    0.0,   0.1,
8021         1.0,    0.0,   0.1,
8022         0.0,    1.0,   0.1,
8023         1.0,    1.0,   0.1,
8024     };
8025     float quad4[] = {
8026         -1.0,    0.0,   0.1,
8027          0.0,    0.0,   0.1,
8028         -1.0,    1.0,   0.1,
8029          0.0,    1.0,   0.1,
8030     };
8031     struct vertex painter[] = {
8032        {-1.0,   -1.0,   0.0,    0x00000000},
8033        { 1.0,   -1.0,   0.0,    0x00000000},
8034        {-1.0,    1.0,   0.0,    0x00000000},
8035        { 1.0,    1.0,   0.0,    0x00000000},
8036     };
8037     WORD indices_cw[]  = {0, 1, 3};
8038     WORD indices_ccw[] = {0, 2, 3};
8039     unsigned int i;
8040     DWORD color;
8041
8042     IDirect3DDevice9_GetDepthStencilSurface(device, &depthstencil);
8043     if(depthstencil == NULL) {
8044         skip("No depth stencil buffer\n");
8045         return;
8046     }
8047     hr = IDirect3DSurface9_GetDesc(depthstencil, &desc);
8048     ok(hr == D3D_OK, "IDirect3DSurface9_GetDesc failed with %08x\n", hr);
8049     IDirect3DSurface9_Release(depthstencil);
8050     if(desc.Format != D3DFMT_D24S8 && desc.Format != D3DFMT_D24X4S4) {
8051         skip("No 4 or 8 bit stencil surface\n");
8052         return;
8053     }
8054
8055     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_STENCIL, 0x00ff0000, 0.0, 0x8);
8056     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
8057     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8058
8059     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILFAIL, D3DSTENCILOP_INCR);
8060     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8061     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR);
8062     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8063     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
8064     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8065     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILREF, 0x3);
8066     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8067
8068     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_REPLACE);
8069     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8070     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_DECR);
8071     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8072     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CCW_STENCILPASS, D3DSTENCILOP_INCR);
8073     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8074
8075     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, TRUE);
8076     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8077     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TWOSIDEDSTENCILMODE, FALSE);
8078     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8079
8080     /* First pass: Fill the stencil buffer with some values... */
8081     hr = IDirect3DDevice9_BeginScene(device);
8082     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
8083     if(SUCCEEDED(hr))
8084     {
8085         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_CW);
8086         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8087         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8088                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad1, sizeof(float) * 3);
8089         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8090                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad1, sizeof(float) * 3);
8091
8092         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TWOSIDEDSTENCILMODE, TRUE);
8093         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8094         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
8095         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8096         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8097                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad2, sizeof(float) * 3);
8098         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8099                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad2, sizeof(float) * 3);
8100
8101         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_CW);
8102         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8103         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8104                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad3, sizeof(float) * 3);
8105         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8106                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad3, sizeof(float) * 3);
8107
8108         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_CCW);
8109         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8110         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8111                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad4, sizeof(float) * 3);
8112         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8113                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad4, sizeof(float) * 3);
8114
8115         hr = IDirect3DDevice9_EndScene(device);
8116         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
8117     }
8118
8119     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8120     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
8121     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8122     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
8123     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8124     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
8125     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8126     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TWOSIDEDSTENCILMODE, FALSE);
8127     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8128     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
8129     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8130     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILFUNC, D3DCMP_EQUAL);
8131     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8132
8133     /* 2nd pass: Make the stencil values visible */
8134     hr = IDirect3DDevice9_BeginScene(device);
8135     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
8136     if(SUCCEEDED(hr))
8137     {
8138         IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
8139         for(i = 0; i < 16; i++) {
8140             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILREF, i);
8141             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8142
8143             painter[0].diffuse = (i * 16); /* Creates shades of blue */
8144             painter[1].diffuse = (i * 16);
8145             painter[2].diffuse = (i * 16);
8146             painter[3].diffuse = (i * 16);
8147             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, painter, sizeof(painter[0]));
8148             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
8149         }
8150         hr = IDirect3DDevice9_EndScene(device);
8151         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
8152     }
8153
8154     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8155     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
8156
8157     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
8158     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8159
8160     color = getPixelColor(device, 160, 420);
8161     ok(color == 0x00000030, "CCW triangle, twoside FALSE, cull cw, replace, has color 0x%08x, expected 0x00000030\n", color);
8162     color = getPixelColor(device, 160, 300);
8163     ok(color == 0x00000080, "CW triangle, twoside FALSE, cull cw, culled, has color 0x%08x, expected 0x00000080\n", color);
8164
8165     color = getPixelColor(device, 480, 420);
8166     ok(color == 0x00000090, "CCW triangle, twoside TRUE, cull off, incr, has color 0x%08x, expected 0x00000090\n", color);
8167     color = getPixelColor(device, 480, 300);
8168     ok(color == 0x00000030, "CW triangle, twoside TRUE, cull off, replace, has color 0x%08x, expected 0x00000030\n", color);
8169
8170     color = getPixelColor(device, 160, 180);
8171     ok(color == 0x00000080, "CCW triangle, twoside TRUE, cull ccw, culled, has color 0x%08x, expected 0x00000080\n", color);
8172     color = getPixelColor(device, 160, 60);
8173     ok(color == 0x00000030, "CW triangle, twoside TRUE, cull ccw, replace, has color 0x%08x, expected 0x00000030\n", color);
8174
8175     color = getPixelColor(device, 480, 180);
8176     ok(color == 0x00000090, "CCW triangle, twoside TRUE, cull cw, incr, has color 0x%08x, expected 0x00000090\n", color);
8177     color = getPixelColor(device, 480, 60);
8178     ok(color == 0x00000080, "CW triangle, twoside TRUE, cull cw, culled, has color 0x%08x, expected 0x00000080\n", color);
8179 }
8180
8181 static void vpos_register_test(IDirect3DDevice9 *device)
8182 {
8183     HRESULT hr;
8184     DWORD color;
8185     const DWORD shader_code[] = {
8186     0xffff0300,                                                             /* ps_3_0                     */
8187     0x0200001f, 0x80000000, 0x90031000,                                     /* dcl vPos.xy                */
8188     0x03000002, 0x80030000, 0x90541000, 0xa1fe0000,                         /* sub r0.xy, vPos.xy, c0.zw  */
8189     0x02000001, 0x800f0001, 0xa0e40000,                                     /* mov r1, c0                 */
8190     0x02000001, 0x80080002, 0xa0550000,                                     /* mov r2.a, c0.y             */
8191     0x02000001, 0x80010002, 0xa0550000,                                     /* mov r2.r, c0.y             */
8192     0x04000058, 0x80020002, 0x80000000, 0x80000001, 0x80550001,             /* cmp r2.g, r0.x, r1.x, r1.y */
8193     0x04000058, 0x80040002, 0x80550000, 0x80000001, 0x80550001,             /* cmp r2.b, r0.y, r1.x, r1.y */
8194     0x02000001, 0x800f0800, 0x80e40002,                                     /* mov oC0, r2                */
8195     0x0000ffff                                                              /* end                        */
8196     };
8197     const DWORD shader_frac_code[] = {
8198     0xffff0300,                                                             /* ps_3_0                     */
8199     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0 */
8200     0x0200001f, 0x80000000, 0x90031000,                                     /* dcl vPos.xy                */
8201     0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                 */
8202     0x02000013, 0x80030000, 0x90541000,                                     /* frc r0.xy, vPos.xy         */
8203     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                */
8204     0x0000ffff                                                              /* end                        */
8205     };
8206     IDirect3DPixelShader9 *shader, *shader_frac;
8207     IDirect3DSurface9 *surface = NULL, *backbuffer;
8208     const float quad[] = {
8209         -1.0,   -1.0,   0.1,    0.0,    0.0,
8210          1.0,   -1.0,   0.1,    1.0,    0.0,
8211         -1.0,    1.0,   0.1,    0.0,    1.0,
8212          1.0,    1.0,   0.1,    1.0,    1.0,
8213     };
8214     D3DLOCKED_RECT lr;
8215     float constant[4] = {1.0, 0.0, 320, 240};
8216     DWORD *pos;
8217
8218     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
8219     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8220     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
8221     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed hr=%08x\n", hr);
8222     hr = IDirect3DDevice9_CreatePixelShader(device, shader_frac_code, &shader_frac);
8223     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed hr=%08x\n", hr);
8224     hr = IDirect3DDevice9_SetPixelShader(device, shader);
8225     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
8226     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8227     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
8228     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
8229     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed hr=%08x\n", hr);
8230
8231     hr = IDirect3DDevice9_BeginScene(device);
8232     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8233     if(SUCCEEDED(hr)) {
8234         hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, constant, 1);
8235         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF failed hr=%08x\n", hr);
8236         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
8237         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8238         hr = IDirect3DDevice9_EndScene(device);
8239         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8240     }
8241
8242     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8243     /* This has to be pixel exact */
8244     color = getPixelColor(device, 319, 239);
8245     ok(color == 0x00000000, "vPos: Pixel 319,239 has color 0x%08x, expected 0x00000000\n", color);
8246     color = getPixelColor(device, 320, 239);
8247     ok(color == 0x0000ff00, "vPos: Pixel 320,239 has color 0x%08x, expected 0x0000ff00\n", color);
8248     color = getPixelColor(device, 319, 240);
8249     ok(color == 0x000000ff, "vPos: Pixel 319,240 has color 0x%08x, expected 0x000000ff\n", color);
8250     color = getPixelColor(device, 320, 240);
8251     ok(color == 0x0000ffff, "vPos: Pixel 320,240 has color 0x%08x, expected 0x0000ffff\n", color);
8252
8253     hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, D3DFMT_X8R8G8B8, 0, 0, TRUE,
8254                                              &surface, NULL);
8255     ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed hr=%08x\n", hr);
8256     hr = IDirect3DDevice9_BeginScene(device);
8257     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8258     if(SUCCEEDED(hr)) {
8259         constant[2] = 16; constant[3] = 16;
8260         hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, constant, 1);
8261         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF failed hr=%08x\n", hr);
8262         hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
8263         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8264         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
8265         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8266         hr = IDirect3DDevice9_EndScene(device);
8267         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8268     }
8269     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, D3DLOCK_READONLY);
8270     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr=%08x\n", hr);
8271
8272     pos = (DWORD *) (((BYTE *) lr.pBits) + 14 * lr.Pitch + 14 * sizeof(DWORD));
8273     color = *pos & 0x00ffffff;
8274     ok(color == 0x00000000, "Pixel 14/14 has color 0x%08x, expected 0x00000000\n", color);
8275     pos = (DWORD *) (((BYTE *) lr.pBits) + 14 * lr.Pitch + 18 * sizeof(DWORD));
8276     color = *pos & 0x00ffffff;
8277     ok(color == 0x0000ff00, "Pixel 14/18 has color 0x%08x, expected 0x0000ff00\n", color);
8278     pos = (DWORD *) (((BYTE *) lr.pBits) + 18 * lr.Pitch + 14 * sizeof(DWORD));
8279     color = *pos & 0x00ffffff;
8280     ok(color == 0x000000ff, "Pixel 18/14 has color 0x%08x, expected 0x000000ff\n", color);
8281     pos = (DWORD *) (((BYTE *) lr.pBits) + 18 * lr.Pitch + 18 * sizeof(DWORD));
8282     color = *pos & 0x00ffffff;
8283     ok(color == 0x0000ffff, "Pixel 18/18 has color 0x%08x, expected 0x0000ffff\n", color);
8284
8285     hr = IDirect3DSurface9_UnlockRect(surface);
8286     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr=%08x\n", hr);
8287
8288     /* Test the fraction value of vPos. This is tested with the offscreen target and not the backbuffer to
8289      * have full control over the multisampling setting inside this test
8290      */
8291     hr = IDirect3DDevice9_SetPixelShader(device, shader_frac);
8292     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
8293     hr = IDirect3DDevice9_BeginScene(device);
8294     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8295     if(SUCCEEDED(hr)) {
8296         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
8297         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8298         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
8299         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8300         hr = IDirect3DDevice9_EndScene(device);
8301         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8302     }
8303     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
8304     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8305
8306     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, D3DLOCK_READONLY);
8307     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr=%08x\n", hr);
8308
8309     pos = (DWORD *) (((BYTE *) lr.pBits) + 14 * lr.Pitch + 14 * sizeof(DWORD));
8310     color = *pos & 0x00ffffff;
8311     ok(color == 0x00000000, "vPos fraction test has color 0x%08x, expected 0x00000000\n", color);
8312
8313     hr = IDirect3DSurface9_UnlockRect(surface);
8314     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr=%08x\n", hr);
8315
8316     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
8317     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
8318     IDirect3DPixelShader9_Release(shader);
8319     IDirect3DPixelShader9_Release(shader_frac);
8320     if(surface) IDirect3DSurface9_Release(surface);
8321     IDirect3DSurface9_Release(backbuffer);
8322 }
8323
8324 static void pointsize_test(IDirect3DDevice9 *device)
8325 {
8326     HRESULT hr;
8327     D3DCAPS9 caps;
8328     D3DMATRIX matrix;
8329     D3DMATRIX identity;
8330     float ptsize, ptsize_orig, ptsizemax_orig, ptsizemin_orig;
8331     DWORD color;
8332
8333     const float vertices[] = {
8334         64,     64,     0.1,
8335         128,    64,     0.1,
8336         192,    64,     0.1,
8337         256,    64,     0.1,
8338         320,    64,     0.1,
8339         384,    64,     0.1,
8340         448,    64,     0.1,
8341         512,    64,     0.1,
8342         576,    64,     0.1,
8343     };
8344
8345     /* 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 */
8346     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;
8347     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;
8348     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;
8349     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;
8350
8351     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;
8352     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;
8353     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;
8354     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;
8355
8356     memset(&caps, 0, sizeof(caps));
8357     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8358     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%08x\n", hr);
8359     if(caps.MaxPointSize < 32.0) {
8360         skip("MaxPointSize < 32.0, skipping(MaxPointsize = %f)\n", caps.MaxPointSize);
8361         return;
8362     }
8363
8364     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 0.0, 0);
8365     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8366     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, &matrix);
8367     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed, hr=%08x\n", hr);
8368     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8369     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
8370     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSIZE, (DWORD *) &ptsize_orig);
8371     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed hr=%08x\n", hr);
8372
8373     hr = IDirect3DDevice9_BeginScene(device);
8374     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8375     if(SUCCEEDED(hr)) {
8376         ptsize = 16.0;
8377         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8378         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8379         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[0], sizeof(float) * 3);
8380         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8381
8382         ptsize = 32.0;
8383         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8384         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8385         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[3], sizeof(float) * 3);
8386         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8387
8388         ptsize = 31.5;
8389         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8390         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8391         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[6], sizeof(float) * 3);
8392         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8393
8394         if(caps.MaxPointSize >= 64.0) {
8395             ptsize = 64.0;
8396             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8397             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8398             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[9], sizeof(float) * 3);
8399             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8400
8401             ptsize = 63.75;
8402             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8403             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8404             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[15], sizeof(float) * 3);
8405             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8406         }
8407
8408         ptsize = 1.0;
8409         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8410         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8411         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[12], sizeof(float) * 3);
8412         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8413
8414         hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSIZE_MAX, (DWORD *) (&ptsizemax_orig));
8415         ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed, hr=%08x\n", hr);
8416         hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSIZE_MAX, (DWORD *) (&ptsizemin_orig));
8417         ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed, hr=%08x\n", hr);
8418
8419         /* What happens if point scaling is disabled, and POINTSIZE_MAX < POINTSIZE? */
8420         ptsize = 16.0;
8421         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8422         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8423         ptsize = 1.0;
8424         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MAX, *((DWORD *) (&ptsize)));
8425         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8426         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[18], sizeof(float) * 3);
8427         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8428
8429         /* What happens if POINTSIZE_MAX < POINTSIZE_MIN?
8430          * ptsize = 4.0, ptsize_max = 1.0, ptsize_min = 16.0
8431          */
8432         ptsize = 4.0;
8433         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8434         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8435         ptsize = 16.0;
8436         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MIN, *((DWORD *) (&ptsize)));
8437         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8438         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[21], sizeof(float) * 3);
8439         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8440
8441         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MAX, *((DWORD *) (&ptsizemax_orig)));
8442         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8443
8444         /* pointsize < pointsize_min < pointsize_max?
8445          * pointsize = 1.0, pointsize_min = 16.0, pointsize_max = default(usually 64.0)
8446          */
8447         ptsize = 1.0;
8448         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8449         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8450         ptsize = 16.0;
8451         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MIN, *((DWORD *) (&ptsize)));
8452         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8453         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[24], sizeof(float) * 3);
8454         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8455
8456         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MIN, *((DWORD *) (&ptsizemin_orig)));
8457         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8458
8459         hr = IDirect3DDevice9_EndScene(device);
8460         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8461     }
8462     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8463     color = getPixelColor(device, 64-9, 64-9);
8464     ok(color == 0x000000ff, "pSize: Pixel (64-9),(64-9) has color 0x%08x, expected 0x000000ff\n", color);
8465     color = getPixelColor(device, 64-8, 64-8);
8466     todo_wine ok(color == 0x00ffffff, "pSize: Pixel (64-8),(64-8) has color 0x%08x, expected 0x00ffffff\n", color);
8467     color = getPixelColor(device, 64-7, 64-7);
8468     ok(color == 0x00ffffff, "pSize: Pixel (64-7),(64-7) has color 0x%08x, expected 0x00ffffff\n", color);
8469     color = getPixelColor(device, 64+7, 64+7);
8470     ok(color == 0x00ffffff, "pSize: Pixel (64+7),(64+7) has color 0x%08x, expected 0x00ffffff\n", color);
8471     color = getPixelColor(device, 64+8, 64+8);
8472     ok(color == 0x000000ff, "pSize: Pixel (64+8),(64+8) has color 0x%08x, expected 0x000000ff\n", color);
8473     color = getPixelColor(device, 64+9, 64+9);
8474     ok(color == 0x000000ff, "pSize: Pixel (64+9),(64+9) has color 0x%08x, expected 0x000000ff\n", color);
8475
8476     color = getPixelColor(device, 128-17, 64-17);
8477     ok(color == 0x000000ff, "pSize: Pixel (128-17),(64-17) has color 0x%08x, expected 0x000000ff\n", color);
8478     color = getPixelColor(device, 128-16, 64-16);
8479     todo_wine ok(color == 0x00ffffff, "pSize: Pixel (128-16),(64-16) has color 0x%08x, expected 0x00ffffff\n", color);
8480     color = getPixelColor(device, 128-15, 64-15);
8481     ok(color == 0x00ffffff, "pSize: Pixel (128-15),(64-15) has color 0x%08x, expected 0x00ffffff\n", color);
8482     color = getPixelColor(device, 128+15, 64+15);
8483     ok(color == 0x00ffffff, "pSize: Pixel (128+15),(64+15) has color 0x%08x, expected 0x00ffffff\n", color);
8484     color = getPixelColor(device, 128+16, 64+16);
8485     ok(color == 0x000000ff, "pSize: Pixel (128+16),(64+16) has color 0x%08x, expected 0x000000ff\n", color);
8486     color = getPixelColor(device, 128+17, 64+17);
8487     ok(color == 0x000000ff, "pSize: Pixel (128+17),(64+17) has color 0x%08x, expected 0x000000ff\n", color);
8488
8489     color = getPixelColor(device, 192-17, 64-17);
8490     ok(color == 0x000000ff, "pSize: Pixel (192-17),(64-17) has color 0x%08x, expected 0x000000ff\n", color);
8491     color = getPixelColor(device, 192-16, 64-16);
8492     ok(color == 0x000000ff, "pSize: Pixel (192-16),(64-16) has color 0x%08x, expected 0x000000ff\n", color);
8493     color = getPixelColor(device, 192-15, 64-15);
8494     ok(color == 0x00ffffff, "pSize: Pixel (192-15),(64-15) has color 0x%08x, expected 0x00ffffff\n", color);
8495     color = getPixelColor(device, 192+15, 64+15);
8496     ok(color == 0x00ffffff, "pSize: Pixel (192+15),(64+15) has color 0x%08x, expected 0x00ffffff\n", color);
8497     color = getPixelColor(device, 192+16, 64+16);
8498     ok(color == 0x000000ff, "pSize: Pixel (192+16),(64+16) has color 0x%08x, expected 0x000000ff\n", color);
8499     color = getPixelColor(device, 192+17, 64+17);
8500     ok(color == 0x000000ff, "pSize: Pixel (192+17),(64+17) has color 0x%08x, expected 0x000000ff\n", color);
8501
8502     if(caps.MaxPointSize >= 64.0) {
8503         color = getPixelColor(device, 256-33, 64-33);
8504         ok(color == 0x000000ff, "pSize: Pixel (256-33),(64-33) has color 0x%08x, expected 0x000000ff\n", color);
8505         color = getPixelColor(device, 256-32, 64-32);
8506         todo_wine ok(color == 0x00ffffff, "pSize: Pixel (256-32),(64-32) has color 0x%08x, expected 0x00ffffff\n", color);
8507         color = getPixelColor(device, 256-31, 64-31);
8508         ok(color == 0x00ffffff, "pSize: Pixel (256-31),(64-31) has color 0x%08x, expected 0x00ffffff\n", color);
8509         color = getPixelColor(device, 256+31, 64+31);
8510         ok(color == 0x00ffffff, "pSize: Pixel (256+31),(64+31) has color 0x%08x, expected 0x00ffffff\n", color);
8511         color = getPixelColor(device, 256+32, 64+32);
8512         ok(color == 0x000000ff, "pSize: Pixel (256+32),(64+32) has color 0x%08x, expected 0x000000ff\n", color);
8513         color = getPixelColor(device, 256+33, 64+33);
8514         ok(color == 0x000000ff, "pSize: Pixel (256+33),(64+33) has color 0x%08x, expected 0x000000ff\n", color);
8515
8516         color = getPixelColor(device, 384-33, 64-33);
8517         ok(color == 0x000000ff, "pSize: Pixel (384-33),(64-33) has color 0x%08x, expected 0x000000ff\n", color);
8518         color = getPixelColor(device, 384-32, 64-32);
8519         ok(color == 0x000000ff, "pSize: Pixel (384-32),(64-32) has color 0x%08x, expected 0x000000ff\n", color);
8520         color = getPixelColor(device, 384-31, 64-31);
8521         ok(color == 0x00ffffff, "pSize: Pixel (384-31),(64-31) has color 0x%08x, expected 0x00ffffff\n", color);
8522         color = getPixelColor(device, 384+31, 64+31);
8523         ok(color == 0x00ffffff, "pSize: Pixel (384+31),(64+31) has color 0x%08x, expected 0x00ffffff\n", color);
8524         color = getPixelColor(device, 384+32, 64+32);
8525         ok(color == 0x000000ff, "pSize: Pixel (384+32),(64+32) has color 0x%08x, expected 0x000000ff\n", color);
8526         color = getPixelColor(device, 384+33, 64+33);
8527         ok(color == 0x000000ff, "pSize: Pixel (384+33),(64+33) has color 0x%08x, expected 0x000000ff\n", color);
8528     }
8529
8530     color = getPixelColor(device, 320-1, 64-1);
8531     ok(color == 0x000000ff, "pSize: Pixel (320-1),(64-1) has color 0x%08x, expected 0x000000ff\n", color);
8532     color = getPixelColor(device, 320-0, 64-0);
8533     ok(color == 0x00ffffff, "pSize: Pixel (320-0),(64-0) has color 0x%08x, expected 0x00ffffff\n", color);
8534     color = getPixelColor(device, 320+1, 64+1);
8535     ok(color == 0x000000ff, "pSize: Pixel (320+1),(64+1) has color 0x%08x, expected 0x000000ff\n", color);
8536
8537     /* ptsize = 16, ptsize_max = 1 --> point has size 1 */
8538     color = getPixelColor(device, 448-4, 64-4);
8539     ok(color == 0x000000ff, "pSize: Pixel (448-4),(64-4) has color 0x%08x, expected 0x00ffffff\n", color);
8540     color = getPixelColor(device, 448+4, 64+4);
8541     ok(color == 0x000000ff, "pSize: Pixel (448+4),(64+4) has color 0x%08x, expected 0x00ffffff\n", color);
8542
8543     /* ptsize = 4, ptsize_max = 1, ptsize_min = 16 --> point has size 1 */
8544     color = getPixelColor(device, 512-4, 64-4);
8545     ok(color == 0x000000ff, "pSize: Pixel (448-4),(64-4) has color 0x%08x, expected 0x00ffffff\n", color);
8546     color = getPixelColor(device, 512+4, 64+4);
8547     ok(color == 0x000000ff, "pSize: Pixel (448+4),(64+4) has color 0x%08x, expected 0x00ffffff\n", color);
8548
8549     /* ptsize = 1, ptsize_max = default(64), ptsize_min = 16 --> point has size 16
8550      * Don't be overly picky - just show that the point is bigger than 1 pixel
8551      */
8552     color = getPixelColor(device, 576-4, 64-4);
8553     ok(color == 0x00ffffff, "pSize: Pixel (448-4),(64-4) has color 0x%08x, expected 0x00ffffff\n", color);
8554     color = getPixelColor(device, 576+4, 64+4);
8555     ok(color == 0x00ffffff, "pSize: Pixel (448+4),(64+4) has color 0x%08x, expected 0x00ffffff\n", color);
8556
8557     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize_orig)));
8558     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed hr=%08x\n", hr);
8559     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, &identity);
8560     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed, hr=%08x\n", hr);
8561 }
8562
8563 static void multiple_rendertargets_test(IDirect3DDevice9 *device)
8564 {
8565     HRESULT hr;
8566     IDirect3DPixelShader9 *ps;
8567     IDirect3DTexture9 *tex1, *tex2;
8568     IDirect3DSurface9 *surf1, *surf2, *backbuf;
8569     D3DCAPS9 caps;
8570     DWORD color;
8571     DWORD shader_code[] = {
8572     0xffff0300,                                                             /* ps_3_0             */
8573     0x05000051, 0xa00f0000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c0, 0, 1, 0, 0 */
8574     0x05000051, 0xa00f0001, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, /* def c1, 0, 0, 1, 0 */
8575     0x02000001, 0x800f0800, 0xa0e40000,                                     /* mov oC0, c0        */
8576     0x02000001, 0x800f0801, 0xa0e40001,                                     /* mov oC1, c1        */
8577     0x0000ffff                                                              /* END                */
8578     };
8579     float quad[] = {
8580        -1.0,   -1.0,    0.1,
8581         1.0,   -1.0,    0.1,
8582        -1.0,    1.0,    0.1,
8583         1.0,    1.0,    0.1,
8584     };
8585     float texquad[] = {
8586        -1.0,   -1.0,    0.1,    0.0,    0.0,
8587         0.0,   -1.0,    0.1,    1.0,    0.0,
8588        -1.0,    1.0,    0.1,    0.0,    1.0,
8589         0.0,    1.0,    0.1,    1.0,    1.0,
8590
8591         0.0,   -1.0,    0.1,    0.0,    0.0,
8592         1.0,   -1.0,    0.1,    1.0,    0.0,
8593         0.0,    1.0,    0.1,    0.0,    1.0,
8594         1.0,    1.0,    0.1,    1.0,    1.0,
8595     };
8596
8597     memset(&caps, 0, sizeof(caps));
8598     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8599     ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed, hr=%08x\n", hr);
8600     if(caps.NumSimultaneousRTs < 2) {
8601         skip("Only 1 simultaneous render target supported, skipping MRT test\n");
8602         return;
8603     }
8604
8605     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0, 0);
8606     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8607
8608     hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &tex1, NULL);
8609     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
8610     hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &tex2, NULL);
8611     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
8612     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &ps);
8613     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed, hr=%08x\n", hr);
8614
8615     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuf);
8616     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderTarget failed, hr=%08x\n", hr);
8617     hr = IDirect3DTexture9_GetSurfaceLevel(tex1, 0, &surf1);
8618     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed, hr=%08x\n", hr);
8619     hr = IDirect3DTexture9_GetSurfaceLevel(tex2, 0, &surf2);
8620     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed, hr=%08x\n", hr);
8621
8622     hr = IDirect3DDevice9_SetPixelShader(device, ps);
8623     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed, hr=%08x\n", hr);
8624     hr = IDirect3DDevice9_SetRenderTarget(device, 0, surf1);
8625     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8626     hr = IDirect3DDevice9_SetRenderTarget(device, 1, surf2);
8627     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8628     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8629     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr=%08x\n", hr);
8630
8631     hr = IDirect3DDevice9_BeginScene(device);
8632     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed, hr=%08x\n", hr);
8633     if(SUCCEEDED(hr)) {
8634         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
8635         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8636
8637         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
8638         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed, hr=%08x\n", hr);
8639         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuf);
8640         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8641         hr = IDirect3DDevice9_SetRenderTarget(device, 1, NULL);
8642         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8643         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
8644         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr=%08x\n", hr);
8645
8646         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex1);
8647         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
8648         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &texquad[0], 5 * sizeof(float));
8649         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8650
8651         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex2);
8652         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
8653         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &texquad[20], 5 * sizeof(float));
8654         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8655
8656         hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
8657         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
8658
8659         hr = IDirect3DDevice9_EndScene(device);
8660         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%08x\n", hr);
8661     }
8662
8663     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8664     color = getPixelColor(device, 160, 240);
8665     ok(color == 0x0000ff00, "Texture 1(output color 1) has color 0x%08x, expected 0x0000ff00\n", color);
8666     color = getPixelColor(device, 480, 240);
8667     ok(color == 0x000000ff, "Texture 2(output color 2) has color 0x%08x, expected 0x000000ff\n", color);
8668
8669     IDirect3DPixelShader9_Release(ps);
8670     IDirect3DTexture9_Release(tex1);
8671     IDirect3DTexture9_Release(tex2);
8672     IDirect3DSurface9_Release(surf1);
8673     IDirect3DSurface9_Release(surf2);
8674     IDirect3DSurface9_Release(backbuf);
8675 }
8676
8677 struct formats {
8678     const char *fmtName;
8679     D3DFORMAT textureFormat;
8680     DWORD resultColorBlending;
8681     DWORD resultColorNoBlending;
8682 };
8683
8684 const struct formats test_formats[] = {
8685   { "D3DFMT_G16R16", D3DFMT_G16R16, 0x001818ff, 0x002010ff},
8686   { "D3DFMT_R16F", D3DFMT_R16F, 0x0018ffff, 0x0020ffff },
8687   { "D3DFMT_G16R16F", D3DFMT_G16R16F, 0x001818ff, 0x002010ff },
8688   { "D3DFMT_A16B16G16R16F", D3DFMT_A16B16G16R16F, 0x00181800, 0x00201000 },
8689   { "D3DFMT_R32F", D3DFMT_R32F, 0x0018ffff, 0x0020ffff },
8690   { "D3DFMT_G32R32F", D3DFMT_G32R32F, 0x001818ff, 0x002010ff },
8691   { "D3DFMT_A32B32G32R32F", D3DFMT_A32B32G32R32F, 0x00181800, 0x00201000 },
8692   { NULL, 0 }
8693 };
8694
8695 static void pixelshader_blending_test(IDirect3DDevice9 *device)
8696 {
8697     HRESULT hr;
8698     IDirect3DTexture9 *offscreenTexture = NULL;
8699     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
8700     IDirect3D9 *d3d = NULL;
8701     DWORD color;
8702     DWORD r0, g0, b0, r1, g1, b1;
8703     int fmt_index;
8704
8705     static const float quad[][5] = {
8706         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
8707         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
8708         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
8709         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
8710     };
8711
8712     /* Quad with R=0x10, G=0x20 */
8713     static const struct vertex quad1[] = {
8714         {-1.0f, -1.0f, 0.1f, 0x80102000},
8715         {-1.0f,  1.0f, 0.1f, 0x80102000},
8716         { 1.0f, -1.0f, 0.1f, 0x80102000},
8717         { 1.0f,  1.0f, 0.1f, 0x80102000},
8718     };
8719
8720     /* Quad with R=0x20, G=0x10 */
8721     static const struct vertex quad2[] = {
8722         {-1.0f, -1.0f, 0.1f, 0x80201000},
8723         {-1.0f,  1.0f, 0.1f, 0x80201000},
8724         { 1.0f, -1.0f, 0.1f, 0x80201000},
8725         { 1.0f,  1.0f, 0.1f, 0x80201000},
8726     };
8727
8728     IDirect3DDevice9_GetDirect3D(device, &d3d);
8729
8730     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
8731     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
8732     if(!backbuffer) {
8733         goto out;
8734     }
8735
8736     for(fmt_index=0; test_formats[fmt_index].textureFormat != 0; fmt_index++)
8737     {
8738         D3DFORMAT fmt = test_formats[fmt_index].textureFormat;
8739         if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, fmt) != D3D_OK) {
8740            skip("%s textures not supported\n", test_formats[fmt_index].fmtName);
8741            continue;
8742         }
8743
8744         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
8745         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
8746
8747         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, fmt, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
8748         ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %08x\n", hr);
8749         if(!offscreenTexture) {
8750             continue;
8751         }
8752
8753         hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
8754         ok(hr == D3D_OK, "Can't get offscreen surface, hr = %08x\n", hr);
8755         if(!offscreen) {
8756             continue;
8757         }
8758
8759         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
8760         ok(hr == D3D_OK, "SetFVF failed, hr = %08x\n", hr);
8761
8762         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
8763         ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8764         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
8765         ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8766         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
8767         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
8768         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
8769         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
8770         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
8771         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8772
8773         /* Below we will draw two quads with different colors and try to blend them together.
8774          * The result color is compared with the expected outcome.
8775          */
8776         if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
8777             hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
8778             ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
8779             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 0.0, 0);
8780             ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
8781
8782             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
8783             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8784
8785             /* Draw a quad using color 0x0010200 */
8786             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_ONE);
8787             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8788             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_ZERO);
8789             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8790             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
8791             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
8792
8793             /* Draw a quad using color 0x0020100 */
8794             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
8795             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8796             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
8797             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8798             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
8799             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
8800
8801             /* We don't want to blend the result on the backbuffer */
8802             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
8803             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8804
8805             /* Prepare rendering the 'blended' texture quad to the backbuffer */
8806             hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
8807             ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
8808             hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
8809             ok(hr == D3D_OK, "SetTexture failed, %08x\n", hr);
8810
8811             hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
8812             ok(hr == D3D_OK, "SetFVF failed, hr = %08x\n", hr);
8813
8814             /* This time with the texture */
8815             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
8816             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %08x\n", hr);
8817
8818             IDirect3DDevice9_EndScene(device);
8819         }
8820         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8821
8822
8823         if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, fmt) == D3D_OK) {
8824             /* Compare the color of the center quad with our expectation */
8825             color = getPixelColor(device, 320, 240);
8826             r0 = (color & 0x00ff0000) >> 16;
8827             g0 = (color & 0x0000ff00) >>  8;
8828             b0 = (color & 0x000000ff) >>  0;
8829
8830             r1 = (test_formats[fmt_index].resultColorBlending & 0x00ff0000) >> 16;
8831             g1 = (test_formats[fmt_index].resultColorBlending & 0x0000ff00) >>  8;
8832             b1 = (test_formats[fmt_index].resultColorBlending & 0x000000ff) >>  0;
8833
8834             ok(r0 >= max(r1, 1) - 1 && r0 <= r1 + 1 &&
8835                g0 >= max(g1, 1) - 1 && g0 <= g1 + 1 &&
8836                b0 >= max(b1, 1) - 1 && b0 <= b1 + 1,
8837                "Offscreen failed for %s: Got color %#08x, expected %#08x.\n", test_formats[fmt_index].fmtName, color, test_formats[fmt_index].resultColorBlending);
8838         } else {
8839             /* No pixel shader blending is supported so expected garbage.The type of 'garbage' depends on the driver version and OS.
8840              * E.g. on G16R16 ati reports (on old r9600 drivers) 0x00ffffff and on modern ones 0x002010ff which is also what Nvidia
8841              * reports. On Vista Nvidia seems to report 0x00ffffff on Geforce7 cards. */
8842             color = getPixelColor(device, 320, 240);
8843             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);
8844         }
8845
8846         IDirect3DDevice9_SetTexture(device, 0, NULL);
8847         if(offscreenTexture) {
8848             IDirect3DTexture9_Release(offscreenTexture);
8849         }
8850         if(offscreen) {
8851             IDirect3DSurface9_Release(offscreen);
8852         }
8853     }
8854
8855 out:
8856     /* restore things */
8857     if(backbuffer) {
8858         IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
8859         IDirect3DSurface9_Release(backbuffer);
8860     }
8861 }
8862
8863 static void tssargtemp_test(IDirect3DDevice9 *device)
8864 {
8865     HRESULT hr;
8866     DWORD color;
8867     static const struct vertex quad[] = {
8868         {-1.0,     -1.0,    0.1,    0x00ff0000},
8869         { 1.0,     -1.0,    0.1,    0x00ff0000},
8870         {-1.0,      1.0,    0.1,    0x00ff0000},
8871         { 1.0,      1.0,    0.1,    0x00ff0000}
8872     };
8873     D3DCAPS9 caps;
8874
8875     memset(&caps, 0, sizeof(caps));
8876     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8877     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
8878     if(!(caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP)) {
8879         skip("D3DPMISCCAPS_TSSARGTEMP not supported\n");
8880         return;
8881     }
8882
8883     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
8884     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
8885
8886     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
8887     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8888     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
8889     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8890
8891     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
8892     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8893     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
8894     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8895     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_RESULTARG, D3DTA_TEMP);
8896     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8897
8898     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_ADD);
8899     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8900     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLORARG1, D3DTA_CURRENT);
8901     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8902     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLORARG2, D3DTA_TEMP);
8903     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8904
8905     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_COLOROP, D3DTOP_DISABLE);
8906     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8907
8908     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0x0000ff00);
8909     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8910     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
8911     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %08x\n", hr);
8912
8913     hr = IDirect3DDevice9_BeginScene(device);
8914     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed, hr = %08x\n", hr);
8915     if(SUCCEEDED(hr)) {
8916
8917         hr = IDirect3DDevice9_EndScene(device);
8918         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr = %08x\n", hr);
8919         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
8920         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed with %08x\n", hr);
8921     }
8922     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8923     color = getPixelColor(device, 320, 240);
8924     ok(color == 0x00FFFF00, "TSSARGTEMP test returned color 0x%08x, expected 0x00FFFF00\n", color);
8925
8926     /* Set stage 1 back to default */
8927     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_RESULTARG, D3DTA_CURRENT);
8928     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8929     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
8930     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8931     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
8932     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8933     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
8934     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8935     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_COLOROP, D3DTOP_DISABLE);
8936     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8937 }
8938
8939 struct testdata
8940 {
8941     DWORD idxVertex; /* number of instances in the first stream */
8942     DWORD idxColor; /* number of instances in the second stream */
8943     DWORD idxInstance; /* should be 1 ?? */
8944     DWORD color1; /* color 1 instance */
8945     DWORD color2; /* color 2 instance */
8946     DWORD color3; /* color 3 instance */
8947     DWORD color4; /* color 4 instance */
8948     WORD strVertex; /* specify which stream to use 0-2*/
8949     WORD strColor;
8950     WORD strInstance;
8951 };
8952
8953 static const struct testdata testcases[]=
8954 {
8955     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  0 */
8956     {3, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0, 1, 2}, /*  1 */
8957     {2, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0, 1, 2}, /*  2 */
8958     {1, 4, 1, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0, 1, 2}, /*  3 */
8959     {0, 4, 1, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0, 1, 2}, /*  4 */
8960     {4, 3, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  5 */
8961     {4, 2, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  6 */
8962     {4, 1, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  7 */
8963     {4, 0, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  8 */
8964     {3, 3, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0, 1, 2}, /*  9 */
8965     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 1, 0, 2}, /* 10 */
8966     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 2, 1}, /* 11 */
8967     {4, 4, 1, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 2, 3, 1}, /* 12 */
8968     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 2, 0, 1}, /* 13 */
8969     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 1, 2, 3}, /* 14 */
8970 /*
8971     This case is handled in a stand alone test, SetStreamSourceFreq(0,(D3DSTREAMSOURCE_INSTANCEDATA | 1))  has to return D3DERR_INVALIDCALL!
8972     {4, 4, 1, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 2, 1, 0, D3DERR_INVALIDCALL},
8973 */
8974 };
8975
8976 /* Drawing Indexed Geometry with instances*/
8977 static void stream_test(IDirect3DDevice9 *device)
8978 {
8979     IDirect3DVertexBuffer9 *vb = NULL;
8980     IDirect3DVertexBuffer9 *vb2 = NULL;
8981     IDirect3DVertexBuffer9 *vb3 = NULL;
8982     IDirect3DIndexBuffer9 *ib = NULL;
8983     IDirect3DVertexDeclaration9 *pDecl = NULL;
8984     IDirect3DVertexShader9 *shader = NULL;
8985     HRESULT hr;
8986     BYTE *data;
8987     DWORD color;
8988     DWORD ind;
8989     unsigned i;
8990
8991     const DWORD shader_code[] =
8992     {
8993         0xfffe0101,                                     /* vs_1_1 */
8994         0x0000001f, 0x80000000, 0x900f0000,             /* dcl_position v0 */
8995         0x0000001f, 0x8000000a, 0x900f0001,             /* dcl_color0 v1 */
8996         0x0000001f, 0x80000005, 0x900f0002,             /* dcl_texcoord v2 */
8997         0x00000001, 0x800f0000, 0x90e40000,             /* mov r0, v0 */
8998         0x00000002, 0xc00f0000, 0x80e40000, 0x90e40002, /* add oPos, r0, v2 */
8999         0x00000001, 0xd00f0000, 0x90e40001,             /* mov oD0, v1 */
9000         0x0000ffff
9001     };
9002
9003     const float quad[][3] =
9004     {
9005         {-0.5f, -0.5f,  1.1f}, /*0 */
9006         {-0.5f,  0.5f,  1.1f}, /*1 */
9007         { 0.5f, -0.5f,  1.1f}, /*2 */
9008         { 0.5f,  0.5f,  1.1f}, /*3 */
9009     };
9010
9011     const float vertcolor[][4] =
9012     {
9013         {1.0f, 0.0f, 0.0f, 1.0f}, /*0 */
9014         {1.0f, 0.0f, 0.0f, 1.0f}, /*1 */
9015         {1.0f, 0.0f, 0.0f, 1.0f}, /*2 */
9016         {1.0f, 0.0f, 0.0f, 1.0f}, /*3 */
9017     };
9018
9019     /* 4 position for 4 instances */
9020     const float instancepos[][3] =
9021     {
9022         {-0.6f,-0.6f, 0.0f},
9023         { 0.6f,-0.6f, 0.0f},
9024         { 0.6f, 0.6f, 0.0f},
9025         {-0.6f, 0.6f, 0.0f},
9026     };
9027
9028     short indices[] = {0, 1, 2, 1, 2, 3};
9029
9030     D3DVERTEXELEMENT9 decl[] =
9031     {
9032         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9033         {1, 0,  D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
9034         {2, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
9035         D3DDECL_END()
9036     };
9037
9038     /* set the default value because it isn't done in wine? */
9039     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 1);
9040     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9041
9042     /* check for D3DSTREAMSOURCE_INDEXEDDATA at stream0 */
9043     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 0, (D3DSTREAMSOURCE_INSTANCEDATA | 1));
9044     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9045
9046     /* check wrong cases */
9047     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 0);
9048     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9049     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9050     ok(hr == D3D_OK && ind == 1, "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9051     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 2);
9052     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9053     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9054     ok(hr == D3D_OK && ind == 2, "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9055     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, (D3DSTREAMSOURCE_INDEXEDDATA | 0));
9056     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9057     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9058     ok(hr == D3D_OK && ind == (D3DSTREAMSOURCE_INDEXEDDATA | 0), "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9059     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, (D3DSTREAMSOURCE_INSTANCEDATA | 0));
9060     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9061     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9062     ok(hr == D3D_OK && ind == (0 | D3DSTREAMSOURCE_INSTANCEDATA), "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9063     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA | 0));
9064     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9065     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9066     ok(hr == D3D_OK && ind == (0 | D3DSTREAMSOURCE_INSTANCEDATA), "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9067
9068     /* set the default value back */
9069     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 1);
9070     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9071
9072     /* create all VertexBuffers*/
9073     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0, D3DPOOL_MANAGED, &vb, NULL);
9074     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
9075     if(!vb) {
9076         skip("Failed to create a vertex buffer\n");
9077         return;
9078     }
9079     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(vertcolor), 0, 0, D3DPOOL_MANAGED, &vb2, NULL);
9080     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
9081     if(!vb2) {
9082         skip("Failed to create a vertex buffer\n");
9083         goto out;
9084     }
9085     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(instancepos), 0, 0, D3DPOOL_MANAGED, &vb3, NULL);
9086     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
9087     if(!vb3) {
9088         skip("Failed to create a vertex buffer\n");
9089         goto out;
9090     }
9091
9092     /* create IndexBuffer*/
9093     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, NULL);
9094     ok(hr == D3D_OK, "IDirect3DDevice9_CreateIndexBuffer failed with %08x\n", hr);
9095     if(!ib) {
9096         skip("Failed to create a index buffer\n");
9097         goto out;
9098     }
9099
9100     /* copy all Buffers (Vertex + Index)*/
9101     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), (void **) &data, 0);
9102     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
9103     memcpy(data, quad, sizeof(quad));
9104     hr = IDirect3DVertexBuffer9_Unlock(vb);
9105     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
9106     hr = IDirect3DVertexBuffer9_Lock(vb2, 0, sizeof(vertcolor), (void **) &data, 0);
9107     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
9108     memcpy(data, vertcolor, sizeof(vertcolor));
9109     hr = IDirect3DVertexBuffer9_Unlock(vb2);
9110     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
9111     hr = IDirect3DVertexBuffer9_Lock(vb3, 0, sizeof(instancepos), (void **) &data, 0);
9112     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
9113     memcpy(data, instancepos, sizeof(instancepos));
9114     hr = IDirect3DVertexBuffer9_Unlock(vb3);
9115     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
9116     hr = IDirect3DIndexBuffer9_Lock(ib, 0, sizeof(indices), (void **) &data, 0);
9117     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Lock failed with %08x\n", hr);
9118     memcpy(data, indices, sizeof(indices));
9119     hr = IDirect3DIndexBuffer9_Unlock(ib);
9120     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
9121
9122     /* create VertexShader */
9123     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
9124     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexShader failed hr=%08x\n", hr);
9125     if(!shader) {
9126         skip("Failed to create a vetex shader\n");
9127         goto out;
9128     }
9129
9130     hr = IDirect3DDevice9_SetVertexShader(device, shader);
9131     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
9132
9133     hr = IDirect3DDevice9_SetIndices(device, ib);
9134     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
9135
9136     /* run all tests */
9137     for( i = 0; i < sizeof(testcases)/sizeof(testcases[0]); ++i)
9138     {
9139         struct testdata act = testcases[i];
9140         decl[0].Stream = act.strVertex;
9141         decl[1].Stream = act.strColor;
9142         decl[2].Stream = act.strInstance;
9143         /* create VertexDeclarations */
9144         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl, &pDecl);
9145         ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed hr=%08x (case %i)\n", hr, i);
9146
9147         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
9148         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x (case %i)\n", hr, i);
9149
9150         hr = IDirect3DDevice9_BeginScene(device);
9151         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x (case %i)\n", hr, i);
9152         if(SUCCEEDED(hr))
9153         {
9154             hr = IDirect3DDevice9_SetVertexDeclaration(device, pDecl);
9155             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x (case %i)\n", hr, i);
9156
9157             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strVertex, (D3DSTREAMSOURCE_INDEXEDDATA | act.idxVertex));
9158             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9159             hr = IDirect3DDevice9_SetStreamSource(device, act.strVertex, vb, 0, sizeof(quad[0]));
9160             ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x (case %i)\n", hr, i);
9161
9162             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strColor, (D3DSTREAMSOURCE_INDEXEDDATA | act.idxColor));
9163             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9164             hr = IDirect3DDevice9_SetStreamSource(device, act.strColor, vb2, 0, sizeof(vertcolor[0]));
9165             ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x (case %i)\n", hr, i);
9166
9167             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strInstance, (D3DSTREAMSOURCE_INSTANCEDATA | act.idxInstance));
9168             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9169             hr = IDirect3DDevice9_SetStreamSource(device, act.strInstance, vb3, 0, sizeof(instancepos[0]));
9170             ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x (case %i)\n", hr, i);
9171
9172             /* don't know if this is right (1*3 and 4*1)*/
9173             hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 0, 1 * 3 , 0, 4*1);
9174             ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitive failed with %08x (case %i)\n", hr, i);
9175             hr = IDirect3DDevice9_EndScene(device);
9176             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x (case %i)\n", hr, i);
9177
9178             /* set all StreamSource && StreamSourceFreq back to default */
9179             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strVertex, 1);
9180             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9181             hr = IDirect3DDevice9_SetStreamSource(device, act.strVertex, NULL, 0, 0);
9182             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9183             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.idxColor, 1);
9184             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9185             hr = IDirect3DDevice9_SetStreamSource(device, act.idxColor, NULL, 0, 0);
9186             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9187             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.idxInstance, 1);
9188             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9189             hr = IDirect3DDevice9_SetStreamSource(device, act.idxInstance, NULL, 0, 0);
9190             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9191         }
9192
9193         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9194         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x (case %i)\n", hr, i);
9195
9196         hr = IDirect3DVertexDeclaration9_Release(pDecl);
9197         ok(hr == D3D_OK, "IDirect3DVertexDeclaration9_Release failed with %08x (case %i)\n", hr, i);
9198
9199         color = getPixelColor(device, 160, 360);
9200         ok(color == act.color1, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color1, i);
9201         color = getPixelColor(device, 480, 360);
9202         ok(color == act.color2, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color2, i);
9203         color = getPixelColor(device, 480, 120);
9204         ok(color == act.color3, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color3, i);
9205         color = getPixelColor(device, 160, 120);
9206         ok(color == act.color4, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color4, i);
9207     }
9208
9209     hr = IDirect3DDevice9_SetIndices(device, NULL);
9210     ok(hr == D3D_OK, "IDirect3DDevice9_SetIndices failed with %08x\n", hr);
9211
9212 out:
9213     if(vb) IDirect3DVertexBuffer9_Release(vb);
9214     if(vb2)IDirect3DVertexBuffer9_Release(vb2);
9215     if(vb3)IDirect3DVertexBuffer9_Release(vb3);
9216     if(ib)IDirect3DIndexBuffer9_Release(ib);
9217     if(shader)IDirect3DVertexShader9_Release(shader);
9218 }
9219
9220 static void np2_stretch_rect_test(IDirect3DDevice9 *device) {
9221     IDirect3DSurface9 *src = NULL, *dst = NULL, *backbuffer = NULL;
9222     IDirect3DTexture9 *dsttex = NULL;
9223     HRESULT hr;
9224     DWORD color;
9225     D3DRECT r1 = {0,  0,  50,  50 };
9226     D3DRECT r2 = {50, 0,  100, 50 };
9227     D3DRECT r3 = {50, 50, 100, 100};
9228     D3DRECT r4 = {0,  50,  50, 100};
9229     const float quad[] = {
9230         -1.0,   -1.0,   0.1,    0.0,    0.0,
9231          1.0,   -1.0,   0.1,    1.0,    0.0,
9232         -1.0,    1.0,   0.1,    0.0,    1.0,
9233          1.0,    1.0,   0.1,    1.0,    1.0,
9234     };
9235
9236     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
9237     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
9238
9239     hr = IDirect3DDevice9_CreateRenderTarget(device, 100, 100, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &src, NULL );
9240     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
9241     hr = IDirect3DDevice9_CreateTexture(device, 25, 25, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &dsttex, NULL);
9242     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
9243
9244     if(!src || !dsttex) {
9245         skip("One or more test resources could not be created\n");
9246         goto cleanup;
9247     }
9248
9249     hr = IDirect3DTexture9_GetSurfaceLevel(dsttex, 0, &dst);
9250     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
9251
9252     hr = IDirect3DDevice9_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
9253     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9254
9255     /* Clear the StretchRect destination for debugging */
9256     hr = IDirect3DDevice9_SetRenderTarget(device, 0, dst);
9257     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
9258     hr = IDirect3DDevice9_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
9259     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9260
9261     hr = IDirect3DDevice9_SetRenderTarget(device, 0, src);
9262     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
9263
9264     hr = IDirect3DDevice9_Clear(device, 1, &r1, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
9265     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9266     hr = IDirect3DDevice9_Clear(device, 1, &r2, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
9267     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9268     hr = IDirect3DDevice9_Clear(device, 1, &r3, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
9269     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9270     hr = IDirect3DDevice9_Clear(device, 1, &r4, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
9271     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9272
9273     /* Stretchrect before setting the render target back to the backbuffer. This will make Wine use
9274      * the target -> texture GL blit path
9275      */
9276     hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst, NULL, D3DTEXF_POINT);
9277     ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
9278     IDirect3DSurface9_Release(dst);
9279
9280     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
9281     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
9282
9283     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) dsttex);
9284     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9285     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
9286     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
9287     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9288     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9289     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9290     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9291
9292     hr = IDirect3DDevice9_BeginScene(device);
9293     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
9294     if(SUCCEEDED(hr)) {
9295         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
9296         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
9297         hr = IDirect3DDevice9_EndScene(device);
9298         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
9299     }
9300
9301     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9302     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
9303     color = getPixelColor(device, 160, 360);
9304     ok(color == 0x00ff0000, "stretchrect: Pixel 160,360 has color 0x%08x, expected 0x00ff0000\n", color);
9305     color = getPixelColor(device, 480, 360);
9306     ok(color == 0x0000ff00, "stretchrect: Pixel 480,360 has color 0x%08x, expected 0x0000ff00\n", color);
9307     color = getPixelColor(device, 480, 120);
9308     ok(color == 0x000000ff, "stretchrect: Pixel 480,120 has color 0x%08x, expected 0x000000ff\n", color);
9309     color = getPixelColor(device, 160, 120);
9310     ok(color == 0x00000000, "stretchrect: Pixel 160,120 has color 0x%08x, expected 0x00000000\n", color);
9311
9312     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
9313     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9314     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
9315     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9316
9317 cleanup:
9318     if(src) IDirect3DSurface9_Release(src);
9319     if(backbuffer) IDirect3DSurface9_Release(backbuffer);
9320     if(dsttex) IDirect3DTexture9_Release(dsttex);
9321 }
9322
9323 static void texop_test(IDirect3DDevice9 *device)
9324 {
9325     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
9326     IDirect3DTexture9 *texture = NULL;
9327     D3DLOCKED_RECT locked_rect;
9328     D3DCOLOR color;
9329     D3DCAPS9 caps;
9330     HRESULT hr;
9331     unsigned i;
9332
9333     static const struct {
9334         float x, y, z;
9335         float s, t;
9336         D3DCOLOR diffuse;
9337     } quad[] = {
9338         {-1.0f, -1.0f, 0.1f, -1.0f, -1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)},
9339         {-1.0f,  1.0f, 0.1f, -1.0f,  1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)},
9340         { 1.0f, -1.0f, 0.1f,  1.0f, -1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)},
9341         { 1.0f,  1.0f, 0.1f,  1.0f,  1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)}
9342     };
9343
9344     static const D3DVERTEXELEMENT9 decl_elements[] = {
9345         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9346         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
9347         {0, 20, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
9348         D3DDECL_END()
9349     };
9350
9351     static const struct {
9352         D3DTEXTUREOP op;
9353         const char *name;
9354         DWORD caps_flag;
9355         D3DCOLOR result;
9356     } test_data[] = {
9357         {D3DTOP_SELECTARG1,                "SELECTARG1",                D3DTEXOPCAPS_SELECTARG1,                D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
9358         {D3DTOP_SELECTARG2,                "SELECTARG2",                D3DTEXOPCAPS_SELECTARG2,                D3DCOLOR_ARGB(0x00, 0x33, 0x33, 0x33)},
9359         {D3DTOP_MODULATE,                  "MODULATE",                  D3DTEXOPCAPS_MODULATE,                  D3DCOLOR_ARGB(0x00, 0x00, 0x33, 0x00)},
9360         {D3DTOP_MODULATE2X,                "MODULATE2X",                D3DTEXOPCAPS_MODULATE2X,                D3DCOLOR_ARGB(0x00, 0x00, 0x66, 0x00)},
9361         {D3DTOP_MODULATE4X,                "MODULATE4X",                D3DTEXOPCAPS_MODULATE4X,                D3DCOLOR_ARGB(0x00, 0x00, 0xcc, 0x00)},
9362         {D3DTOP_ADD,                       "ADD",                       D3DTEXOPCAPS_ADD,                       D3DCOLOR_ARGB(0x00, 0x33, 0xff, 0x33)},
9363         {D3DTOP_ADDSIGNED,                 "ADDSIGNED",                 D3DTEXOPCAPS_ADDSIGNED,                 D3DCOLOR_ARGB(0x00, 0x00, 0xb2, 0x00)},
9364         {D3DTOP_ADDSIGNED2X,               "ADDSIGNED2X",               D3DTEXOPCAPS_ADDSIGNED2X,               D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
9365         {D3DTOP_SUBTRACT,                  "SUBTRACT",                  D3DTEXOPCAPS_SUBTRACT,                  D3DCOLOR_ARGB(0x00, 0x00, 0xcc, 0x00)},
9366         {D3DTOP_ADDSMOOTH,                 "ADDSMOOTH",                 D3DTEXOPCAPS_ADDSMOOTH,                 D3DCOLOR_ARGB(0x00, 0x33, 0xff, 0x33)},
9367         {D3DTOP_BLENDDIFFUSEALPHA,         "BLENDDIFFUSEALPHA",         D3DTEXOPCAPS_BLENDDIFFUSEALPHA,         D3DCOLOR_ARGB(0x00, 0x22, 0x77, 0x22)},
9368         {D3DTOP_BLENDTEXTUREALPHA,         "BLENDTEXTUREALPHA",         D3DTEXOPCAPS_BLENDTEXTUREALPHA,         D3DCOLOR_ARGB(0x00, 0x14, 0xad, 0x14)},
9369         {D3DTOP_BLENDFACTORALPHA,          "BLENDFACTORALPHA",          D3DTEXOPCAPS_BLENDFACTORALPHA,          D3DCOLOR_ARGB(0x00, 0x07, 0xe4, 0x07)},
9370         {D3DTOP_BLENDTEXTUREALPHAPM,       "BLENDTEXTUREALPHAPM",       D3DTEXOPCAPS_BLENDTEXTUREALPHAPM,       D3DCOLOR_ARGB(0x00, 0x14, 0xff, 0x14)},
9371         {D3DTOP_BLENDCURRENTALPHA,         "BLENDCURRENTALPHA",         D3DTEXOPCAPS_BLENDCURRENTALPHA,         D3DCOLOR_ARGB(0x00, 0x22, 0x77, 0x22)},
9372         {D3DTOP_MODULATEALPHA_ADDCOLOR,    "MODULATEALPHA_ADDCOLOR",    D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR,    D3DCOLOR_ARGB(0x00, 0x1f, 0xff, 0x1f)},
9373         {D3DTOP_MODULATECOLOR_ADDALPHA,    "MODULATECOLOR_ADDALPHA",    D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA,    D3DCOLOR_ARGB(0x00, 0x99, 0xcc, 0x99)},
9374         {D3DTOP_MODULATEINVALPHA_ADDCOLOR, "MODULATEINVALPHA_ADDCOLOR", D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR, D3DCOLOR_ARGB(0x00, 0x14, 0xff, 0x14)},
9375         {D3DTOP_MODULATEINVCOLOR_ADDALPHA, "MODULATEINVCOLOR_ADDALPHA", D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA, D3DCOLOR_ARGB(0x00, 0xcc, 0x99, 0xcc)},
9376         /* BUMPENVMAP & BUMPENVMAPLUMINANCE have their own tests */
9377         {D3DTOP_DOTPRODUCT3,               "DOTPRODUCT2",               D3DTEXOPCAPS_DOTPRODUCT3,               D3DCOLOR_ARGB(0x00, 0x99, 0x99, 0x99)},
9378         {D3DTOP_MULTIPLYADD,               "MULTIPLYADD",               D3DTEXOPCAPS_MULTIPLYADD,               D3DCOLOR_ARGB(0x00, 0xff, 0x33, 0x00)},
9379         {D3DTOP_LERP,                      "LERP",                      D3DTEXOPCAPS_LERP,                      D3DCOLOR_ARGB(0x00, 0x00, 0x33, 0x33)},
9380     };
9381
9382     memset(&caps, 0, sizeof(caps));
9383     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9384     ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x\n", hr);
9385
9386     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
9387     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed with 0x%08x\n", hr);
9388     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
9389     ok(SUCCEEDED(hr), "SetVertexDeclaration failed with 0x%08x\n", hr);
9390
9391     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
9392     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed with 0x%08x\n", hr);
9393     hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
9394     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
9395     *((DWORD *)locked_rect.pBits) = D3DCOLOR_ARGB(0x99, 0x00, 0xff, 0x00);
9396     hr = IDirect3DTexture9_UnlockRect(texture, 0);
9397     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
9398     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
9399     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
9400
9401     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG0, D3DTA_DIFFUSE);
9402     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9403     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9404     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9405     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9406     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9407
9408     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
9409     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9410
9411     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
9412     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9413     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0xdd333333);
9414     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9415     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA);
9416     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9417
9418     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
9419     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9420
9421     for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
9422     {
9423         if (!(caps.TextureOpCaps & test_data[i].caps_flag))
9424         {
9425             skip("tex operation %s not supported\n", test_data[i].name);
9426             continue;
9427         }
9428
9429         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, test_data[i].op);
9430         ok(SUCCEEDED(hr), "SetTextureStageState (%s) failed with 0x%08x\n", test_data[i].name, hr);
9431
9432         hr = IDirect3DDevice9_BeginScene(device);
9433         ok(SUCCEEDED(hr), "BeginScene failed with 0x%08x\n", hr);
9434
9435         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
9436         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9437
9438         hr = IDirect3DDevice9_EndScene(device);
9439         ok(SUCCEEDED(hr), "EndScene failed with 0x%08x\n", hr);
9440
9441         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9442         ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
9443
9444         color = getPixelColor(device, 320, 240);
9445         ok(color_match(color, test_data[i].result, 3), "Operation %s returned color 0x%08x, expected 0x%08x\n",
9446                 test_data[i].name, color, test_data[i].result);
9447     }
9448
9449     if (texture) IDirect3DTexture9_Release(texture);
9450     if (vertex_declaration) IDirect3DVertexDeclaration9_Release(vertex_declaration);
9451 }
9452
9453 static void yuv_color_test(IDirect3DDevice9 *device) {
9454     HRESULT hr;
9455     IDirect3DSurface9 *surface = NULL, *target = NULL;
9456     unsigned int fmt, i;
9457     D3DFORMAT format;
9458     const char *fmt_string;
9459     D3DLOCKED_RECT lr;
9460     IDirect3D9 *d3d;
9461     HRESULT color;
9462     DWORD ref_color_left, ref_color_right;
9463
9464     struct {
9465         DWORD in;           /* The input color */
9466         DWORD uyvy_left;    /* "in" interpreted as uyvy and transformed to RGB, pixel 1/1*/
9467         DWORD uyvy_right;   /* "in" interpreted as uyvy and transformed to RGB, pixel 2/1*/
9468         DWORD yuy2_left;    /* "in" interpreted as yuy2 and transformed to RGB, pixel 1/1 */
9469         DWORD yuy2_right;   /* "in" interpreted as yuy2 and transformed to RGB, pixel 2/1 */
9470     } test_data[] = {
9471     /* Originally I wanted to avoid being evil, and set Y1 = Y2 to avoid triggering troubles in shader converters,
9472      * but the main difference between YUY2 and UYVY is the swapped ordering of the chroma and luminance
9473      * values. However, handling the two Y's properly could have a big impact on image quality, so be picky about
9474      * that
9475      */
9476       { 0x00000000, 0x00008700, 0x00008700, 0x00008700, 0x00008700 },
9477       { 0xff000000, 0x00008700, 0x004bff1c, 0x00b30000, 0x00b30000 },
9478       { 0x00ff0000, 0x00b30000, 0x00b30000, 0x00008700, 0x004bff1c },
9479       { 0x0000ff00, 0x004bff1c, 0x00008700, 0x000030e1, 0x000030e1 },
9480       { 0x000000ff, 0x000030e1, 0x000030e1, 0x004bff1c, 0x00008700 },
9481       { 0xffff0000, 0x00b30000, 0x00ffd01c, 0x00b30000, 0x00ffd01c },
9482       { 0xff00ff00, 0x004bff1c, 0x004bff1c, 0x00b300e1, 0x00b300e1 },
9483       { 0xff0000ff, 0x000030e1, 0x004bffff, 0x00ffd01c, 0x00b30000 },
9484       { 0x00ffff00, 0x00ffd01c, 0x00b30000, 0x000030e1, 0x004bffff },
9485       { 0x00ff00ff, 0x00b300e1, 0x00b300e1, 0x004bff1c, 0x004bff1c },
9486       { 0x0000ffff, 0x004bffff, 0x000030e1, 0x004bffff, 0x000030e1 },
9487       { 0xffffff00, 0x00ffd01c, 0x00ffd01c, 0x00b300e1, 0x00ff79ff },
9488       { 0xffff00ff, 0x00b300e1, 0x00ff79ff, 0x00ffd01c, 0x00ffd01c },
9489       { 0xffffffff, 0x00ff79ff, 0x00ff79ff, 0x00ff79ff, 0x00ff79ff },
9490
9491       { 0x4cff4c54, 0x00ff0000, 0x00ff0000, 0x000b8b00, 0x00b6ffa3 },
9492       { 0x00800080, 0x00000000, 0x00000000, 0x0000ff00, 0x0000ff00 },
9493       { 0xFF80FF80, 0x00ffffff, 0x00ffffff, 0x00ff00ff, 0x00ff00ff },
9494       { 0x1c6b1cff, 0x000000fd, 0x000000fd, 0x006dff45, 0x0000d500 },
9495     };
9496
9497     hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
9498     ok(hr == D3D_OK, "IDirect3DDevice9_GetDirect3D failed, hr = %08x\n", hr);
9499     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &target);
9500     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderTarget failed, hr = %08x\n", hr);
9501
9502     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX0);
9503     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %08x\n", hr);
9504
9505     for(fmt = 0; fmt < 2; fmt++) {
9506         if(fmt == 0) {
9507             format = D3DFMT_UYVY;
9508             fmt_string = "D3DFMT_UYVY";
9509         } else {
9510             format = D3DFMT_YUY2;
9511             fmt_string = "D3DFMT_YUY2";
9512         }
9513
9514         /* Some(all?) Windows drivers do not support YUV 3D textures, only 2D surfaces in StretchRect. Thus use
9515                        * StretchRect to draw the YUV surface onto the screen instead of drawPrimitive
9516                        */
9517         if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
9518                                         D3DRTYPE_SURFACE, format) != D3D_OK) {
9519             skip("%s is not supported\n", fmt_string);
9520             continue;
9521         }
9522
9523         /* A pixel is effectively 16 bit large, but two pixels are stored together, so the minimum size is 2x1 */
9524         hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2, 1, format, D3DPOOL_DEFAULT, &surface, NULL);
9525         ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed, hr = %08x\n", hr);
9526
9527         for(i = 0; i < (sizeof(test_data)/sizeof(test_data[0])); i++) {
9528             if(fmt == 0) {
9529                 ref_color_left = test_data[i].uyvy_left;
9530                 ref_color_right = test_data[i].uyvy_right;
9531             } else {
9532                 ref_color_left = test_data[i].yuy2_left;
9533                 ref_color_right = test_data[i].yuy2_right;
9534             }
9535
9536             memset(&lr, 0, sizeof(lr));
9537             hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
9538             ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr = %08x\n", hr);
9539             *((DWORD *) lr.pBits) = test_data[i].in;
9540             hr = IDirect3DSurface9_UnlockRect(surface);
9541             ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr = %08x\n", hr);
9542
9543             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
9544             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9545             hr = IDirect3DDevice9_StretchRect(device, surface, NULL, target, NULL, D3DTEXF_POINT);
9546             ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with 0x%08x\n", hr);
9547             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9548             ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
9549
9550             /* Native D3D can't resist filtering the YUY surface, even though we asked it not to do so above. To
9551              * prevent running into precision problems, read a far left and far right pixel. In the future we may
9552              * want to add tests for the filtered pixels as well.
9553              *
9554              * Unfortunately different implementations(Windows-NV and Mac-ATI tested) interpret some colors vastly
9555              * differently, so we need a max diff of 16
9556              */
9557             color = getPixelColor(device, 40, 240);
9558             ok(color_match(color, ref_color_left, 16),
9559                "Input 0x%08x: Got color 0x%08x for pixel 1/1, expected 0x%08x, format %s\n",
9560                test_data[i].in, color, ref_color_left, fmt_string);
9561             color = getPixelColor(device, 600, 240);
9562             ok(color_match(color, ref_color_right, 16),
9563                "Input 0x%08x: Got color 0x%08x for pixel 2/1, expected 0x%08x, format %s\n",
9564                test_data[i].in, color, ref_color_left, fmt_string);
9565         }
9566         IDirect3DSurface9_Release(surface);
9567     }
9568     IDirect3DSurface9_Release(target);
9569     IDirect3D9_Release(d3d);
9570 }
9571
9572 static void texop_range_test(IDirect3DDevice9 *device)
9573 {
9574     static const struct {
9575         float x, y, z;
9576         D3DCOLOR diffuse;
9577     } quad[] = {
9578         {-1.0f, -1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)},
9579         {-1.0f,  1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)},
9580         { 1.0f, -1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)},
9581         { 1.0f,  1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)}
9582     };
9583     HRESULT hr;
9584     IDirect3DTexture9 *texture;
9585     D3DLOCKED_RECT locked_rect;
9586     D3DCAPS9 caps;
9587     DWORD color;
9588
9589     /* We need ADD and SUBTRACT operations */
9590     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9591     ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x\n", hr);
9592     if (!(caps.TextureOpCaps & D3DTEXOPCAPS_ADD)) {
9593         skip("D3DTOP_ADD is not supported, skipping value range test\n");
9594     }
9595     if (!(caps.TextureOpCaps & D3DTEXOPCAPS_SUBTRACT)) {
9596         skip("D3DTEXOPCAPS_SUBTRACT is not supported, skipping value range test\n");
9597     }
9598
9599     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
9600     ok(SUCCEEDED(hr), "SetFVF failed with 0x%08x\n", hr);
9601     /* Stage 1: result = diffuse(=1.0) + diffuse
9602      * stage 2: result = result - tfactor(= 0.5)
9603      */
9604     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0x80808080);
9605     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9606     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
9607     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9608     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
9609     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9610     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
9611     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9612     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_CURRENT);
9613     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9614     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9615     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9616     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SUBTRACT);
9617     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9618
9619     hr = IDirect3DDevice9_BeginScene(device);
9620     ok(SUCCEEDED(hr), "BeginScene failed with 0x%08x\n", hr);
9621     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
9622     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9623     hr = IDirect3DDevice9_EndScene(device);
9624     ok(SUCCEEDED(hr), "EndScene failed with 0x%08x\n", hr);
9625     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9626     ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
9627
9628     color = getPixelColor(device, 320, 240);
9629     ok(color_match(color, 0x00808080, 1), "texop Range > 1.0 returned 0x%08x, expected 0x00808080\n",
9630        color);
9631
9632     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
9633     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed with 0x%08x\n", hr);
9634     hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
9635     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
9636     *((DWORD *)locked_rect.pBits) = D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00);
9637     hr = IDirect3DTexture9_UnlockRect(texture, 0);
9638     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
9639     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
9640     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
9641
9642     /* Stage 1: result = texture(=0.0) - tfactor(= 0.5)
9643      * stage 2: result = result + diffuse(1.0)
9644      */
9645     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0x80808080);
9646     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9647     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9648     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9649     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9650     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9651     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SUBTRACT);
9652     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9653     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_CURRENT);
9654     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9655     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
9656     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9657     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
9658     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9659
9660     hr = IDirect3DDevice9_BeginScene(device);
9661     ok(SUCCEEDED(hr), "BeginScene failed with 0x%08x\n", hr);
9662     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
9663     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9664     hr = IDirect3DDevice9_EndScene(device);
9665     ok(SUCCEEDED(hr), "EndScene failed with 0x%08x\n", hr);
9666     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9667     ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
9668
9669     color = getPixelColor(device, 320, 240);
9670     ok(color_match(color, 0x00ffffff, 1), "texop Range < 0.0 returned 0x%08x, expected 0x00ffffff\n",
9671        color);
9672
9673     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
9674     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9675     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
9676     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9677     hr = IDirect3DDevice9_SetTexture(device, 1, NULL);
9678     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
9679     IDirect3DTexture9_Release(texture);
9680 }
9681
9682 static void alphareplicate_test(IDirect3DDevice9 *device) {
9683     struct vertex quad[] = {
9684         { -1.0,    -1.0,    0.1,    0x80ff00ff },
9685         {  1.0,    -1.0,    0.1,    0x80ff00ff },
9686         { -1.0,     1.0,    0.1,    0x80ff00ff },
9687         {  1.0,     1.0,    0.1,    0x80ff00ff },
9688     };
9689     HRESULT hr;
9690     DWORD color;
9691
9692     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
9693     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9694
9695     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
9696     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
9697
9698     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9699     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9700     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE | D3DTA_ALPHAREPLICATE);
9701     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9702
9703     hr = IDirect3DDevice9_BeginScene(device);
9704     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
9705     if(SUCCEEDED(hr)) {
9706         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
9707         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9708         hr = IDirect3DDevice9_EndScene(device);
9709         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
9710     }
9711
9712     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9713     ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
9714
9715     color = getPixelColor(device, 320, 240);
9716     ok(color_match(color, 0x00808080, 1), "alphareplicate test 0x%08x, expected 0x00808080\n",
9717        color);
9718
9719     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
9720     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9721
9722 }
9723
9724 static void dp3_alpha_test(IDirect3DDevice9 *device) {
9725     HRESULT hr;
9726     D3DCAPS9 caps;
9727     DWORD color;
9728     struct vertex quad[] = {
9729         { -1.0,    -1.0,    0.1,    0x408080c0 },
9730         {  1.0,    -1.0,    0.1,    0x408080c0 },
9731         { -1.0,     1.0,    0.1,    0x408080c0 },
9732         {  1.0,     1.0,    0.1,    0x408080c0 },
9733     };
9734
9735     memset(&caps, 0, sizeof(caps));
9736     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9737     ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x\n", hr);
9738     if (!(caps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3)) {
9739         skip("D3DTOP_DOTPRODUCT3 not supported\n");
9740         return;
9741     }
9742
9743     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
9744     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9745
9746     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
9747     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
9748
9749     /* dp3_x4 r0, diffuse_bias, tfactor_bias
9750      * mov r0.a, diffuse.a
9751      * mov r0, r0.a
9752      *
9753      * It turns out that the 2nd line is ignored, and the dp3 result written into r0.a instead
9754      * 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
9755      * (0.0 * 0.5 + 0.0 * 0.5 + 0.25 * 0.5) * 4 = 0.125 * 4 = 0.5, with a bunch of inprecision.
9756      */
9757     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);
9758     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9759     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
9760     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9761     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9762     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9763     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
9764     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9765     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
9766     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9767     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9768     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9769     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_CURRENT | D3DTA_ALPHAREPLICATE);
9770     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9771     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
9772     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9773     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0xffffffff);
9774     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9775
9776     hr = IDirect3DDevice9_BeginScene(device);
9777     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
9778     if(SUCCEEDED(hr)) {
9779         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
9780         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9781         hr = IDirect3DDevice9_EndScene(device);
9782         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
9783     }
9784
9785     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9786     ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
9787
9788     color = getPixelColor(device, 320, 240);
9789     ok(color_match(color, 0x00808080, 4), "dp3 alpha test 0x%08x, expected 0x00808080\n",
9790        color);
9791
9792     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
9793     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9794     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
9795     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9796     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
9797     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9798 }
9799
9800 static void zwriteenable_test(IDirect3DDevice9 *device) {
9801     HRESULT hr;
9802     DWORD color;
9803     struct vertex quad1[] = {
9804         { -1.0,  -1.0,  0.1,    0x00ff0000},
9805         { -1.0,   1.0,  0.1,    0x00ff0000},
9806         {  1.0,  -1.0,  0.1,    0x00ff0000},
9807         {  1.0,   1.0,  0.1,    0x00ff0000},
9808     };
9809     struct vertex quad2[] = {
9810         { -1.0,  -1.0,  0.9,    0x0000ff00},
9811         { -1.0,   1.0,  0.9,    0x0000ff00},
9812         {  1.0,  -1.0,  0.9,    0x0000ff00},
9813         {  1.0,   1.0,  0.9,    0x0000ff00},
9814     };
9815
9816     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
9817     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9818
9819     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
9820     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
9821     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
9822     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9823     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
9824     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9825     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
9826     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9827
9828     hr = IDirect3DDevice9_BeginScene(device);
9829     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
9830     if(SUCCEEDED(hr)) {
9831         /* The Z buffer is filled with 1.0. Draw a red quad with z = 0.1, zenable = D3DZB_FALSE, zwriteenable = TRUE.
9832          * The red color is written because the z test is disabled. The question is whether the z = 0.1 values
9833          * are written into the Z buffer. After the draw, set zenable = TRUE and draw a green quad at z = 0.9.
9834          * If the values are written, the z test will fail(0.9 > 0.1) and the red color remains. If the values
9835          * are not written, the z test succeeds(0.9 < 1.0) and the green color is written. It turns out that
9836          * the screen is green, so zenable = D3DZB_FALSE and zwriteenable  = TRUE does NOT write to the z buffer.
9837          */
9838         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
9839         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9840         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
9841         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9842         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
9843         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9844
9845         hr = IDirect3DDevice9_EndScene(device);
9846         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
9847     }
9848
9849     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9850     ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
9851     color = getPixelColor(device, 320, 240);
9852     ok(color_match(color, 0x0000ff00, 1), "zwriteenable test returned 0x%08x, expected 0x0000ff00\n",
9853        color);
9854
9855     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
9856     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9857 }
9858
9859 START_TEST(visual)
9860 {
9861     IDirect3DDevice9 *device_ptr;
9862     D3DCAPS9 caps;
9863     HRESULT hr;
9864     DWORD color;
9865
9866     d3d9_handle = LoadLibraryA("d3d9.dll");
9867     if (!d3d9_handle)
9868     {
9869         skip("Could not load d3d9.dll\n");
9870         return;
9871     }
9872
9873     device_ptr = init_d3d9();
9874     if (!device_ptr)
9875     {
9876         skip("Creating the device failed\n");
9877         return;
9878     }
9879
9880     IDirect3DDevice9_GetDeviceCaps(device_ptr, &caps);
9881
9882     /* Check for the reliability of the returned data */
9883     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
9884     if(FAILED(hr))
9885     {
9886         skip("Clear failed, can't assure correctness of the test results, skipping\n");
9887         goto cleanup;
9888     }
9889     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
9890
9891     color = getPixelColor(device_ptr, 1, 1);
9892     if(color !=0x00ff0000)
9893     {
9894         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
9895         goto cleanup;
9896     }
9897
9898     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xff00ddee, 0.0, 0);
9899     if(FAILED(hr))
9900     {
9901         skip("Clear failed, can't assure correctness of the test results, skipping\n");
9902         goto cleanup;
9903     }
9904     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
9905
9906     color = getPixelColor(device_ptr, 639, 479);
9907     if(color != 0x0000ddee)
9908     {
9909         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
9910         goto cleanup;
9911     }
9912
9913     /* Now execute the real tests */
9914     stretchrect_test(device_ptr);
9915     lighting_test(device_ptr);
9916     clear_test(device_ptr);
9917     fog_test(device_ptr);
9918     if(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
9919     {
9920         test_cube_wrap(device_ptr);
9921     } else {
9922         skip("No cube texture support\n");
9923     }
9924     z_range_test(device_ptr);
9925     if(caps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)
9926     {
9927         maxmip_test(device_ptr);
9928     }
9929     else
9930     {
9931         skip("No mipmap support\n");
9932     }
9933     offscreen_test(device_ptr);
9934     alpha_test(device_ptr);
9935     shademode_test(device_ptr);
9936     srgbtexture_test(device_ptr);
9937     release_buffer_test(device_ptr);
9938     float_texture_test(device_ptr);
9939     g16r16_texture_test(device_ptr);
9940     pixelshader_blending_test(device_ptr);
9941     texture_transform_flags_test(device_ptr);
9942     autogen_mipmap_test(device_ptr);
9943     fixed_function_decl_test(device_ptr);
9944     conditional_np2_repeat_test(device_ptr);
9945     fixed_function_bumpmap_test(device_ptr);
9946     if(caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) {
9947         stencil_cull_test(device_ptr);
9948     } else {
9949         skip("No two sided stencil support\n");
9950     }
9951     pointsize_test(device_ptr);
9952     tssargtemp_test(device_ptr);
9953     np2_stretch_rect_test(device_ptr);
9954     yuv_color_test(device_ptr);
9955     zwriteenable_test(device_ptr);
9956
9957     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1))
9958     {
9959         test_constant_clamp_vs(device_ptr);
9960         test_compare_instructions(device_ptr);
9961     }
9962     else skip("No vs_1_1 support\n");
9963
9964     if (caps.VertexShaderVersion >= D3DVS_VERSION(2, 0))
9965     {
9966         test_mova(device_ptr);
9967         if (caps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) {
9968             test_vshader_input(device_ptr);
9969             test_vshader_float16(device_ptr);
9970             stream_test(device_ptr);
9971         } else {
9972             skip("No vs_3_0 support\n");
9973         }
9974     }
9975     else skip("No vs_2_0 support\n");
9976
9977     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1) && caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
9978     {
9979         fog_with_shader_test(device_ptr);
9980         fog_srgbwrite_test(device_ptr);
9981     }
9982     else skip("No vs_1_1 and ps_1_1 support\n");
9983
9984     if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
9985     {
9986         texbem_test(device_ptr);
9987         texdepth_test(device_ptr);
9988         texkill_test(device_ptr);
9989         x8l8v8u8_test(device_ptr);
9990         if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 4)) {
9991             constant_clamp_ps_test(device_ptr);
9992             cnd_test(device_ptr);
9993             if (caps.PixelShaderVersion >= D3DPS_VERSION(2, 0)) {
9994                 dp2add_ps_test(device_ptr);
9995                 if (caps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) {
9996                     nested_loop_test(device_ptr);
9997                     fixed_function_varying_test(device_ptr);
9998                     vFace_register_test(device_ptr);
9999                     vpos_register_test(device_ptr);
10000                     multiple_rendertargets_test(device_ptr);
10001                     if(caps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) {
10002                         vshader_version_varying_test(device_ptr);
10003                         pshader_version_varying_test(device_ptr);
10004                     } else {
10005                         skip("No vs_3_0 support\n");
10006                     }
10007                 } else {
10008                     skip("No ps_3_0 support\n");
10009                 }
10010             } else {
10011                 skip("No ps_2_0 support\n");
10012             }
10013         }
10014     }
10015     else skip("No ps_1_1 support\n");
10016
10017     texop_test(device_ptr);
10018     texop_range_test(device_ptr);
10019     alphareplicate_test(device_ptr);
10020     dp3_alpha_test(device_ptr);
10021
10022 cleanup:
10023     if(device_ptr) {
10024         ULONG ref;
10025
10026         D3DPRESENT_PARAMETERS present_parameters;
10027         IDirect3DSwapChain9 *swapchain;
10028         IDirect3DDevice9_GetSwapChain(device_ptr, 0, &swapchain);
10029         IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters);
10030         IDirect3DSwapChain9_Release(swapchain);
10031         ref = IDirect3DDevice9_Release(device_ptr);
10032         DestroyWindow(present_parameters.hDeviceWindow);
10033         ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
10034     }
10035 }