d3d9: Add an alpha blending test.
[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, 0);
296     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
297
298     hr = IDirect3DDevice9_SetFVF(device, fvf);
299     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
300
301     hr = IDirect3DDevice9_BeginScene(device);
302     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
303     if(hr == D3D_OK)
304     {
305         /* No lights are defined... That means, lit vertices should be entirely black */
306         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
307         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
308         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
309                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitquad, sizeof(unlitquad[0]));
310         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
311
312         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
313         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
314         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
315                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litquad, sizeof(litquad[0]));
316         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
317
318         hr = IDirect3DDevice9_SetFVF(device, nfvf);
319         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
320
321         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
322         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
323         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
324                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitnquad, sizeof(unlitnquad[0]));
325         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
326
327         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
328         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
329         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
330                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litnquad, sizeof(litnquad[0]));
331         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
332
333         IDirect3DDevice9_EndScene(device);
334         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
335     }
336
337     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
338
339     color = getPixelColor(device, 160, 360); /* lower left quad - unlit without normals */
340     ok(color == 0x00ff0000, "Unlit quad without normals has color %08x\n", color);
341     color = getPixelColor(device, 160, 120); /* upper left quad - lit without normals */
342     ok(color == 0x00000000, "Lit quad without normals has color %08x\n", color);
343     color = getPixelColor(device, 480, 360); /* lower left quad - unlit with normals */
344     ok(color == 0x000000ff, "Unlit quad with normals has color %08x\n", color);
345     color = getPixelColor(device, 480, 120); /* upper left quad - lit with normals */
346     ok(color == 0x00000000, "Lit quad with normals has color %08x\n", color);
347
348     hr = IDirect3DDevice9_GetMaterial(device, &old_material);
349     ok(hr == D3D_OK, "IDirect3DDevice9_GetMaterial returned %08x\n", hr);
350     memset(&material, 0, sizeof(material));
351     material.Diffuse.r = 0.0;
352     material.Diffuse.g = 0.0;
353     material.Diffuse.b = 0.0;
354     material.Diffuse.a = 1.0;
355     material.Ambient.r = 0.0;
356     material.Ambient.g = 0.0;
357     material.Ambient.b = 0.0;
358     material.Ambient.a = 0.0;
359     material.Specular.r = 0.0;
360     material.Specular.g = 0.0;
361     material.Specular.b = 0.0;
362     material.Specular.a = 0.0;
363     material.Emissive.r = 0.0;
364     material.Emissive.g = 0.0;
365     material.Emissive.b = 0.0;
366     material.Emissive.a = 0.0;
367     material.Power = 0.0;
368     IDirect3DDevice9_SetMaterial(device, &material);
369     ok(hr == D3D_OK, "IDirect3DDevice9_SetMaterial returned %08x\n", hr);
370
371     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
372     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
373     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
374     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
375
376     hr = IDirect3DDevice9_GetTextureStageState(device, 0, D3DTSS_COLOROP, &cop);
377     ok(hr == D3D_OK, "IDirect3DDevice9_GetTextureStageState returned %08x\n", hr);
378     hr = IDirect3DDevice9_GetTextureStageState(device, 0, D3DTSS_COLORARG1, &carg);
379     ok(hr == D3D_OK, "IDirect3DDevice9_GetTextureStageState returned %08x\n", hr);
380     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
381     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
382     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE | D3DTA_ALPHAREPLICATE);
383     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
384
385     hr = IDirect3DDevice9_BeginScene(device);
386     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
387     if(SUCCEEDED(hr)) {
388         struct vertex lighting_test[] = {
389             {-1.0,   -1.0,   0.1,    0x8000ff00},
390             { 1.0,   -1.0,   0.1,    0x80000000},
391             {-1.0,    1.0,   0.1,    0x8000ff00},
392             { 1.0,    1.0,   0.1,    0x80000000}
393         };
394         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
395         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr=%08x\n", hr);
396         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, lighting_test, sizeof(lighting_test[0]));
397         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
398
399         hr = IDirect3DDevice9_EndScene(device);
400         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
401     }
402
403     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
404     color = getPixelColor(device, 320, 240);
405     ok(color == 0x00ffffff, "Lit vertex alpha test returned color %08x, expected 0x00ffffff\n", color);
406
407     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, cop);
408     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
409     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
410     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
411     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
412     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
413     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
414     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
415     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, carg);
416     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
417     hr = IDirect3DDevice9_SetMaterial(device, &old_material);
418     ok(hr == D3D_OK, "IDirect3DDevice9_SetMaterial returned %08x\n", hr);
419 }
420
421 static void clear_test(IDirect3DDevice9 *device)
422 {
423     /* Tests the correctness of clearing parameters */
424     HRESULT hr;
425     D3DRECT rect[2];
426     D3DRECT rect_negneg;
427     DWORD color;
428     D3DVIEWPORT9 old_vp, vp;
429     RECT scissor;
430     DWORD oldColorWrite;
431     BOOL invalid_clear_failed = FALSE;
432
433     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
434     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
435
436     /* Positive x, negative y */
437     rect[0].x1 = 0;
438     rect[0].y1 = 480;
439     rect[0].x2 = 320;
440     rect[0].y2 = 240;
441
442     /* Positive x, positive y */
443     rect[1].x1 = 0;
444     rect[1].y1 = 0;
445     rect[1].x2 = 320;
446     rect[1].y2 = 240;
447     /* Clear 2 rectangles with one call. The refrast returns an error in this case, every real driver tested so far
448      * returns D3D_OK, but ignores the rectangle silently
449      */
450     hr = IDirect3DDevice9_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
451     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
452     if(hr == D3DERR_INVALIDCALL) invalid_clear_failed = TRUE;
453
454     /* negative x, negative y */
455     rect_negneg.x1 = 640;
456     rect_negneg.y1 = 240;
457     rect_negneg.x2 = 320;
458     rect_negneg.y2 = 0;
459     hr = IDirect3DDevice9_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
460     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
461     if(hr == D3DERR_INVALIDCALL) invalid_clear_failed = TRUE;
462
463     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
464
465     color = getPixelColor(device, 160, 360); /* lower left quad */
466     ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
467     color = getPixelColor(device, 160, 120); /* upper left quad */
468     if(invalid_clear_failed) {
469         /* If the negative rectangle was refused, the other rectangles in the list shouldn't be cleared either */
470         ok(color == 0x00ffffff, "Clear rectangle 1(pos, pos) has color %08x\n", color);
471     } else {
472         /* If the negative rectangle was dropped silently, the correct ones are cleared */
473         ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
474     }
475     color = getPixelColor(device, 480, 360); /* lower right quad  */
476     ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
477     color = getPixelColor(device, 480, 120); /* upper right quad */
478     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
479
480     /* Test how the viewport affects clears */
481     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
482     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
483     hr = IDirect3DDevice9_GetViewport(device, &old_vp);
484     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
485
486     vp.X = 160;
487     vp.Y = 120;
488     vp.Width = 160;
489     vp.Height = 120;
490     vp.MinZ = 0.0;
491     vp.MaxZ = 1.0;
492     hr = IDirect3DDevice9_SetViewport(device, &vp);
493     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
494     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
495     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
496
497     vp.X = 320;
498     vp.Y = 240;
499     vp.Width = 320;
500     vp.Height = 240;
501     vp.MinZ = 0.0;
502     vp.MaxZ = 1.0;
503     hr = IDirect3DDevice9_SetViewport(device, &vp);
504     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
505     rect[0].x1 = 160;
506     rect[0].y1 = 120;
507     rect[0].x2 = 480;
508     rect[0].y2 = 360;
509     hr = IDirect3DDevice9_Clear(device, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
510     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
511
512     hr = IDirect3DDevice9_SetViewport(device, &old_vp);
513     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
514
515     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
516     color = getPixelColor(device, 158, 118);
517     ok(color == 0x00ffffff, "(158,118) has color %08x\n", color);
518     color = getPixelColor(device, 162, 118);
519     ok(color == 0x00ffffff, "(162,118) has color %08x\n", color);
520     color = getPixelColor(device, 158, 122);
521     ok(color == 0x00ffffff, "(158,122) has color %08x\n", color);
522     color = getPixelColor(device, 162, 122);
523     ok(color == 0x000000ff, "(162,122) has color %08x\n", color);
524
525     color = getPixelColor(device, 318, 238);
526     ok(color == 0x000000ff, "(318,238) has color %08x\n", color);
527     color = getPixelColor(device, 322, 238);
528     ok(color == 0x00ffffff, "(322,328) has color %08x\n", color);
529     color = getPixelColor(device, 318, 242);
530     ok(color == 0x00ffffff, "(318,242) has color %08x\n", color);
531     color = getPixelColor(device, 322, 242);
532     ok(color == 0x0000ff00, "(322,242) has color %08x\n", color);
533
534     color = getPixelColor(device, 478, 358);
535     ok(color == 0x0000ff00, "(478,358 has color %08x\n", color);
536     color = getPixelColor(device, 482, 358);
537     ok(color == 0x00ffffff, "(482,358) has color %08x\n", color);
538     color = getPixelColor(device, 478, 362);
539     ok(color == 0x00ffffff, "(478,362) has color %08x\n", color);
540     color = getPixelColor(device, 482, 362);
541     ok(color == 0x00ffffff, "(482,362) has color %08x\n", color);
542
543     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
544     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
545
546     scissor.left = 160;
547     scissor.right = 480;
548     scissor.top = 120;
549     scissor.bottom = 360;
550     hr = IDirect3DDevice9_SetScissorRect(device, &scissor);
551     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %08x\n", hr);
552     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, TRUE);
553     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %08x\n", hr);
554
555     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
556     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
557     hr = IDirect3DDevice9_Clear(device, 1, &rect[1], D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
558     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
559
560     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, FALSE);
561     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %08x\n", hr);
562
563     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
564     color = getPixelColor(device, 158, 118);
565     ok(color == 0x00ffffff, "Pixel 158/118 has color %08x\n", color);
566     color = getPixelColor(device, 162, 118);
567     ok(color == 0x00ffffff, "Pixel 162/118 has color %08x\n", color);
568     color = getPixelColor(device, 158, 122);
569     ok(color == 0x00ffffff, "Pixel 158/122 has color %08x\n", color);
570     color = getPixelColor(device, 162, 122);
571     ok(color == 0x00ff0000, "Pixel 162/122 has color %08x\n", color);
572
573     color = getPixelColor(device, 158, 358);
574     ok(color == 0x00ffffff, "Pixel 158/358 has color %08x\n", color);
575     color = getPixelColor(device, 162, 358);
576     ok(color == 0x0000ff00, "Pixel 162/358 has color %08x\n", color);
577     color = getPixelColor(device, 158, 358);
578     ok(color == 0x00ffffff, "Pixel 158/358 has color %08x\n", color);
579     color = getPixelColor(device, 162, 362);
580     ok(color == 0x00ffffff, "Pixel 162/362 has color %08x\n", color);
581
582     color = getPixelColor(device, 478, 118);
583     ok(color == 0x00ffffff, "Pixel 158/118 has color %08x\n", color);
584     color = getPixelColor(device, 478, 122);
585     ok(color == 0x0000ff00, "Pixel 162/118 has color %08x\n", color);
586     color = getPixelColor(device, 482, 122);
587     ok(color == 0x00ffffff, "Pixel 158/122 has color %08x\n", color);
588     color = getPixelColor(device, 482, 358);
589     ok(color == 0x00ffffff, "Pixel 162/122 has color %08x\n", color);
590
591     color = getPixelColor(device, 478, 358);
592     ok(color == 0x0000ff00, "Pixel 478/358 has color %08x\n", color);
593     color = getPixelColor(device, 478, 362);
594     ok(color == 0x00ffffff, "Pixel 478/118 has color %08x\n", color);
595     color = getPixelColor(device, 482, 358);
596     ok(color == 0x00ffffff, "Pixel 482/122 has color %08x\n", color);
597     color = getPixelColor(device, 482, 362);
598     ok(color == 0x00ffffff, "Pixel 482/122 has color %08x\n", color);
599
600     color = getPixelColor(device, 318, 238);
601     ok(color == 0x00ff0000, "Pixel 318/238 has color %08x\n", color);
602     color = getPixelColor(device, 318, 242);
603     ok(color == 0x0000ff00, "Pixel 318/242 has color %08x\n", color);
604     color = getPixelColor(device, 322, 238);
605     ok(color == 0x0000ff00, "Pixel 322/238 has color %08x\n", color);
606     color = getPixelColor(device, 322, 242);
607     ok(color == 0x0000ff00, "Pixel 322/242 has color %08x\n", color);
608
609     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_COLORWRITEENABLE, &oldColorWrite);
610     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
611     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED);
612     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
613
614     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
615     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
616
617     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, oldColorWrite);
618     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
619
620     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
621
622     /* Colorwriteenable does not affect the clear */
623     color = getPixelColor(device, 320, 240);
624     ok(color == 0x00ffffff, "Color write protected clear returned color %08x\n", color);
625 }
626
627 typedef struct {
628     float in[4];
629     DWORD out;
630 } test_data_t;
631
632 /*
633  *  c7      mova    ARGB            mov     ARGB
634  * -2.4     -2      0x00ffff00      -3      0x00ff0000
635  * -1.6     -2      0x00ffff00      -2      0x00ffff00
636  * -0.4      0      0x0000ffff      -1      0x0000ff00
637  *  0.4      0      0x0000ffff       0      0x0000ffff
638  *  1.6      2      0x00ff00ff       1      0x000000ff
639  *  2.4      2      0x00ff00ff       2      0x00ff00ff
640  */
641 static void test_mova(IDirect3DDevice9 *device)
642 {
643     static const DWORD mova_test[] = {
644         0xfffe0200,                                                             /* vs_2_0                       */
645         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
646         0x05000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0   */
647         0x05000051, 0xa00f0001, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, /* def c1, 1.0, 1.0, 0.0, 1.0   */
648         0x05000051, 0xa00f0002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, /* def c2, 0.0, 1.0, 0.0, 1.0   */
649         0x05000051, 0xa00f0003, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 0.0, 1.0, 1.0, 1.0   */
650         0x05000051, 0xa00f0004, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c4, 0.0, 0.0, 1.0, 1.0   */
651         0x05000051, 0xa00f0005, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, /* def c5, 1.0, 0.0, 1.0, 1.0   */
652         0x05000051, 0xa00f0006, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c6, 1.0, 1.0, 1.0, 1.0   */
653         0x0200002e, 0xb0010000, 0xa0000007,                                     /* mova a0.x, c7.x              */
654         0x03000001, 0xd00f0000, 0xa0e42003, 0xb0000000,                         /* mov oD0, c[a0.x + 3]         */
655         0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
656         0x0000ffff                                                              /* END                          */
657     };
658     static const DWORD mov_test[] = {
659         0xfffe0101,                                                             /* vs_1_1                       */
660         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
661         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0   */
662         0x00000051, 0xa00f0001, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, /* def c1, 1.0, 1.0, 0.0, 1.0   */
663         0x00000051, 0xa00f0002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, /* def c2, 0.0, 1.0, 0.0, 1.0   */
664         0x00000051, 0xa00f0003, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 0.0, 1.0, 1.0, 1.0   */
665         0x00000051, 0xa00f0004, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c4, 0.0, 0.0, 1.0, 1.0   */
666         0x00000051, 0xa00f0005, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, /* def c5, 1.0, 0.0, 1.0, 1.0   */
667         0x00000051, 0xa00f0006, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c6, 1.0, 1.0, 1.0, 1.0   */
668         0x00000001, 0xb0010000, 0xa0000007,                                     /* mov a0.x, c7.x               */
669         0x00000001, 0xd00f0000, 0xa0e42003,                                     /* mov oD0, c[a0.x + 3]         */
670         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
671         0x0000ffff                                                              /* END                          */
672     };
673
674     static const test_data_t test_data[2][6] = {
675         {
676             {{-2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff0000},
677             {{-1.6f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
678             {{-0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ff00},
679             {{ 0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
680             {{ 1.6f, 0.0f, 0.0f, 0.0f}, 0x000000ff},
681             {{ 2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff}
682         },
683         {
684             {{-2.4f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
685             {{-1.6f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
686             {{-0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
687             {{ 0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
688             {{ 1.6f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff},
689             {{ 2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff}
690         }
691     };
692
693     static const float quad[][3] = {
694         {-1.0f, -1.0f, 0.0f},
695         {-1.0f,  1.0f, 0.0f},
696         { 1.0f, -1.0f, 0.0f},
697         { 1.0f,  1.0f, 0.0f},
698     };
699
700     static const D3DVERTEXELEMENT9 decl_elements[] = {
701         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
702         D3DDECL_END()
703     };
704
705     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
706     IDirect3DVertexShader9 *mova_shader = NULL;
707     IDirect3DVertexShader9 *mov_shader = NULL;
708     HRESULT hr;
709     UINT i, j;
710
711     hr = IDirect3DDevice9_CreateVertexShader(device, mova_test, &mova_shader);
712     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
713     hr = IDirect3DDevice9_CreateVertexShader(device, mov_test, &mov_shader);
714     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
715     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
716     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
717     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
718     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
719
720     hr = IDirect3DDevice9_SetVertexShader(device, mov_shader);
721     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
722     for(j = 0; j < 2; ++j)
723     {
724         for (i = 0; i < (sizeof(test_data[0]) / sizeof(test_data_t)); ++i)
725         {
726             DWORD color;
727
728             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 7, test_data[j][i].in, 1);
729             ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
730
731             hr = IDirect3DDevice9_BeginScene(device);
732             ok(SUCCEEDED(hr), "BeginScene failed (%08x)\n", hr);
733
734             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], 3 * sizeof(float));
735             ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
736
737             hr = IDirect3DDevice9_EndScene(device);
738             ok(SUCCEEDED(hr), "EndScene failed (%08x)\n", hr);
739
740             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
741             ok(SUCCEEDED(hr), "Present failed (%08x)\n", hr);
742
743             color = getPixelColor(device, 320, 240);
744             ok(color == test_data[j][i].out, "Expected color %08x, got %08x (for input %f, instruction %s)\n",
745                test_data[j][i].out, color, test_data[j][i].in[0], j == 0 ? "mov" : "mova");
746
747             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
748             ok(SUCCEEDED(hr), "Clear failed (%08x)\n", hr);
749         }
750         hr = IDirect3DDevice9_SetVertexShader(device, mova_shader);
751         ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
752     }
753
754     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
755     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
756
757     IDirect3DVertexDeclaration9_Release(vertex_declaration);
758     IDirect3DVertexShader9_Release(mova_shader);
759     IDirect3DVertexShader9_Release(mov_shader);
760 }
761
762 struct sVertex {
763     float x, y, z;
764     DWORD diffuse;
765     DWORD specular;
766 };
767
768 struct sVertexT {
769     float x, y, z, rhw;
770     DWORD diffuse;
771     DWORD specular;
772 };
773
774 static void fog_test(IDirect3DDevice9 *device)
775 {
776     HRESULT hr;
777     DWORD color;
778     BYTE r, g, b;
779     float start = 0.0f, end = 1.0f;
780     D3DCAPS9 caps;
781     int i;
782
783     /* Gets full z based fog with linear fog, no fog with specular color */
784     struct sVertex unstransformed_1[] = {
785         {-1,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
786         {-1,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
787         { 0,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
788         { 0,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
789     };
790     /* Ok, I am too lazy to deal with transform matrices */
791     struct sVertex unstransformed_2[] = {
792         {-1,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
793         {-1,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
794         { 0,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
795         { 0,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
796     };
797     /* Untransformed ones. Give them a different diffuse color to make the test look
798      * nicer. It also makes making sure that they are drawn correctly easier.
799      */
800     struct sVertexT transformed_1[] = {
801         {320,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
802         {640,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
803         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
804         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
805     };
806     struct sVertexT transformed_2[] = {
807         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
808         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
809         {640,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
810         {320,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
811     };
812     struct vertex rev_fog_quads[] = {
813        {-1.0,   -1.0,   0.1,    0x000000ff},
814        {-1.0,    0.0,   0.1,    0x000000ff},
815        { 0.0,    0.0,   0.1,    0x000000ff},
816        { 0.0,   -1.0,   0.1,    0x000000ff},
817
818        { 0.0,   -1.0,   0.9,    0x000000ff},
819        { 0.0,    0.0,   0.9,    0x000000ff},
820        { 1.0,    0.0,   0.9,    0x000000ff},
821        { 1.0,   -1.0,   0.9,    0x000000ff},
822
823        { 0.0,    0.0,   0.4,    0x000000ff},
824        { 0.0,    1.0,   0.4,    0x000000ff},
825        { 1.0,    1.0,   0.4,    0x000000ff},
826        { 1.0,    0.0,   0.4,    0x000000ff},
827
828        {-1.0,    0.0,   0.7,    0x000000ff},
829        {-1.0,    1.0,   0.7,    0x000000ff},
830        { 0.0,    1.0,   0.7,    0x000000ff},
831        { 0.0,    0.0,   0.7,    0x000000ff},
832     };
833     WORD Indices[] = {0, 1, 2, 2, 3, 0};
834
835     memset(&caps, 0, sizeof(caps));
836     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
837     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %08x\n", hr);
838     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
839     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
840
841     /* Setup initial states: No lighting, fog on, fog color */
842     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
843     ok(hr == D3D_OK, "Turning off lighting returned %08x\n", hr);
844     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
845     ok(hr == D3D_OK, "Turning on fog calculations returned %08x\n", hr);
846     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
847     ok(hr == D3D_OK, "Turning on fog calculations returned %08x\n", hr);
848
849     /* First test: Both table fog and vertex fog off */
850     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
851     ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
852     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
853     ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
854
855     /* Start = 0, end = 1. Should be default, but set them */
856     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
857     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
858     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
859     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
860
861     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
862     {
863         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
864         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
865         /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
866         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
867                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_1,
868                                                      sizeof(unstransformed_1[0]));
869         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
870
871         /* That makes it use the Z value */
872         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
873         ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
874         /* Untransformed, vertex fog != none (or table fog != none):
875          * Use the Z value as input into the equation
876          */
877         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
878                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_2,
879                                                      sizeof(unstransformed_1[0]));
880         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
881
882         /* transformed verts */
883         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
884         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
885         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
886         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
887                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
888                                                      sizeof(transformed_1[0]));
889         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
890
891         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
892         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
893         /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
894          * equation
895          */
896         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
897                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_2,
898                                                      sizeof(transformed_2[0]));
899
900         hr = IDirect3DDevice9_EndScene(device);
901         ok(hr == D3D_OK, "EndScene returned %08x\n", hr);
902     }
903     else
904     {
905         ok(FALSE, "BeginScene failed\n");
906     }
907
908     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
909     color = getPixelColor(device, 160, 360);
910     ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color);
911     color = getPixelColor(device, 160, 120);
912     ok(color == 0x0000FF00 || color == 0x0000FE00, "Untransformed vertex with linear vertex fog has color %08x\n", color);
913     color = getPixelColor(device, 480, 120);
914     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
915     if(caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
916     {
917         color = getPixelColor(device, 480, 360);
918         ok(color == 0x0000FF00 || color == 0x0000FE00, "Transformed vertex with linear table fog has color %08x\n", color);
919     }
920     else
921     {
922         /* Without fog table support the vertex fog is still applied, even though table fog is turned on.
923          * The settings above result in no fogging with vertex fog
924          */
925         color = getPixelColor(device, 480, 120);
926         ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
927         trace("Info: Table fog not supported by this device\n");
928     }
929
930     /* Now test the special case fogstart == fogend */
931     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
932     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
933
934     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
935     {
936         start = 512;
937         end = 512;
938         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
939         ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
940         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
941         ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
942
943         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
944         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
945         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
946         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState %08x\n", hr);
947         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
948         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
949
950         /* Untransformed vertex, z coord = 0.1, fogstart = 512, fogend = 512. Would result in
951          * a completely fog-free primitive because start > zcoord, but because start == end, the primitive
952          * is fully covered by fog. The same happens to the 2nd untransformed quad with z = 1.0.
953          * The third transformed quad remains unfogged because the fogcoords are read from the specular
954          * color and has fixed fogstart and fogend.
955          */
956         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
957                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_1,
958                 sizeof(unstransformed_1[0]));
959         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
960         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
961                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_2,
962                 sizeof(unstransformed_1[0]));
963         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
964
965         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
966         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
967         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
968         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
969                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
970                 sizeof(transformed_1[0]));
971         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
972
973         hr = IDirect3DDevice9_EndScene(device);
974         ok(hr == D3D_OK, "EndScene returned %08x\n", hr);
975     }
976     else
977     {
978         ok(FALSE, "BeginScene failed\n");
979     }
980     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
981     color = getPixelColor(device, 160, 360);
982     ok(color == 0x0000FF00 || color == 0x0000FE00, "Untransformed vertex with vertex fog and z = 0.1 has color %08x\n", color);
983     color = getPixelColor(device, 160, 120);
984     ok(color == 0x0000FF00 || color == 0x0000FE00, "Untransformed vertex with vertex fog and z = 1.0 has color %08x\n", color);
985     color = getPixelColor(device, 480, 120);
986     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
987
988     /* Test "reversed" fog without shaders. With shaders this fails on a few Windows D3D implementations,
989      * but without shaders it seems to work everywhere
990      */
991     end = 0.2;
992     start = 0.8;
993     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
994     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
995     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
996     ok(hr == D3D_OK, "Setting fog end returned %08x\n", hr);
997     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
998     ok( hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
999
1000     /* Test reversed fog without shaders. ATI cards have problems with reversed fog and shaders, so
1001      * it doesn't seem very important for games. ATI cards also have problems with reversed table fog,
1002      * so skip this for now
1003      */
1004     for(i = 0; i < 1 /*2 - Table fog test disabled, fails on ATI */; i++) {
1005         const char *mode = (i ? "table" : "vertex");
1006         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
1007         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
1008         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, i == 0 ? D3DFOG_LINEAR : D3DFOG_NONE);
1009         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1010         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, i == 0 ? D3DFOG_NONE : D3DFOG_LINEAR);
1011         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1012         hr = IDirect3DDevice9_BeginScene(device);
1013         ok( hr == D3D_OK, "IDirect3DDDevice9_BeginScene returned %08x\n", hr);
1014         if(SUCCEEDED(hr)) {
1015             WORD Indices2[] = { 0,  1,  2,  2,  3, 0,
1016                                 4,  5,  6,  6,  7, 4,
1017                                 8,  9, 10, 10, 11, 8,
1018                             12, 13, 14, 14, 15, 12};
1019
1020             hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */,
1021                     16 /* NumVerts */, 8 /*PrimCount */, Indices2, D3DFMT_INDEX16, rev_fog_quads,
1022                     sizeof(rev_fog_quads[0]));
1023
1024             hr = IDirect3DDevice9_EndScene(device);
1025             ok( hr == D3D_OK, "IDirect3DDDevice9_EndScene returned %08x\n", hr);
1026         }
1027         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1028         color = getPixelColor(device, 160, 360);
1029         ok(color == 0x0000FF00 || color == 0x0000FE00, "Reversed %s fog: z=0.1 has color 0x%08x, expected 0x0000ff00\n", mode, color);
1030
1031         color = getPixelColor(device, 160, 120);
1032         r = (color & 0x00ff0000) >> 16;
1033         g = (color & 0x0000ff00) >>  8;
1034         b = (color & 0x000000ff);
1035         ok(r == 0x00 && g >= 0x29 && g <= 0x2d && b >= 0xd2 && b <= 0xd6,
1036            "Reversed %s fog: z=0.7 has color 0x%08x, expected\n", mode, color);
1037
1038         color = getPixelColor(device, 480, 120);
1039         r = (color & 0x00ff0000) >> 16;
1040         g = (color & 0x0000ff00) >>  8;
1041         b = (color & 0x000000ff);
1042         ok(r == 0x00 && g >= 0xa8 && g <= 0xac && b >= 0x53 && b <= 0x57,
1043            "Reversed %s fog: z=0.4 has color 0x%08x, expected\n", mode, color);
1044
1045         color = getPixelColor(device, 480, 360);
1046         ok(color == 0x000000ff, "Reversed %s fog: z=0.9 has color 0x%08x, expected 0x000000ff\n", mode, color);
1047
1048         if(!(caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)) {
1049             skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping reversed table fog test\n");
1050             break;
1051         }
1052     }
1053     /* Turn off the fog master switch to avoid confusing other tests */
1054     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
1055     ok(hr == D3D_OK, "Turning off fog calculations returned %08x\n", hr);
1056     start = 0.0;
1057     end = 1.0;
1058     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
1059     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
1060     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
1061     ok(hr == D3D_OK, "Setting fog end returned %08x\n", hr);
1062     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
1063     ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState %08x\n", hr);
1064     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
1065     ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
1066 }
1067
1068 /* This test verifies the behaviour of cube maps wrt. texture wrapping.
1069  * D3D cube map wrapping always behaves like GL_CLAMP_TO_EDGE,
1070  * regardless of the actual addressing mode set. */
1071 static void test_cube_wrap(IDirect3DDevice9 *device)
1072 {
1073     static const float quad[][6] = {
1074         {-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1075         {-1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1076         { 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1077         { 1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1078     };
1079
1080     static const D3DVERTEXELEMENT9 decl_elements[] = {
1081         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1082         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1083         D3DDECL_END()
1084     };
1085
1086     static const struct {
1087         D3DTEXTUREADDRESS mode;
1088         const char *name;
1089     } address_modes[] = {
1090         {D3DTADDRESS_WRAP, "D3DTADDRESS_WRAP"},
1091         {D3DTADDRESS_MIRROR, "D3DTADDRESS_MIRROR"},
1092         {D3DTADDRESS_CLAMP, "D3DTADDRESS_CLAMP"},
1093         {D3DTADDRESS_BORDER, "D3DTADDRESS_BORDER"},
1094         {D3DTADDRESS_MIRRORONCE, "D3DTADDRESS_MIRRORONCE"},
1095     };
1096
1097     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1098     IDirect3DCubeTexture9 *texture = NULL;
1099     IDirect3DSurface9 *surface = NULL;
1100     D3DLOCKED_RECT locked_rect;
1101     HRESULT hr;
1102     UINT x;
1103     INT y, face;
1104
1105     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1106     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1107     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1108     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1109
1110     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
1111             D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL);
1112     ok(SUCCEEDED(hr), "CreateOffscreenPlainSurface failed (0x%08x)\n", hr);
1113
1114     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
1115     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1116
1117     for (y = 0; y < 128; ++y)
1118     {
1119         DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1120         for (x = 0; x < 64; ++x)
1121         {
1122             *ptr++ = 0xffff0000;
1123         }
1124         for (x = 64; x < 128; ++x)
1125         {
1126             *ptr++ = 0xff0000ff;
1127         }
1128     }
1129
1130     hr = IDirect3DSurface9_UnlockRect(surface);
1131     ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
1132
1133     hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
1134             D3DPOOL_DEFAULT, &texture, NULL);
1135     ok(SUCCEEDED(hr), "CreateCubeTexture failed (0x%08x)\n", hr);
1136
1137     /* Create cube faces */
1138     for (face = 0; face < 6; ++face)
1139     {
1140         IDirect3DSurface9 *face_surface = NULL;
1141
1142         hr= IDirect3DCubeTexture9_GetCubeMapSurface(texture, face, 0, &face_surface);
1143         ok(SUCCEEDED(hr), "GetCubeMapSurface failed (0x%08x)\n", hr);
1144
1145         hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, face_surface, NULL);
1146         ok(SUCCEEDED(hr), "UpdateSurface failed (0x%08x)\n", hr);
1147
1148         IDirect3DSurface9_Release(face_surface);
1149     }
1150
1151     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
1152     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1153
1154     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
1155     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1156     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
1157     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1158     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_BORDERCOLOR, 0xff00ff00);
1159     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_BORDERCOLOR failed (0x%08x)\n", hr);
1160
1161     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1162     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1163
1164     for (x = 0; x < (sizeof(address_modes) / sizeof(*address_modes)); ++x)
1165     {
1166         DWORD color;
1167
1168         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, address_modes[x].mode);
1169         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU (%s) failed (0x%08x)\n", address_modes[x].name, hr);
1170         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, address_modes[x].mode);
1171         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV (%s) failed (0x%08x)\n", address_modes[x].name, hr);
1172
1173         hr = IDirect3DDevice9_BeginScene(device);
1174         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1175
1176         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1177         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
1178
1179         hr = IDirect3DDevice9_EndScene(device);
1180         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1181
1182         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1183         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1184
1185         /* Due to the nature of this test, we sample essentially at the edge
1186          * between two faces. Because of this it's undefined from which face
1187          * the driver will sample. Fortunately that's not important for this
1188          * test, since all we care about is that it doesn't sample from the
1189          * other side of the surface or from the border. */
1190         color = getPixelColor(device, 320, 240);
1191         ok(color == 0x00ff0000 || color == 0x000000ff,
1192                 "Got color 0x%08x for addressing mode %s, expected 0x00ff0000 or 0x000000ff.\n",
1193                 color, address_modes[x].name);
1194
1195         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
1196         ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
1197     }
1198
1199     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1200     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1201
1202     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1203     IDirect3DCubeTexture9_Release(texture);
1204     IDirect3DSurface9_Release(surface);
1205 }
1206
1207 static void offscreen_test(IDirect3DDevice9 *device)
1208 {
1209     HRESULT hr;
1210     IDirect3DTexture9 *offscreenTexture = NULL;
1211     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
1212     DWORD color;
1213
1214     static const float quad[][5] = {
1215         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
1216         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
1217         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
1218         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
1219     };
1220
1221     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
1222     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
1223
1224     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
1225     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %08x\n", hr);
1226     if(!offscreenTexture) {
1227         trace("Failed to create an X8R8G8B8 offscreen texture, trying R5G6B5\n");
1228         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
1229         ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %08x\n", hr);
1230         if(!offscreenTexture) {
1231             skip("Cannot create an offscreen render target\n");
1232             goto out;
1233         }
1234     }
1235
1236     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1237     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
1238     if(!backbuffer) {
1239         goto out;
1240     }
1241
1242     hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
1243     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %08x\n", hr);
1244     if(!offscreen) {
1245         goto out;
1246     }
1247
1248     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
1249     ok(hr == D3D_OK, "SetFVF failed, hr = %08x\n", hr);
1250
1251     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
1252     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
1253     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
1254     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
1255     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
1256     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1257     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
1258     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1259     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1260     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1261
1262     if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
1263         hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
1264         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
1265         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1266         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
1267
1268         /* Draw without textures - Should result in a white quad */
1269         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
1270         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %08x\n", hr);
1271
1272         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
1273         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
1274         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
1275         ok(hr == D3D_OK, "SetTexture failed, %08x\n", hr);
1276
1277         /* This time with the texture */
1278         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
1279         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %08x\n", hr);
1280
1281         IDirect3DDevice9_EndScene(device);
1282     }
1283
1284     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1285
1286     /* Center quad - should be white */
1287     color = getPixelColor(device, 320, 240);
1288     ok(color == 0x00ffffff, "Offscreen failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1289     /* Some quad in the cleared part of the texture */
1290     color = getPixelColor(device, 170, 240);
1291     ok(color == 0x00ff00ff, "Offscreen failed: Got color 0x%08x, expected 0x00ff00ff.\n", color);
1292     /* Part of the originally cleared back buffer */
1293     color = getPixelColor(device, 10, 10);
1294     ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1295     if(0) {
1296         /* Lower left corner of the screen, where back buffer offscreen rendering draws the offscreen texture.
1297          * It should be red, but the offscreen texture may leave some junk there. Not tested yet. Depending on
1298          * the offscreen rendering mode this test would succeed or fail
1299          */
1300         color = getPixelColor(device, 10, 470);
1301         ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1302     }
1303
1304 out:
1305     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1306
1307     /* restore things */
1308     if(backbuffer) {
1309         IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
1310         IDirect3DSurface9_Release(backbuffer);
1311     }
1312     if(offscreenTexture) {
1313         IDirect3DTexture9_Release(offscreenTexture);
1314     }
1315     if(offscreen) {
1316         IDirect3DSurface9_Release(offscreen);
1317     }
1318 }
1319
1320 /* This test tests fog in combination with shaders.
1321  * What's tested: linear fog (vertex and table) with pixel shader
1322  *                linear table fog with non foggy vertex shader
1323  *                vertex fog with foggy vertex shader, non-linear
1324  *                fog with shader, non-linear fog with foggy shader,
1325  *                linear table fog with foggy shader
1326  */
1327 static void fog_with_shader_test(IDirect3DDevice9 *device)
1328 {
1329     HRESULT hr;
1330     DWORD color;
1331     union {
1332         float f;
1333         DWORD i;
1334     } start, end;
1335     unsigned int i, j;
1336
1337     /* basic vertex shader without fog computation ("non foggy") */
1338     static const DWORD vertex_shader_code1[] = {
1339         0xfffe0101,                                                             /* vs_1_1                       */
1340         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
1341         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                */
1342         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
1343         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                  */
1344         0x0000ffff
1345     };
1346     /* basic vertex shader with reversed fog computation ("foggy") */
1347     static const DWORD vertex_shader_code2[] = {
1348         0xfffe0101,                                                             /* vs_1_1                        */
1349         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0               */
1350         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                 */
1351         0x00000051, 0xa00f0000, 0xbfa00000, 0x00000000, 0xbf666666, 0x00000000, /* def c0, -1.25, 0.0, -0.9, 0.0 */
1352         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                  */
1353         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                   */
1354         0x00000002, 0x800f0000, 0x90aa0000, 0xa0aa0000,                         /* add r0, v0.z, c0.z            */
1355         0x00000005, 0xc00f0001, 0x80000000, 0xa0000000,                         /* mul oFog, r0.x, c0.x          */
1356         0x0000ffff
1357     };
1358     /* basic pixel shader */
1359     static const DWORD pixel_shader_code[] = {
1360         0xffff0101,                                                             /* ps_1_1     */
1361         0x00000001, 0x800f0000, 0x90e40000,                                     /* mov r0, vo */
1362         0x0000ffff
1363     };
1364
1365     static struct vertex quad[] = {
1366         {-1.0f, -1.0f,  0.0f,          0xFFFF0000  },
1367         {-1.0f,  1.0f,  0.0f,          0xFFFF0000  },
1368         { 1.0f, -1.0f,  0.0f,          0xFFFF0000  },
1369         { 1.0f,  1.0f,  0.0f,          0xFFFF0000  },
1370     };
1371
1372     static const D3DVERTEXELEMENT9 decl_elements[] = {
1373         {0,  0, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1374         {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
1375         D3DDECL_END()
1376     };
1377
1378     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1379     IDirect3DVertexShader9      *vertex_shader[3]   = {NULL, NULL, NULL};
1380     IDirect3DPixelShader9       *pixel_shader[2]    = {NULL, NULL};
1381
1382     /* This reference data was collected on a nVidia GeForce 7600GS driver version 84.19 DirectX version 9.0c on Windows XP */
1383     static const struct test_data_t {
1384         int vshader;
1385         int pshader;
1386         D3DFOGMODE vfog;
1387         D3DFOGMODE tfog;
1388         unsigned int color[11];
1389     } test_data[] = {
1390         /* only pixel shader: */
1391         {0, 1, D3DFOG_NONE, D3DFOG_LINEAR,
1392         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1393         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1394         {0, 1, D3DFOG_EXP, D3DFOG_LINEAR,
1395         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1396         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1397         {0, 1, D3DFOG_EXP2, D3DFOG_LINEAR,
1398         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1399         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1400         {0, 1, D3DFOG_LINEAR, D3DFOG_NONE,
1401         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1402         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1403         {0, 1, D3DFOG_LINEAR, D3DFOG_LINEAR,
1404         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1405         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1406
1407         /* vertex shader */
1408         {1, 0, D3DFOG_NONE, D3DFOG_NONE,
1409         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1410          0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1411         {1, 0, D3DFOG_NONE, D3DFOG_LINEAR,
1412         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1413         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1414         {1, 0, D3DFOG_EXP, D3DFOG_LINEAR,
1415         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1416         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1417
1418         {1, 0, D3DFOG_EXP2, D3DFOG_LINEAR,
1419         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1420         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1421         {1, 0, D3DFOG_LINEAR, D3DFOG_LINEAR,
1422         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1423         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1424
1425         /* vertex shader and pixel shader */
1426         /* The next 4 tests would read the fog coord output, but it isn't available.
1427          * The result is a fully fogged quad, no matter what the Z coord is. This is on
1428          * a geforce 7400, 97.52 driver, Windows Vista, but probably hardware dependent.
1429          * These tests should be disabled if some other hardware behaves differently
1430          */
1431         {1, 1, D3DFOG_NONE, D3DFOG_NONE,
1432         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1433         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1434         {1, 1, D3DFOG_LINEAR, D3DFOG_NONE,
1435         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1436         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1437         {1, 1, D3DFOG_EXP, D3DFOG_NONE,
1438         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1439         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1440         {1, 1, D3DFOG_EXP2, D3DFOG_NONE,
1441         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1442         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1443
1444         /* These use the Z coordinate with linear table fog */
1445         {1, 1, D3DFOG_NONE, D3DFOG_LINEAR,
1446         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1447         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1448         {1, 1, D3DFOG_EXP, D3DFOG_LINEAR,
1449         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1450         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1451         {1, 1, D3DFOG_EXP2, D3DFOG_LINEAR,
1452         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1453         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1454         {1, 1, D3DFOG_LINEAR, D3DFOG_LINEAR,
1455         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1456         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1457
1458         /* Non-linear table fog without fog coord */
1459         {1, 1, D3DFOG_NONE, D3DFOG_EXP,
1460         {0x00ff0000, 0x00e71800, 0x00d12e00, 0x00bd4200, 0x00ab5400, 0x009b6400,
1461         0x008d7200, 0x007f8000, 0x00738c00, 0x00689700, 0x005ea100}},
1462         {1, 1, D3DFOG_NONE, D3DFOG_EXP2,
1463         {0x00fd0200, 0x00f50200, 0x00f50a00, 0x00e91600, 0x00d92600, 0x00c73800,
1464         0x00b24d00, 0x009c6300, 0x00867900, 0x00728d00, 0x005ea100}},
1465
1466 #if 0  /* FIXME: these fail on GeForce 8500 */
1467         /* foggy vertex shader */
1468         {2, 0, D3DFOG_NONE, D3DFOG_NONE,
1469         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1470          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1471         {2, 0, D3DFOG_EXP, D3DFOG_NONE,
1472         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1473          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1474         {2, 0, D3DFOG_EXP2, D3DFOG_NONE,
1475         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1476          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1477         {2, 0, D3DFOG_LINEAR, D3DFOG_NONE,
1478         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1479          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1480 #endif
1481
1482         /* foggy vertex shader and pixel shader. First 4 tests with vertex fog,
1483          * all using the fixed fog-coord linear fog
1484          */
1485         {2, 1, D3DFOG_NONE, D3DFOG_NONE,
1486         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1487          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1488         {2, 1, D3DFOG_EXP, D3DFOG_NONE,
1489         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1490          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1491         {2, 1, D3DFOG_EXP2, D3DFOG_NONE,
1492         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1493          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1494         {2, 1, D3DFOG_LINEAR, D3DFOG_NONE,
1495         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1496          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1497
1498         /* These use table fog. Here the shader-provided fog coordinate is
1499          * ignored and the z coordinate used instead
1500          */
1501         {2, 1, D3DFOG_NONE, D3DFOG_EXP,
1502         {0x00ff0000, 0x00e71800, 0x00d12e00, 0x00bd4200, 0x00ab5400, 0x009b6400,
1503         0x008d7200, 0x007f8000, 0x00738c00, 0x00689700, 0x005ea100}},
1504         {2, 1, D3DFOG_NONE, D3DFOG_EXP2,
1505         {0x00fd0200, 0x00f50200, 0x00f50a00, 0x00e91600, 0x00d92600, 0x00c73800,
1506         0x00b24d00, 0x009c6300, 0x00867900, 0x00728d00, 0x005ea100}},
1507         {2, 1, D3DFOG_NONE, D3DFOG_LINEAR,
1508         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1509         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1510     };
1511
1512     /* NOTE: changing these values will not affect the tests with foggy vertex shader, as the values are hardcoded in the shader*/
1513     start.f=0.1f;
1514     end.f=0.9f;
1515
1516     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code1, &vertex_shader[1]);
1517     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1518     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code2, &vertex_shader[2]);
1519     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1520     hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader[1]);
1521     ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1522     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1523     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
1524
1525     /* Setup initial states: No lighting, fog on, fog color */
1526     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1527     ok(hr == D3D_OK, "Turning off lighting failed (%08x)\n", hr);
1528     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
1529     ok(hr == D3D_OK, "Turning on fog calculations failed (%08x)\n", hr);
1530     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
1531     ok(hr == D3D_OK, "Setting fog color failed (%08x)\n", hr);
1532     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1533     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1534
1535     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
1536     ok(hr == D3D_OK, "Turning off table fog failed (%08x)\n", hr);
1537     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
1538     ok(hr == D3D_OK, "Turning off vertex fog failed (%08x)\n", hr);
1539
1540     /* Use fogtart = 0.1 and end = 0.9 to test behavior outside the fog transition phase, too*/
1541     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, start.i);
1542     ok(hr == D3D_OK, "Setting fog start failed (%08x)\n", hr);
1543     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, end.i);
1544     ok(hr == D3D_OK, "Setting fog end failed (%08x)\n", hr);
1545
1546     for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++)
1547     {
1548         hr = IDirect3DDevice9_SetVertexShader(device, vertex_shader[test_data[i].vshader]);
1549         ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1550         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader[test_data[i].pshader]);
1551         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1552         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, test_data[i].vfog);
1553         ok( hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1554         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, test_data[i].tfog);
1555         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1556
1557         for(j=0; j < 11; j++)
1558         {
1559             /* Don't use the whole zrange to prevent rounding errors */
1560             quad[0].z = 0.001f + (float)j / 10.02f;
1561             quad[1].z = 0.001f + (float)j / 10.02f;
1562             quad[2].z = 0.001f + (float)j / 10.02f;
1563             quad[3].z = 0.001f + (float)j / 10.02f;
1564
1565             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1566             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
1567
1568             hr = IDirect3DDevice9_BeginScene(device);
1569             ok( hr == D3D_OK, "BeginScene returned failed (%08x)\n", hr);
1570
1571             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1572             ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1573
1574             hr = IDirect3DDevice9_EndScene(device);
1575             ok(hr == D3D_OK, "EndScene failed (%08x)\n", hr);
1576
1577             IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1578
1579             /* As the red and green component are the result of blending use 5% tolerance on the expected value */
1580             color = getPixelColor(device, 128, 240);
1581             ok(color_match(color, test_data[i].color[j], 13),
1582                 "fog vs%i ps%i fvm%i ftm%i %d: got color %08x, expected %08x +-5%%\n",
1583                 test_data[i].vshader, test_data[i].pshader, test_data[i].vfog, test_data[i].tfog, j, color, test_data[i].color[j]);
1584         }
1585     }
1586
1587     /* reset states */
1588     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
1589     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1590     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1591     ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1592     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1593     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1594     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
1595     ok(hr == D3D_OK, "Turning off fog calculations failed (%08x)\n", hr);
1596
1597     IDirect3DVertexShader9_Release(vertex_shader[1]);
1598     IDirect3DVertexShader9_Release(vertex_shader[2]);
1599     IDirect3DPixelShader9_Release(pixel_shader[1]);
1600     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1601 }
1602
1603 static void generate_bumpmap_textures(IDirect3DDevice9 *device) {
1604     unsigned int i, x, y;
1605     HRESULT hr;
1606     IDirect3DTexture9 *texture[2] = {NULL, NULL};
1607     D3DLOCKED_RECT locked_rect;
1608
1609     /* Generate the textures */
1610     for(i=0; i<2; i++)
1611     {
1612         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, i?D3DFMT_A8R8G8B8:D3DFMT_V8U8,
1613                                             D3DPOOL_MANAGED, &texture[i], NULL);
1614         ok(SUCCEEDED(hr), "CreateTexture failed (0x%08x)\n", hr);
1615
1616         hr = IDirect3DTexture9_LockRect(texture[i], 0, &locked_rect, NULL, 0);
1617         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1618         for (y = 0; y < 128; ++y)
1619         {
1620             if(i)
1621             { /* Set up black texture with 2x2 texel white spot in the middle */
1622                 DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1623                 for (x = 0; x < 128; ++x)
1624                 {
1625                     if(y>62 && y<66 && x>62 && x<66)
1626                         *ptr++ = 0xffffffff;
1627                     else
1628                         *ptr++ = 0xff000000;
1629                 }
1630             }
1631             else
1632             { /* Set up a displacement map which points away from the center parallel to the closest axis.
1633                * (if multiplied with bumpenvmat)
1634               */
1635                 WORD *ptr = (WORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1636                 for (x = 0; x < 128; ++x)
1637                 {
1638                     if(abs(x-64)>abs(y-64))
1639                     {
1640                         if(x < 64)
1641                             *ptr++ = 0xc000;
1642                         else
1643                             *ptr++ = 0x4000;
1644                     }
1645                     else
1646                     {
1647                         if(y < 64)
1648                             *ptr++ = 0x0040;
1649                         else
1650                             *ptr++ = 0x00c0;
1651                     }
1652                 }
1653             }
1654         }
1655         hr = IDirect3DTexture9_UnlockRect(texture[i], 0);
1656         ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
1657
1658         hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture[i]);
1659         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1660
1661         /* Disable texture filtering */
1662         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MINFILTER, D3DTEXF_POINT);
1663         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1664         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
1665         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1666
1667         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1668         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU failed (0x%08x)\n", hr);
1669         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1670         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV failed (0x%08x)\n", hr);
1671     }
1672 }
1673
1674 /* test the behavior of the texbem instruction
1675  * with normal 2D and projective 2D textures
1676  */
1677 static void texbem_test(IDirect3DDevice9 *device)
1678 {
1679     HRESULT hr;
1680     DWORD color;
1681     int i;
1682
1683     static const DWORD pixel_shader_code[] = {
1684         0xffff0101,                         /* ps_1_1*/
1685         0x00000042, 0xb00f0000,             /* tex t0*/
1686         0x00000043, 0xb00f0001, 0xb0e40000, /* texbem t1, t0*/
1687         0x00000001, 0x800f0000, 0xb0e40001, /* mov r0, t1*/
1688         0x0000ffff
1689     };
1690     static const DWORD double_texbem_code[] =  {
1691         0xffff0103,                                         /* ps_1_3           */
1692         0x00000042, 0xb00f0000,                             /* tex t0           */
1693         0x00000043, 0xb00f0001, 0xb0e40000,                 /* texbem t1, t0    */
1694         0x00000042, 0xb00f0002,                             /* tex t2           */
1695         0x00000043, 0xb00f0003, 0xb0e40002,                 /* texbem t3, t2    */
1696         0x00000002, 0x800f0000, 0xb0e40001, 0xb0e40003,     /* add r0, t1, t3   */
1697         0x0000ffff                                          /* end              */
1698     };
1699
1700
1701     static const float quad[][7] = {
1702         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f},
1703         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f},
1704         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 1.0f, 0.0f},
1705         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 1.0f, 1.0f},
1706     };
1707     static const float quad_proj[][9] = {
1708         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f,   0.0f,   0.0f, 0.0f, 128.0f},
1709         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f,   0.0f, 128.0f, 0.0f, 128.0f},
1710         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 128.0f,   0.0f, 0.0f, 128.0f},
1711         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 128.0f, 128.0f, 0.0f, 128.0f},
1712     };
1713
1714     static const D3DVERTEXELEMENT9 decl_elements[][4] = { {
1715         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1716         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1717         {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1718         D3DDECL_END()
1719     },{
1720         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1721         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1722         {0, 20, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1723         D3DDECL_END()
1724     } };
1725
1726     /* use asymmetric matrix to test loading */
1727     float bumpenvmat[4] = {0.0,0.5,-0.5,0.0};
1728
1729     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1730     IDirect3DPixelShader9       *pixel_shader       = NULL;
1731     IDirect3DTexture9           *texture            = NULL, *texture1, *texture2;
1732     D3DLOCKED_RECT locked_rect;
1733
1734     generate_bumpmap_textures(device);
1735
1736     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
1737     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
1738     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
1739     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
1740     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
1741
1742     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
1743     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1744
1745     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1746     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
1747
1748     for(i=0; i<2; i++)
1749     {
1750         if(i)
1751         {
1752             hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4|D3DTTFF_PROJECTED);
1753             ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
1754         }
1755
1756         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements[i], &vertex_declaration);
1757         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1758         hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1759         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1760
1761         hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader);
1762         ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1763         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader);
1764         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1765
1766         hr = IDirect3DDevice9_BeginScene(device);
1767         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1768
1769         if(!i)
1770             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1771         else
1772             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad_proj[0], sizeof(quad_proj[0]));
1773         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
1774
1775         hr = IDirect3DDevice9_EndScene(device);
1776         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1777
1778         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1779         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1780
1781         color = getPixelColor(device, 320-32, 240);
1782         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1783         color = getPixelColor(device, 320+32, 240);
1784         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1785         color = getPixelColor(device, 320, 240-32);
1786         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1787         color = getPixelColor(device, 320, 240+32);
1788         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1789
1790         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1791         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1792         IDirect3DPixelShader9_Release(pixel_shader);
1793
1794         hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1795         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1796         IDirect3DVertexDeclaration9_Release(vertex_declaration);
1797     }
1798
1799     /* clean up */
1800     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
1801     ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
1802
1803     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
1804     ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
1805
1806     for(i=0; i<2; i++)
1807     {
1808         hr = IDirect3DDevice9_GetTexture(device, i, (IDirect3DBaseTexture9 **) &texture);
1809         ok(SUCCEEDED(hr), "IDirect3DDevice9_GetTexture failed (0x%08x)\n", hr);
1810         IDirect3DTexture9_Release(texture); /* For the GetTexture */
1811         hr = IDirect3DDevice9_SetTexture(device, i, NULL);
1812         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1813         IDirect3DTexture9_Release(texture);
1814     }
1815
1816     /* Test double texbem */
1817     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_V8U8, D3DPOOL_MANAGED, &texture, NULL);
1818     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed (0x%08x)\n", hr);
1819     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_V8U8, D3DPOOL_MANAGED, &texture1, NULL);
1820     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed (0x%08x)\n", hr);
1821     hr = IDirect3DDevice9_CreateTexture(device, 8, 8, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture2, NULL);
1822     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed (0x%08x)\n", hr);
1823     hr = IDirect3DDevice9_CreatePixelShader(device, double_texbem_code, &pixel_shader);
1824     ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1825
1826     hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
1827     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1828     ((signed char *) locked_rect.pBits)[0] = (-1.0 / 8.0) * 127;
1829     ((signed char *) locked_rect.pBits)[1] = ( 1.0 / 8.0) * 127;
1830
1831     hr = IDirect3DTexture9_UnlockRect(texture, 0);
1832     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1833
1834     hr = IDirect3DTexture9_LockRect(texture1, 0, &locked_rect, NULL, 0);
1835     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1836     ((signed char *) locked_rect.pBits)[0] = (-2.0 / 8.0) * 127;
1837     ((signed char *) locked_rect.pBits)[1] = (-4.0 / 8.0) * 127;
1838     hr = IDirect3DTexture9_UnlockRect(texture1, 0);
1839     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1840
1841     {
1842         /* Some data without any meaning, just to have an 8x8 array to see which element is picked */
1843 #define tex  0x00ff0000
1844 #define tex1 0x0000ff00
1845 #define origin 0x000000ff
1846         static const DWORD pixel_data[] = {
1847             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1848             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1849             0x000000ff, tex1      , 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1850             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1851             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, origin,     0x000000ff, tex       , 0x000000ff,
1852             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1853             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1854             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1855         };
1856 #undef tex1
1857 #undef tex2
1858 #undef origin
1859
1860         hr = IDirect3DTexture9_LockRect(texture2, 0, &locked_rect, NULL, 0);
1861         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1862         for(i = 0; i < 8; i++) {
1863             memcpy(((char *) locked_rect.pBits) + i * locked_rect.Pitch, pixel_data + 8 * i, 8 * sizeof(DWORD));
1864         }
1865         hr = IDirect3DTexture9_UnlockRect(texture2, 0);
1866         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1867     }
1868
1869     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
1870     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1871     hr = IDirect3DDevice9_SetTexture(device, 1, (IDirect3DBaseTexture9 *) texture2);
1872     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1873     hr = IDirect3DDevice9_SetTexture(device, 2, (IDirect3DBaseTexture9 *) texture1);
1874     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1875     hr = IDirect3DDevice9_SetTexture(device, 3, (IDirect3DBaseTexture9 *) texture2);
1876     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1877     hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader);
1878     ok(SUCCEEDED(hr), "Direct3DDevice9_SetPixelShader failed (0x%08x)\n", hr);
1879     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX4);
1880     ok(SUCCEEDED(hr), "Direct3DDevice9_SetPixelShader failed (0x%08x)\n", hr);
1881
1882     bumpenvmat[0] =-1.0;  bumpenvmat[2] =  2.0;
1883     bumpenvmat[1] = 0.0;  bumpenvmat[3] =  0.0;
1884     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
1885     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
1886     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
1887     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
1888
1889     bumpenvmat[0] = 1.5; bumpenvmat[2] =  0.0;
1890     bumpenvmat[1] = 0.0; bumpenvmat[3] =  0.5;
1891     IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
1892     IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
1893     IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
1894     IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
1895
1896     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1897     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1898     hr = IDirect3DDevice9_SetSamplerState(device, 1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1899     hr = IDirect3DDevice9_SetSamplerState(device, 1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1900     hr = IDirect3DDevice9_SetSamplerState(device, 2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1901     hr = IDirect3DDevice9_SetSamplerState(device, 2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1902     hr = IDirect3DDevice9_SetSamplerState(device, 3, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1903     hr = IDirect3DDevice9_SetSamplerState(device, 3, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1904
1905     hr = IDirect3DDevice9_BeginScene(device);
1906     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1907     if(SUCCEEDED(hr)) {
1908         static const float double_quad[] = {
1909             -1.0,   -1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
1910              1.0,   -1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
1911             -1.0,    1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
1912              1.0,    1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
1913         };
1914
1915         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, double_quad, sizeof(float) * 11);
1916         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
1917         hr = IDirect3DDevice9_EndScene(device);
1918         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1919     }
1920     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1921     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1922     color = getPixelColor(device, 320, 240);
1923     ok(color == 0x00ffff00, "double texbem failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
1924
1925     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1926     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1927     hr = IDirect3DDevice9_SetTexture(device, 1, NULL);
1928     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1929     hr = IDirect3DDevice9_SetTexture(device, 2, NULL);
1930     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1931     hr = IDirect3DDevice9_SetTexture(device, 3, NULL);
1932     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1933     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1934     ok(SUCCEEDED(hr), "Direct3DDevice9_SetPixelShader failed (0x%08x)\n", hr);
1935
1936     IDirect3DPixelShader9_Release(pixel_shader);
1937     IDirect3DTexture9_Release(texture);
1938     IDirect3DTexture9_Release(texture1);
1939     IDirect3DTexture9_Release(texture2);
1940 }
1941
1942 static void z_range_test(IDirect3DDevice9 *device)
1943 {
1944     const struct vertex quad[] =
1945     {
1946         {-1.0f,  0.0f,   1.1f,                          0xffff0000},
1947         {-1.0f,  1.0f,   1.1f,                          0xffff0000},
1948         { 1.0f,  0.0f,  -1.1f,                          0xffff0000},
1949         { 1.0f,  1.0f,  -1.1f,                          0xffff0000},
1950     };
1951     const struct vertex quad2[] =
1952     {
1953         {-1.0f,  0.0f,   1.1f,                          0xff0000ff},
1954         {-1.0f,  1.0f,   1.1f,                          0xff0000ff},
1955         { 1.0f,  0.0f,  -1.1f,                          0xff0000ff},
1956         { 1.0f,  1.0f,  -1.1f,                          0xff0000ff},
1957     };
1958
1959     const struct tvertex quad3[] =
1960     {
1961         {    0,   240,   1.1f,  1.0,                    0xffffff00},
1962         {    0,   480,   1.1f,  1.0,                    0xffffff00},
1963         {  640,   240,  -1.1f,  1.0,                    0xffffff00},
1964         {  640,   480,  -1.1f,  1.0,                    0xffffff00},
1965     };
1966     const struct tvertex quad4[] =
1967     {
1968         {    0,   240,   1.1f,  1.0,                    0xff00ff00},
1969         {    0,   480,   1.1f,  1.0,                    0xff00ff00},
1970         {  640,   240,  -1.1f,  1.0,                    0xff00ff00},
1971         {  640,   480,  -1.1f,  1.0,                    0xff00ff00},
1972     };
1973     HRESULT hr;
1974     DWORD color;
1975     IDirect3DVertexShader9 *shader;
1976     IDirect3DVertexDeclaration9 *decl;
1977     D3DCAPS9 caps;
1978     const DWORD shader_code[] = {
1979         0xfffe0101,                                     /* vs_1_1           */
1980         0x0000001f, 0x80000000, 0x900f0000,             /* dcl_position v0  */
1981         0x00000001, 0xc00f0000, 0x90e40000,             /* mov oPos, v0     */
1982         0x00000001, 0xd00f0000, 0xa0e40000,             /* mov oD0, c0      */
1983         0x0000ffff                                      /* end              */
1984     };
1985     static const D3DVERTEXELEMENT9 decl_elements[] = {
1986         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1987         D3DDECL_END()
1988     };
1989     /* Does the Present clear the depth stencil? Clear the depth buffer with some value != 0,
1990      * then call Present. Then clear the color buffer to make sure it has some defined content
1991      * after the Present with D3DSWAPEFFECT_DISCARD. After that draw a plane that is somewhere cut
1992      * by the depth value.
1993      */
1994     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.75, 0);
1995     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
1996     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1997     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4, 0);
1998
1999     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, TRUE);
2000     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2001     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
2002     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2003     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
2004     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2005     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
2006     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2007     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
2008     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
2009
2010     hr = IDirect3DDevice9_BeginScene(device);
2011     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2012     if(hr == D3D_OK)
2013     {
2014         /* Test the untransformed vertex path */
2015         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
2016         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2017         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS);
2018         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2019         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad2, sizeof(quad2[0]));
2020         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2021
2022         /* Test the transformed vertex path */
2023         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2024         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
2025
2026         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad4, sizeof(quad4[0]));
2027         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2028         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
2029         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2030         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad3, sizeof(quad3[0]));
2031         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2032
2033         hr = IDirect3DDevice9_EndScene(device);
2034         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2035     }
2036
2037     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2038     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2039
2040     /* Do not test the exact corner pixels, but go pretty close to them */
2041
2042     /* Clipped because z > 1.0 */
2043     color = getPixelColor(device, 28, 238);
2044     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2045     color = getPixelColor(device, 28, 241);
2046     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2047
2048     /* Not clipped, > z buffer clear value(0.75) */
2049     color = getPixelColor(device, 31, 238);
2050     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2051     color = getPixelColor(device, 31, 241);
2052     ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
2053     color = getPixelColor(device, 100, 238);
2054     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2055     color = getPixelColor(device, 100, 241);
2056     ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
2057
2058     /* Not clipped, < z buffer clear value */
2059     color = getPixelColor(device, 104, 238);
2060     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2061     color = getPixelColor(device, 104, 241);
2062     ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color);
2063     color = getPixelColor(device, 318, 238);
2064     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2065     color = getPixelColor(device, 318, 241);
2066     ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color);
2067
2068     /* Clipped because z < 0.0 */
2069     color = getPixelColor(device, 321, 238);
2070     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2071     color = getPixelColor(device, 321, 241);
2072     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2073
2074     /* Test the shader path */
2075     IDirect3DDevice9_GetDeviceCaps(device, &caps);
2076     if (caps.VertexShaderVersion < D3DVS_VERSION(1, 1)) {
2077         skip("Vertex shaders not supported\n");
2078         goto out;
2079     }
2080     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
2081     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
2082     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
2083     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
2084
2085     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4, 0);
2086
2087     IDirect3DDevice9_SetVertexDeclaration(device, decl);
2088     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
2089     IDirect3DDevice9_SetVertexShader(device, shader);
2090     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
2091
2092     hr = IDirect3DDevice9_BeginScene(device);
2093     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2094     if(hr == D3D_OK)
2095     {
2096         float colorf[] = {1.0, 0.0, 0.0, 1.0};
2097         float colorf2[] = {0.0, 0.0, 1.0, 1.0};
2098         IDirect3DDevice9_SetVertexShaderConstantF(device, 0, colorf, 1);
2099         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
2100         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2101         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS);
2102         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2103         IDirect3DDevice9_SetVertexShaderConstantF(device, 0, colorf2, 1);
2104         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad2, sizeof(quad2[0]));
2105         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2106
2107         hr = IDirect3DDevice9_EndScene(device);
2108         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2109     }
2110
2111     IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2112     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
2113     IDirect3DDevice9_SetVertexShader(device, NULL);
2114     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
2115
2116     IDirect3DVertexDeclaration9_Release(decl);
2117     IDirect3DVertexShader9_Release(shader);
2118
2119     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2120     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2121     /* Z < 1.0 */
2122     color = getPixelColor(device, 28, 238);
2123     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2124
2125     /* 1.0 < z < 0.75 */
2126     color = getPixelColor(device, 31, 238);
2127     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2128     color = getPixelColor(device, 100, 238);
2129     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2130
2131     /* 0.75 < z < 0.0 */
2132     color = getPixelColor(device, 104, 238);
2133     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2134     color = getPixelColor(device, 318, 238);
2135     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2136
2137     /* 0.0 < z */
2138     color = getPixelColor(device, 321, 238);
2139     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2140
2141     out:
2142     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
2143     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2144     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
2145     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2146     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
2147     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2148 }
2149
2150 static void fill_surface(IDirect3DSurface9 *surface, DWORD color)
2151 {
2152     D3DSURFACE_DESC desc;
2153     D3DLOCKED_RECT l;
2154     HRESULT hr;
2155     unsigned int x, y;
2156     DWORD *mem;
2157
2158     memset(&desc, 0, sizeof(desc));
2159     memset(&l, 0, sizeof(l));
2160     hr = IDirect3DSurface9_GetDesc(surface, &desc);
2161     ok(hr == D3D_OK, "IDirect3DSurface9_GetDesc failed with %08x\n", hr);
2162     hr = IDirect3DSurface9_LockRect(surface, &l, NULL, 0);
2163     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed with %08x\n", hr);
2164     if(FAILED(hr)) return;
2165
2166     for(y = 0; y < desc.Height; y++)
2167     {
2168         mem = (DWORD *) ((BYTE *) l.pBits + y * l.Pitch);
2169         for(x = 0; x < l.Pitch / sizeof(DWORD); x++)
2170         {
2171             mem[x] = color;
2172         }
2173     }
2174     hr = IDirect3DSurface9_UnlockRect(surface);
2175     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed with %08x\n", hr);
2176 }
2177
2178 /* This tests a variety of possible StretchRect() situations */
2179 static void stretchrect_test(IDirect3DDevice9 *device)
2180 {
2181     HRESULT hr;
2182     IDirect3DTexture9 *tex_rt32 = NULL, *tex_rt64 = NULL, *tex_rt_dest64 = NULL;
2183     IDirect3DSurface9 *surf_tex_rt32 = NULL, *surf_tex_rt64 = NULL, *surf_tex_rt_dest64 = NULL;
2184     IDirect3DTexture9 *tex32 = NULL, *tex64 = NULL, *tex_dest64 = NULL;
2185     IDirect3DSurface9 *surf_tex32 = NULL, *surf_tex64 = NULL, *surf_tex_dest64 = NULL;
2186     IDirect3DSurface9 *surf_rt32 = NULL, *surf_rt64 = NULL, *surf_rt_dest64 = NULL;
2187     IDirect3DSurface9 *surf_offscreen32 = NULL, *surf_offscreen64 = NULL, *surf_offscreen_dest64 = NULL;
2188     IDirect3DSurface9 *surf_temp32 = NULL, *surf_temp64 = NULL;
2189     IDirect3DSurface9 *orig_rt = NULL;
2190     DWORD color;
2191
2192     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &orig_rt);
2193     ok(hr == D3D_OK, "Can't get render target, hr = %08x\n", hr);
2194     if(!orig_rt) {
2195         goto out;
2196     }
2197
2198     /* Create our temporary surfaces in system memory */
2199     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf_temp32, NULL);
2200     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2201     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf_temp64, NULL);
2202     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2203
2204     /* Create offscreen plain surfaces in D3DPOOL_DEFAULT */
2205     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_offscreen32, NULL);
2206     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2207     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_offscreen64, NULL);
2208     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2209     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_offscreen_dest64, NULL);
2210     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2211
2212     /* Create render target surfaces */
2213     hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &surf_rt32, NULL );
2214     ok(hr == D3D_OK, "Creating the render target surface failed with %08x\n", hr);
2215     hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &surf_rt64, NULL );
2216     ok(hr == D3D_OK, "Creating the render target surface failed with %08x\n", hr);
2217     hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &surf_rt_dest64, NULL );
2218     ok(hr == D3D_OK, "Creating the render target surface failed with %08x\n", hr);
2219
2220     /* Create render target textures */
2221     hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt32, NULL);
2222     ok(hr == D3D_OK, "Creating the render target texture failed with %08x\n", hr);
2223     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt64, NULL);
2224     ok(hr == D3D_OK, "Creating the render target texture failed with %08x\n", hr);
2225     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt_dest64, NULL);
2226     ok(hr == D3D_OK, "Creating the render target texture failed with %08x\n", hr);
2227     if (tex_rt32) {
2228         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt32, 0, &surf_tex_rt32);
2229         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2230     }
2231     if (tex_rt64) {
2232         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt64, 0, &surf_tex_rt64);
2233         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2234     }
2235     if (tex_rt_dest64) {
2236         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt_dest64, 0, &surf_tex_rt_dest64);
2237         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2238     }
2239
2240     /* Create regular textures in D3DPOOL_DEFAULT */
2241     hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex32, NULL);
2242     ok(hr == D3D_OK, "Creating the regular texture failed with %08x\n", hr);
2243     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex64, NULL);
2244     ok(hr == D3D_OK, "Creating the regular texture failed with %08x\n", hr);
2245     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_dest64, NULL);
2246     ok(hr == D3D_OK, "Creating the regular texture failed with %08x\n", hr);
2247     if (tex32) {
2248         hr = IDirect3DTexture9_GetSurfaceLevel(tex32, 0, &surf_tex32);
2249         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2250     }
2251     if (tex64) {
2252         hr = IDirect3DTexture9_GetSurfaceLevel(tex64, 0, &surf_tex64);
2253         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2254     }
2255     if (tex_dest64) {
2256         hr = IDirect3DTexture9_GetSurfaceLevel(tex_dest64, 0, &surf_tex_dest64);
2257         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2258     }
2259
2260     /*********************************************************************
2261      * Tests for when the source parameter is an offscreen plain surface *
2262      *********************************************************************/
2263
2264     /* Fill the offscreen 64x64 surface with green */
2265     if (surf_offscreen64)
2266         fill_surface(surf_offscreen64, 0xff00ff00);
2267
2268     /* offscreenplain ==> offscreenplain, same size */
2269     if(surf_offscreen64 && surf_offscreen_dest64) {
2270         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_offscreen_dest64, NULL, 0);
2271         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2272
2273         if (hr == D3D_OK) {
2274             color = getPixelColorFromSurface(surf_offscreen_dest64, 32, 32);
2275             ok(color == 0xff00ff00, "StretchRect offscreen ==> offscreen same size failed: Got color 0x%08x, expected 0xff00ff00.\n", color);
2276         }
2277     }
2278
2279     /* offscreenplain ==> rendertarget texture, same size */
2280     if(surf_offscreen64 && surf_tex_rt_dest64 && surf_temp64) {
2281         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_tex_rt_dest64, NULL, 0);
2282         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2283
2284         /* We can't lock rendertarget textures, so copy to our temp surface first */
2285         if (hr == D3D_OK) {
2286             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2287             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2288         }
2289
2290         if (hr == D3D_OK) {
2291             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2292             ok(color == 0xff00ff00, "StretchRect offscreen ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xff00ff00.\n", color);
2293         }
2294     }
2295
2296     /* offscreenplain ==> rendertarget surface, same size */
2297     if(surf_offscreen64 && surf_rt_dest64) {
2298         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_rt_dest64, NULL, 0);
2299         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2300
2301         if (hr == D3D_OK) {
2302             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2303             ok(color == 0xff00ff00, "StretchRect offscreen ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xff00ff00.\n", color);
2304         }
2305     }
2306
2307     /* offscreenplain ==> texture, same size (should fail) */
2308     if(surf_offscreen64 && surf_tex_dest64) {
2309         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_tex_dest64, NULL, 0);
2310         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2311     }
2312
2313     /* Fill the smaller offscreen surface with red */
2314     fill_surface(surf_offscreen32, 0xffff0000);
2315
2316     /* offscreenplain ==> offscreenplain, scaling (should fail) */
2317     if(surf_offscreen32 && surf_offscreen64) {
2318         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_offscreen64, NULL, 0);
2319         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2320     }
2321
2322     /* offscreenplain ==> rendertarget texture, scaling */
2323     if(surf_offscreen32 && surf_tex_rt_dest64 && surf_temp64) {
2324         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_tex_rt_dest64, NULL, 0);
2325         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2326
2327         /* We can't lock rendertarget textures, so copy to our temp surface first */
2328         if (hr == D3D_OK) {
2329             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2330             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2331         }
2332
2333         if (hr == D3D_OK) {
2334             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2335             ok(color == 0xffff0000, "StretchRect offscreen ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2336         }
2337     }
2338
2339     /* offscreenplain ==> rendertarget surface, scaling */
2340     if(surf_offscreen32 && surf_rt_dest64) {
2341         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_rt_dest64, NULL, 0);
2342         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2343
2344         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2345         ok(color == 0xffff0000, "StretchRect offscreen ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2346     }
2347
2348     /* offscreenplain ==> texture, scaling (should fail) */
2349     if(surf_offscreen32 && surf_tex_dest64) {
2350         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_tex_dest64, NULL, 0);
2351         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2352     }
2353
2354     /************************************************************
2355      * Tests for when the source parameter is a regular texture *
2356      ************************************************************/
2357
2358     /* Fill the surface of the regular texture with blue */
2359     if (surf_tex64 && surf_temp64) {
2360         /* Can't fill the surf_tex directly because it's created in D3DPOOL_DEFAULT */
2361         fill_surface(surf_temp64, 0xff0000ff);
2362         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp64, NULL, surf_tex64, NULL);
2363         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
2364     }
2365
2366     /* texture ==> offscreenplain, same size */
2367     if(surf_tex64 && surf_offscreen64) {
2368         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_offscreen64, NULL, 0);
2369         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2370     }
2371
2372     /* texture ==> rendertarget texture, same size */
2373     if(surf_tex64 && surf_tex_rt_dest64 && surf_temp64) {
2374         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_tex_rt_dest64, NULL, 0);
2375         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2376
2377         /* We can't lock rendertarget textures, so copy to our temp surface first */
2378         if (hr == D3D_OK) {
2379             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2380             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2381         }
2382
2383         if (hr == D3D_OK) {
2384             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2385             ok(color == 0xff0000ff, "StretchRect texture ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xff0000ff.\n", color);
2386         }
2387     }
2388
2389     /* texture ==> rendertarget surface, same size */
2390     if(surf_tex64 && surf_rt_dest64) {
2391         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_rt_dest64, NULL, 0);
2392         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2393
2394         if (hr == D3D_OK) {
2395             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2396             ok(color == 0xff0000ff, "StretchRect texture ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xff0000ff.\n", color);
2397         }
2398     }
2399
2400     /* texture ==> texture, same size (should fail) */
2401     if(surf_tex64 && surf_tex_dest64) {
2402         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_tex_dest64, NULL, 0);
2403         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2404     }
2405
2406     /* Fill the surface of the smaller regular texture with red */
2407     if (surf_tex32 && surf_temp32) {
2408         /* Can't fill the surf_tex directly because it's created in D3DPOOL_DEFAULT */
2409         fill_surface(surf_temp32, 0xffff0000);
2410         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp32, NULL, surf_tex32, NULL);
2411         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
2412     }
2413
2414     /* texture ==> offscreenplain, scaling (should fail) */
2415     if(surf_tex32 && surf_offscreen64) {
2416         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_offscreen64, NULL, 0);
2417         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2418     }
2419
2420     /* texture ==> rendertarget texture, scaling */
2421     if(surf_tex32 && surf_tex_rt_dest64 && surf_temp64) {
2422         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_tex_rt_dest64, NULL, 0);
2423         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2424
2425         /* We can't lock rendertarget textures, so copy to our temp surface first */
2426         if (hr == D3D_OK) {
2427             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2428             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2429         }
2430
2431         if (hr == D3D_OK) {
2432             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2433             ok(color == 0xffff0000, "StretchRect texture ==> rendertarget texture scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2434         }
2435     }
2436
2437     /* texture ==> rendertarget surface, scaling */
2438     if(surf_tex32 && surf_rt_dest64) {
2439         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_rt_dest64, NULL, 0);
2440         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2441
2442         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2443         ok(color == 0xffff0000, "StretchRect texture ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2444     }
2445
2446     /* texture ==> texture, scaling (should fail) */
2447     if(surf_tex32 && surf_tex_dest64) {
2448         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_tex_dest64, NULL, 0);
2449         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2450     }
2451
2452     /*****************************************************************
2453      * Tests for when the source parameter is a rendertarget texture *
2454      *****************************************************************/
2455
2456     /* Fill the surface of the rendertarget texture with white */
2457     if (surf_tex_rt64 && surf_temp64) {
2458         /* Can't fill the surf_tex_rt directly because it's created in D3DPOOL_DEFAULT */
2459         fill_surface(surf_temp64, 0xffffffff);
2460         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp64, NULL, surf_tex_rt64, NULL);
2461         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
2462     }
2463
2464     /* rendertarget texture ==> offscreenplain, same size */
2465     if(surf_tex_rt64 && surf_offscreen64) {
2466         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_offscreen64, NULL, 0);
2467         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2468     }
2469
2470     /* rendertarget texture ==> rendertarget texture, same size */
2471     if(surf_tex_rt64 && surf_tex_rt_dest64 && surf_temp64) {
2472         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_tex_rt_dest64, NULL, 0);
2473         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2474
2475         /* We can't lock rendertarget textures, so copy to our temp surface first */
2476         if (hr == D3D_OK) {
2477             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2478             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2479         }
2480
2481         if (hr == D3D_OK) {
2482             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2483             ok(color == 0xffffffff, "StretchRect rendertarget texture ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xffffffff.\n", color);
2484         }
2485     }
2486
2487     /* rendertarget texture ==> rendertarget surface, same size */
2488     if(surf_tex_rt64 && surf_rt_dest64) {
2489         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_rt_dest64, NULL, 0);
2490         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2491
2492         if (hr == D3D_OK) {
2493             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2494             ok(color == 0xffffffff, "StretchRect rendertarget texture ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xffffffff.\n", color);
2495         }
2496     }
2497
2498     /* rendertarget texture ==> texture, same size (should fail) */
2499     if(surf_tex_rt64 && surf_tex_dest64) {
2500         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_tex_dest64, NULL, 0);
2501         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2502     }
2503
2504     /* Fill the surface of the smaller rendertarget texture with red */
2505     if (surf_tex_rt32 && surf_temp32) {
2506         /* Can't fill the surf_tex_rt directly because it's created in D3DPOOL_DEFAULT */
2507         fill_surface(surf_temp32, 0xffff0000);
2508         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp32, NULL, surf_tex_rt32, NULL);
2509         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
2510     }
2511
2512     /* rendertarget texture ==> offscreenplain, scaling (should fail) */
2513     if(surf_tex_rt32 && surf_offscreen64) {
2514         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_offscreen64, NULL, 0);
2515         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2516     }
2517
2518     /* rendertarget texture ==> rendertarget texture, scaling */
2519     if(surf_tex_rt32 && surf_tex_rt_dest64 && surf_temp64) {
2520         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_tex_rt_dest64, NULL, 0);
2521         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2522
2523         /* We can't lock rendertarget textures, so copy to our temp surface first */
2524         if (hr == D3D_OK) {
2525             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2526             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2527         }
2528
2529         if (hr == D3D_OK) {
2530             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2531             ok(color == 0xffff0000, "StretchRect rendertarget texture ==> rendertarget texture scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2532         }
2533     }
2534
2535     /* rendertarget texture ==> rendertarget surface, scaling */
2536     if(surf_tex_rt32 && surf_rt_dest64) {
2537         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_rt_dest64, NULL, 0);
2538         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2539
2540         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2541         ok(color == 0xffff0000, "StretchRect rendertarget texture ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2542     }
2543
2544     /* rendertarget texture ==> texture, scaling (should fail) */
2545     if(surf_tex_rt32 && surf_tex_dest64) {
2546         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_tex_dest64, NULL, 0);
2547         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2548     }
2549
2550     /*****************************************************************
2551      * Tests for when the source parameter is a rendertarget surface *
2552      *****************************************************************/
2553
2554     /* Fill the surface of the rendertarget surface with black */
2555     if (surf_rt64)
2556         fill_surface(surf_rt64, 0xff000000);
2557
2558     /* rendertarget texture ==> offscreenplain, same size */
2559     if(surf_rt64 && surf_offscreen64) {
2560         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_offscreen64, NULL, 0);
2561         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2562     }
2563
2564     /* rendertarget surface ==> rendertarget texture, same size */
2565     if(surf_rt64 && surf_tex_rt_dest64 && surf_temp64) {
2566         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_tex_rt_dest64, NULL, 0);
2567         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2568
2569         /* We can't lock rendertarget textures, so copy to our temp surface first */
2570         if (hr == D3D_OK) {
2571             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2572             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2573         }
2574
2575         if (hr == D3D_OK) {
2576             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2577             ok(color == 0xff000000, "StretchRect rendertarget surface ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xff000000.\n", color);
2578         }
2579     }
2580
2581     /* rendertarget surface ==> rendertarget surface, same size */
2582     if(surf_rt64 && surf_rt_dest64) {
2583         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_rt_dest64, NULL, 0);
2584         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2585
2586         if (hr == D3D_OK) {
2587             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2588             ok(color == 0xff000000, "StretchRect rendertarget surface ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xff000000.\n", color);
2589         }
2590     }
2591
2592     /* rendertarget surface ==> texture, same size (should fail) */
2593     if(surf_rt64 && surf_tex_dest64) {
2594         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_tex_dest64, NULL, 0);
2595         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2596     }
2597
2598     /* Fill the surface of the smaller rendertarget texture with red */
2599     if (surf_rt32)
2600         fill_surface(surf_rt32, 0xffff0000);
2601
2602     /* rendertarget surface ==> offscreenplain, scaling (should fail) */
2603     if(surf_rt32 && surf_offscreen64) {
2604         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_offscreen64, NULL, 0);
2605         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2606     }
2607
2608     /* rendertarget surface ==> rendertarget texture, scaling */
2609     if(surf_rt32 && surf_tex_rt_dest64 && surf_temp64) {
2610         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_tex_rt_dest64, NULL, 0);
2611         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2612
2613         /* We can't lock rendertarget textures, so copy to our temp surface first */
2614         if (hr == D3D_OK) {
2615             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2616             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2617         }
2618
2619         if (hr == D3D_OK) {
2620             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2621             ok(color == 0xffff0000, "StretchRect rendertarget surface ==> rendertarget texture scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2622         }
2623     }
2624
2625     /* rendertarget surface ==> rendertarget surface, scaling */
2626     if(surf_rt32 && surf_rt_dest64) {
2627         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_rt_dest64, NULL, 0);
2628         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2629
2630         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2631         ok(color == 0xffff0000, "StretchRect rendertarget surface ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2632     }
2633
2634     /* rendertarget surface ==> texture, scaling (should fail) */
2635     if(surf_rt32 && surf_tex_dest64) {
2636         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_tex_dest64, NULL, 0);
2637         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2638     }
2639
2640     /* TODO: Test when source and destination RECT parameters are given... */
2641     /* TODO: Test format conversions */
2642
2643
2644 out:
2645     /* Clean up */
2646     if (surf_rt32)
2647         IDirect3DSurface9_Release(surf_rt32);
2648     if (surf_rt64)
2649         IDirect3DSurface9_Release(surf_rt64);
2650     if (surf_rt_dest64)
2651         IDirect3DSurface9_Release(surf_rt_dest64);
2652     if (surf_temp32)
2653         IDirect3DSurface9_Release(surf_temp32);
2654     if (surf_temp64)
2655         IDirect3DSurface9_Release(surf_temp64);
2656     if (surf_offscreen32)
2657         IDirect3DSurface9_Release(surf_offscreen32);
2658     if (surf_offscreen64)
2659         IDirect3DSurface9_Release(surf_offscreen64);
2660     if (surf_offscreen_dest64)
2661         IDirect3DSurface9_Release(surf_offscreen_dest64);
2662
2663     if (tex_rt32) {
2664         if (surf_tex_rt32)
2665             IDirect3DSurface9_Release(surf_tex_rt32);
2666         IDirect3DTexture9_Release(tex_rt32);
2667     }
2668     if (tex_rt64) {
2669         if (surf_tex_rt64)
2670             IDirect3DSurface9_Release(surf_tex_rt64);
2671         IDirect3DTexture9_Release(tex_rt64);
2672     }
2673     if (tex_rt_dest64) {
2674         if (surf_tex_rt_dest64)
2675             IDirect3DSurface9_Release(surf_tex_rt_dest64);
2676         IDirect3DTexture9_Release(tex_rt_dest64);
2677     }
2678     if (tex32) {
2679         if (surf_tex32)
2680             IDirect3DSurface9_Release(surf_tex32);
2681         IDirect3DTexture9_Release(tex32);
2682     }
2683     if (tex64) {
2684         if (surf_tex64)
2685             IDirect3DSurface9_Release(surf_tex64);
2686         IDirect3DTexture9_Release(tex64);
2687     }
2688     if (tex_dest64) {
2689         if (surf_tex_dest64)
2690             IDirect3DSurface9_Release(surf_tex_dest64);
2691         IDirect3DTexture9_Release(tex_dest64);
2692     }
2693
2694     if (orig_rt) {
2695         hr = IDirect3DDevice9_SetRenderTarget(device, 0, orig_rt);
2696         ok(hr == D3D_OK, "IDirect3DSetRenderTarget failed with %08x\n", hr);
2697         IDirect3DSurface9_Release(orig_rt);
2698     }
2699 }
2700
2701 static void maxmip_test(IDirect3DDevice9 *device)
2702 {
2703     IDirect3DTexture9 *texture = NULL;
2704     IDirect3DSurface9 *surface = NULL;
2705     HRESULT hr;
2706     DWORD color;
2707     const float quads[] = {
2708         -1.0,   -1.0,   0.0,    0.0,    0.0,
2709         -1.0,    0.0,   0.0,    0.0,    1.0,
2710          0.0,   -1.0,   0.0,    1.0,    0.0,
2711          0.0,    0.0,   0.0,    1.0,    1.0,
2712
2713          0.0,   -1.0,   0.0,    0.0,    0.0,
2714          0.0,    0.0,   0.0,    0.0,    1.0,
2715          1.0,   -1.0,   0.0,    1.0,    0.0,
2716          1.0,    0.0,   0.0,    1.0,    1.0,
2717
2718          0.0,    0.0,   0.0,    0.0,    0.0,
2719          0.0,    1.0,   0.0,    0.0,    1.0,
2720          1.0,    0.0,   0.0,    1.0,    0.0,
2721          1.0,    1.0,   0.0,    1.0,    1.0,
2722
2723         -1.0,    0.0,   0.0,    0.0,    0.0,
2724         -1.0,    1.0,   0.0,    0.0,    1.0,
2725          0.0,    0.0,   0.0,    1.0,    0.0,
2726          0.0,    1.0,   0.0,    1.0,    1.0,
2727     };
2728
2729     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
2730     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
2731
2732     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
2733                                         &texture, NULL);
2734     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
2735     if(!texture)
2736     {
2737         skip("Failed to create test texture\n");
2738         return;
2739     }
2740
2741     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
2742     fill_surface(surface, 0xffff0000);
2743     IDirect3DSurface9_Release(surface);
2744     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface);
2745     fill_surface(surface, 0xff00ff00);
2746     IDirect3DSurface9_Release(surface);
2747     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
2748     fill_surface(surface, 0xff0000ff);
2749     IDirect3DSurface9_Release(surface);
2750
2751     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
2752     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
2753     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2754     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
2755
2756     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
2757     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2758
2759     hr = IDirect3DDevice9_BeginScene(device);
2760     if(SUCCEEDED(hr))
2761     {
2762         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
2763         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2764         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[ 0], 5 * sizeof(float));
2765         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2766
2767         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
2768         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2769         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[20], 5 * sizeof(float));
2770         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2771
2772         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
2773         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2774         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[40], 5 * sizeof(float));
2775         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2776
2777         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
2778         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2779         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[60], 5 * sizeof(float));
2780         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2781         hr = IDirect3DDevice9_EndScene(device);
2782     }
2783
2784     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2785     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2786     /* With mipmapping disabled, the max mip level is ignored, only level 0 is used */
2787     color = getPixelColor(device, 160, 360);
2788     ok(color == 0x00FF0000, "MapMip 0, no mipfilter has color %08x\n", color);
2789     color = getPixelColor(device, 160, 120);
2790     ok(color == 0x00FF0000, "MapMip 3, no mipfilter has color %08x\n", color);
2791     color = getPixelColor(device, 480, 120);
2792     ok(color == 0x00FF0000, "MapMip 2, no mipfilter has color %08x\n", color);
2793     color = getPixelColor(device, 480, 360);
2794     ok(color == 0x00FF0000, "MapMip 1, no mipfilter has color %08x\n", color);
2795
2796     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
2797     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
2798
2799     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
2800     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2801
2802     hr = IDirect3DDevice9_BeginScene(device);
2803     if(SUCCEEDED(hr))
2804     {
2805         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
2806         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2807         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[ 0], 5 * sizeof(float));
2808         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2809
2810         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
2811         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2812         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[20], 5 * sizeof(float));
2813         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2814
2815         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
2816         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2817         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[40], 5 * sizeof(float));
2818         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2819
2820         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
2821         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2822         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[60], 5 * sizeof(float));
2823         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2824         hr = IDirect3DDevice9_EndScene(device);
2825     }
2826
2827     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
2828     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2829     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
2830     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2831
2832     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2833     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2834     /* Max Mip level 0-2 sample from the specified texture level, Max Mip level 3(> levels in texture)
2835      * samples from the highest level in the texture(level 2)
2836      */
2837     color = getPixelColor(device, 160, 360);
2838     ok(color == 0x00FF0000, "MapMip 0, point mipfilter has color %08x\n", color);
2839     color = getPixelColor(device, 160, 120);
2840     ok(color == 0x000000FF, "MapMip 3, point mipfilter has color %08x\n", color);
2841     color = getPixelColor(device, 480, 120);
2842     ok(color == 0x000000FF, "MapMip 2, point mipfilter has color %08x\n", color);
2843     color = getPixelColor(device, 480, 360);
2844     ok(color == 0x0000FF00, "MapMip 1, point mipfilter has color %08x\n", color);
2845
2846     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
2847     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
2848     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
2849     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
2850     IDirect3DTexture9_Release(texture);
2851 }
2852
2853 static void release_buffer_test(IDirect3DDevice9 *device)
2854 {
2855     IDirect3DVertexBuffer9 *vb = NULL;
2856     IDirect3DIndexBuffer9 *ib = NULL;
2857     HRESULT hr;
2858     BYTE *data;
2859     long ref;
2860
2861     static const struct vertex quad[] = {
2862         {-1.0,      -1.0,       0.1,        0xffff0000},
2863         {-1.0,       1.0,       0.1,        0xffff0000},
2864         { 1.0,       1.0,       0.1,        0xffff0000},
2865
2866         {-1.0,      -1.0,       0.1,        0xff00ff00},
2867         {-1.0,       1.0,       0.1,        0xff00ff00},
2868         { 1.0,       1.0,       0.1,        0xff00ff00}
2869     };
2870     short indices[] = {3, 4, 5};
2871
2872     /* Index and vertex buffers should always be creatable */
2873     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, D3DFVF_XYZ | D3DFVF_DIFFUSE,
2874                                               D3DPOOL_MANAGED, &vb, NULL);
2875     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
2876     if(!vb) {
2877         skip("Failed to create a vertex buffer\n");
2878         return;
2879     }
2880     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, NULL);
2881     ok(hr == D3D_OK, "IDirect3DDevice9_CreateIndexBuffer failed with %08x\n", hr);
2882     if(!ib) {
2883         skip("Failed to create an index buffer\n");
2884         return;
2885     }
2886
2887     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), (void **) &data, 0);
2888     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
2889     memcpy(data, quad, sizeof(quad));
2890     hr = IDirect3DVertexBuffer9_Unlock(vb);
2891     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
2892
2893     hr = IDirect3DIndexBuffer9_Lock(ib, 0, sizeof(indices), (void **) &data, 0);
2894     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Lock failed with %08x\n", hr);
2895     memcpy(data, indices, sizeof(indices));
2896     hr = IDirect3DIndexBuffer9_Unlock(ib);
2897     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
2898
2899     hr = IDirect3DDevice9_SetIndices(device, ib);
2900     ok(hr == D3D_OK, "IDirect3DDevice9_SetIndices failed with %08x\n", hr);
2901     hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad[0]));
2902     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
2903     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
2904     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
2905
2906     /* Now destroy the bound index buffer and draw again */
2907     ref = IDirect3DIndexBuffer9_Release(ib);
2908     ok(ref == 0, "Index Buffer reference count is %08ld\n", ref);
2909
2910     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
2911     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2912
2913     hr = IDirect3DDevice9_BeginScene(device);
2914     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2915     if(SUCCEEDED(hr))
2916     {
2917         /* Deliberately using minvertexindex = 0 and numVertices = 6 to prevent d3d from
2918          * making assumptions about the indices or vertices
2919          */
2920         hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 3, 3, 0, 1);
2921         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitive failed with %08x\n", hr);
2922         hr = IDirect3DDevice9_EndScene(device);
2923         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2924     }
2925
2926     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2927     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
2928
2929     hr = IDirect3DDevice9_SetIndices(device, NULL);
2930     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
2931     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2932     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
2933
2934     /* Index buffer was already destroyed as part of the test */
2935     IDirect3DVertexBuffer9_Release(vb);
2936 }
2937
2938 static void float_texture_test(IDirect3DDevice9 *device)
2939 {
2940     IDirect3D9 *d3d = NULL;
2941     HRESULT hr;
2942     IDirect3DTexture9 *texture = NULL;
2943     D3DLOCKED_RECT lr;
2944     float *data;
2945     DWORD color;
2946     float quad[] = {
2947         -1.0,      -1.0,       0.1,     0.0,    0.0,
2948         -1.0,       1.0,       0.1,     0.0,    1.0,
2949          1.0,      -1.0,       0.1,     1.0,    0.0,
2950          1.0,       1.0,       0.1,     1.0,    1.0,
2951     };
2952
2953     memset(&lr, 0, sizeof(lr));
2954     IDirect3DDevice9_GetDirect3D(device, &d3d);
2955     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
2956                                      D3DRTYPE_TEXTURE, D3DFMT_R32F) != D3D_OK) {
2957         skip("D3DFMT_R32F textures not supported\n");
2958         goto out;
2959     }
2960
2961     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_R32F,
2962                                         D3DPOOL_MANAGED, &texture, NULL);
2963     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
2964     if(!texture) {
2965         skip("Failed to create R32F texture\n");
2966         goto out;
2967     }
2968
2969     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
2970     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %08x\n", hr);
2971     data = lr.pBits;
2972     *data = 0.0;
2973     hr = IDirect3DTexture9_UnlockRect(texture, 0);
2974     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %08x\n", hr);
2975
2976     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
2977     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
2978
2979     hr = IDirect3DDevice9_BeginScene(device);
2980     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2981     if(SUCCEEDED(hr))
2982     {
2983         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2984         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
2985
2986         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
2987         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2988
2989         hr = IDirect3DDevice9_EndScene(device);
2990         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2991     }
2992     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
2993     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
2994
2995     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2996     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
2997
2998     color = getPixelColor(device, 240, 320);
2999     ok(color == 0x0000FFFF, "R32F with value 0.0 has color %08x, expected 0x0000FFFF\n", color);
3000
3001 out:
3002     if(texture) IDirect3DTexture9_Release(texture);
3003     IDirect3D9_Release(d3d);
3004 }
3005
3006 static void g16r16_texture_test(IDirect3DDevice9 *device)
3007 {
3008     IDirect3D9 *d3d = NULL;
3009     HRESULT hr;
3010     IDirect3DTexture9 *texture = NULL;
3011     D3DLOCKED_RECT lr;
3012     DWORD *data;
3013     DWORD color, red, green, blue;
3014     float quad[] = {
3015        -1.0,      -1.0,       0.1,     0.0,    0.0,
3016        -1.0,       1.0,       0.1,     0.0,    1.0,
3017         1.0,      -1.0,       0.1,     1.0,    0.0,
3018         1.0,       1.0,       0.1,     1.0,    1.0,
3019     };
3020
3021     memset(&lr, 0, sizeof(lr));
3022     IDirect3DDevice9_GetDirect3D(device, &d3d);
3023     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
3024        D3DRTYPE_TEXTURE, D3DFMT_G16R16) != D3D_OK) {
3025            skip("D3DFMT_G16R16 textures not supported\n");
3026            goto out;
3027     }
3028
3029     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_G16R16,
3030                                         D3DPOOL_MANAGED, &texture, NULL);
3031     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
3032     if(!texture) {
3033         skip("Failed to create D3DFMT_G16R16 texture\n");
3034         goto out;
3035     }
3036
3037     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
3038     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %08x\n", hr);
3039     data = lr.pBits;
3040     *data = 0x0f00f000;
3041     hr = IDirect3DTexture9_UnlockRect(texture, 0);
3042     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %08x\n", hr);
3043
3044     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3045     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3046
3047     hr = IDirect3DDevice9_BeginScene(device);
3048     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3049     if(SUCCEEDED(hr))
3050     {
3051         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3052         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3053
3054         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
3055         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3056
3057         hr = IDirect3DDevice9_EndScene(device);
3058         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3059     }
3060     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3061     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3062
3063     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3064     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3065
3066     color = getPixelColor(device, 240, 320);
3067     red   = (color & 0x00ff0000) >> 16;
3068     green = (color & 0x0000ff00) >>  8;
3069     blue  = (color & 0x000000ff) >>  0;
3070     ok(blue == 0xff && red >= 0xef && red <= 0xf1 && green >= 0x0e && green <= 0x10,
3071        "D3DFMT_G16R16 with value 0x00ffff00 has color %08x, expected 0x00F00FFF\n", color);
3072
3073 out:
3074     if(texture) IDirect3DTexture9_Release(texture);
3075     IDirect3D9_Release(d3d);
3076 }
3077
3078 static void texture_transform_flags_test(IDirect3DDevice9 *device)
3079 {
3080     HRESULT hr;
3081     IDirect3D9 *d3d;
3082     D3DFORMAT fmt = D3DFMT_X8R8G8B8;
3083     D3DCAPS9 caps;
3084     IDirect3DTexture9 *texture = NULL;
3085     IDirect3DVolumeTexture9 *volume = NULL;
3086     unsigned int x, y, z;
3087     D3DLOCKED_RECT lr;
3088     D3DLOCKED_BOX lb;
3089     DWORD color;
3090     UINT w, h;
3091     IDirect3DVertexDeclaration9 *decl, *decl2, *decl3;
3092     float identity[16] = {1.0, 0.0, 0.0, 0.0,
3093                            0.0, 1.0, 0.0, 0.0,
3094                            0.0, 0.0, 1.0, 0.0,
3095                            0.0, 0.0, 0.0, 1.0};
3096     static const D3DVERTEXELEMENT9 decl_elements[] = {
3097         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3098         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3099         D3DDECL_END()
3100     };
3101     static const D3DVERTEXELEMENT9 decl_elements2[] = {
3102         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3103         {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3104         D3DDECL_END()
3105     };
3106     static const D3DVERTEXELEMENT9 decl_elements3[] = {
3107         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3108         {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3109         D3DDECL_END()
3110     };
3111     static const unsigned char proj_texdata[] = {0x00, 0x00, 0x00, 0x00,
3112                                                  0x00, 0xff, 0x00, 0x00,
3113                                                  0x00, 0x00, 0x00, 0x00,
3114                                                  0x00, 0x00, 0x00, 0x00};
3115
3116     memset(&lr, 0, sizeof(lr));
3117     memset(&lb, 0, sizeof(lb));
3118     IDirect3DDevice9_GetDirect3D(device, &d3d);
3119     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
3120                                      D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16) == D3D_OK) {
3121         fmt = D3DFMT_A16B16G16R16;
3122     }
3123     IDirect3D9_Release(d3d);
3124
3125     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
3126     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
3127     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements2, &decl2);
3128     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
3129     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements3, &decl3);
3130     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
3131     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, FALSE);
3132     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_SRGBTEXTURE) returned %08x\n", hr);
3133     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
3134     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MAGFILTER) returned %08x\n", hr);
3135     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
3136     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MINFILTER) returned %08x\n", hr);
3137     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
3138     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MIPFILTER) returned %08x\n", hr);
3139     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
3140     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSU) returned %08x\n", hr);
3141     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
3142     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSV) returned %08x\n", hr);
3143     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP);
3144     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSW) returned %08x\n", hr);
3145     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
3146     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState(D3DRS_LIGHTING) returned %08x\n", hr);
3147     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
3148     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3149
3150     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3151     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %08x\n", hr);
3152     w = min(1024, caps.MaxTextureWidth);
3153     h = min(1024, caps.MaxTextureHeight);
3154     hr = IDirect3DDevice9_CreateTexture(device, w, h, 1,
3155                                         0, fmt, D3DPOOL_MANAGED, &texture, NULL);
3156     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
3157     if(!texture) {
3158         skip("Failed to create the test texture\n");
3159         return;
3160     }
3161
3162     /* Unfortunately there is no easy way to set up a texture coordinate passthrough
3163      * in d3d fixed function pipeline, so create a texture that has a gradient from 0.0 to
3164      * 1.0 in red and green for the x and y coords
3165      */
3166     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
3167     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %08x\n", hr);
3168     for(y = 0; y < h; y++) {
3169         for(x = 0; x < w; x++) {
3170             double r_f = (double) y / (double) h;
3171             double g_f = (double) x / (double) w;
3172             if(fmt == D3DFMT_A16B16G16R16) {
3173                 unsigned short r, g;
3174                 unsigned short *dst = (unsigned short *) (((char *) lr.pBits) + y * lr.Pitch + x * 8);
3175                 r = (unsigned short) (r_f * 65536.0);
3176                 g = (unsigned short) (g_f * 65536.0);
3177                 dst[0] = r;
3178                 dst[1] = g;
3179                 dst[2] = 0;
3180                 dst[3] = 65535;
3181             } else {
3182                 unsigned char *dst = ((unsigned char *) lr.pBits) + y * lr.Pitch + x * 4;
3183                 unsigned char r = (unsigned char) (r_f * 255.0);
3184                 unsigned char g = (unsigned char) (g_f * 255.0);
3185                 dst[0] = 0;
3186                 dst[1] = g;
3187                 dst[2] = r;
3188                 dst[3] = 255;
3189             }
3190         }
3191     }
3192     hr = IDirect3DTexture9_UnlockRect(texture, 0);
3193     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect returned %08x\n", hr);
3194     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3195     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
3196
3197     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3198     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3199     hr = IDirect3DDevice9_BeginScene(device);
3200     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3201     if(SUCCEEDED(hr))
3202     {
3203         float quad1[] = {
3204             -1.0,      -1.0,       0.1,     1.0,    1.0,
3205             -1.0,       0.0,       0.1,     1.0,    1.0,
3206              0.0,      -1.0,       0.1,     1.0,    1.0,
3207              0.0,       0.0,       0.1,     1.0,    1.0,
3208         };
3209         float quad2[] = {
3210             -1.0,       0.0,       0.1,     1.0,    1.0,
3211             -1.0,       1.0,       0.1,     1.0,    1.0,
3212              0.0,       0.0,       0.1,     1.0,    1.0,
3213              0.0,       1.0,       0.1,     1.0,    1.0,
3214         };
3215         float quad3[] = {
3216              0.0,       0.0,       0.1,     0.5,    0.5,
3217              0.0,       1.0,       0.1,     0.5,    0.5,
3218              1.0,       0.0,       0.1,     0.5,    0.5,
3219              1.0,       1.0,       0.1,     0.5,    0.5,
3220         };
3221         float quad4[] = {
3222              320,       480,       0.1,     1.0,    0.0,    1.0,
3223              320,       240,       0.1,     1.0,    0.0,    1.0,
3224              640,       480,       0.1,     1.0,    0.0,    1.0,
3225              640,       240,       0.1,     1.0,    0.0,    1.0,
3226         };
3227         float mat[16] = {0.0, 0.0, 0.0, 0.0,
3228                           0.0, 0.0, 0.0, 0.0,
3229                           0.0, 0.0, 0.0, 0.0,
3230                           0.0, 0.0, 0.0, 0.0};
3231
3232         /* What happens with the texture matrix if D3DTSS_TEXTURETRANSFORMFLAGS is disabled? */
3233         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3234         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3235         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
3236         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3237
3238         /* What happens with transforms enabled? */
3239         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3240         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3241         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
3242         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3243
3244         /* What happens if 4 coords are used, but only 2 given ?*/
3245         mat[8] = 1.0;
3246         mat[13] = 1.0;
3247         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3248         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3249         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
3250         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3251         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
3252         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3253
3254         /* What happens with transformed geometry? This setup lead to 0/0 coords with untransformed
3255          * geometry. If the same applies to transformed vertices, the quad will be black, otherwise red,
3256          * due to the coords in the vertices. (turns out red, indeed)
3257          */
3258         memset(mat, 0, sizeof(mat));
3259         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3260         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3261         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_TEX1);
3262         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3263         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3264         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3265         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
3266         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3267
3268         hr = IDirect3DDevice9_EndScene(device);
3269         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3270     }
3271     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3272     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3273     color = getPixelColor(device, 160, 360);
3274     ok(color == 0x00FFFF00 || color == 0x00FEFE00, "quad 1 has color %08x, expected 0x00FFFF00\n", color);
3275     color = getPixelColor(device, 160, 120);
3276     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
3277     color = getPixelColor(device, 480, 120);
3278     ok(color == 0x0000FF00 || color == 0x0000FE00, "quad 3 has color %08x, expected 0x0000FF00\n", color);
3279     color = getPixelColor(device, 480, 360);
3280     ok(color == 0x00FF0000 || 0x00FE0000, "quad 4 has color %08x, expected 0x00FF0000\n", color);
3281
3282     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
3283     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3284
3285     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3286     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3287     hr = IDirect3DDevice9_BeginScene(device);
3288     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3289     if(SUCCEEDED(hr))
3290     {
3291         float quad1[] = {
3292             -1.0,      -1.0,       0.1,     0.8,    0.2,
3293             -1.0,       0.0,       0.1,     0.8,    0.2,
3294              0.0,      -1.0,       0.1,     0.8,    0.2,
3295              0.0,       0.0,       0.1,     0.8,    0.2,
3296         };
3297         float quad2[] = {
3298             -1.0,       0.0,       0.1,     0.5,    1.0,
3299             -1.0,       1.0,       0.1,     0.5,    1.0,
3300              0.0,       0.0,       0.1,     0.5,    1.0,
3301              0.0,       1.0,       0.1,     0.5,    1.0,
3302         };
3303         float quad3[] = {
3304              0.0,       0.0,       0.1,     0.5,    1.0,
3305              0.0,       1.0,       0.1,     0.5,    1.0,
3306              1.0,       0.0,       0.1,     0.5,    1.0,
3307              1.0,       1.0,       0.1,     0.5,    1.0,
3308         };
3309         float quad4[] = {
3310              0.0,      -1.0,       0.1,     0.8,    0.2,
3311              0.0,       0.0,       0.1,     0.8,    0.2,
3312              1.0,      -1.0,       0.1,     0.8,    0.2,
3313              1.0,       0.0,       0.1,     0.8,    0.2,
3314         };
3315         float mat[16] = {0.0, 0.0, 0.0, 0.0,
3316                           0.0, 0.0, 0.0, 0.0,
3317                           0.0, 1.0, 0.0, 0.0,
3318                           0.0, 0.0, 0.0, 0.0};
3319
3320         /* What happens to the default 1 in the 3rd coordinate if it is disabled?
3321          */
3322         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3323         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3324         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3325         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3326
3327         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
3328         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3329
3330         /* D3DTFF_COUNT1 does not work on Nvidia drivers. It behaves like D3DTTFF_DISABLE. On ATI drivers
3331          * it behaves like COUNT2 because normal textures require 2 coords
3332          */
3333         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
3334         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3335         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 5 * sizeof(float));
3336         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3337
3338         /* Just to be sure, the same as quad2 above */
3339         memset(mat, 0, sizeof(mat));
3340         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3341         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3342         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3343         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3344         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
3345         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3346
3347         /* Now, what happens to the 2nd coordinate(that is disabled in the matrix) if it is not
3348          * used? And what happens to the first?
3349          */
3350         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
3351         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3352         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
3353         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3354
3355         hr = IDirect3DDevice9_EndScene(device);
3356         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3357     }
3358     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3359     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3360     color = getPixelColor(device, 160, 360);
3361     ok(color == 0x00FF0000 || color == 0x00FE0000, "quad 1 has color %08x, expected 0x00FF0000\n", color);
3362     color = getPixelColor(device, 160, 120);
3363     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
3364     color = getPixelColor(device, 480, 120);
3365     ok(color == 0x00ff8000 || color == 0x00fe7f00 || color == 0x00000000,
3366        "quad 3 has color %08x, expected 0x00ff8000\n", color);
3367     color = getPixelColor(device, 480, 360);
3368     ok(color == 0x0033cc00 || color == 0x0032cb00 || color == 0x00FF0000 || color == 0x00FE0000,
3369        "quad 4 has color %08x, expected 0x0033cc00\n", color);
3370
3371     IDirect3DTexture9_Release(texture);
3372
3373     /* Test projected textures, without any fancy matrices */
3374     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff203040, 0.0, 0);
3375     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3376     hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_L8, D3DPOOL_MANAGED, &texture, NULL);
3377     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
3378     hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &identity);
3379     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3380     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl3);
3381     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
3382
3383     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
3384     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %08x\n", hr);
3385     for(x = 0; x < 4; x++) {
3386         memcpy(((BYTE *) lr.pBits) + lr.Pitch * x, proj_texdata + 4 * x, 4 * sizeof(proj_texdata[0]));
3387     }
3388     hr = IDirect3DTexture9_UnlockRect(texture, 0);
3389     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %08x\n", hr);
3390     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3391     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3392
3393     hr = IDirect3DDevice9_BeginScene(device);
3394     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3395     if(SUCCEEDED(hr))
3396     {
3397         const float proj_quads[] = {
3398            -1.0,   -1.0,    0.1,    0.0,    0.0,    4.0,    6.0,
3399             1.0,   -1.0,    0.1,    4.0,    0.0,    4.0,    6.0,
3400            -1.0,    0.0,    0.1,    0.0,    4.0,    4.0,    6.0,
3401             1.0,    0.0,    0.1,    4.0,    4.0,    4.0,    6.0,
3402            -1.0,    0.0,    0.1,    0.0,    0.0,    4.0,    6.0,
3403             1.0,    0.0,    0.1,    4.0,    0.0,    4.0,    6.0,
3404            -1.0,    1.0,    0.1,    0.0,    4.0,    4.0,    6.0,
3405             1.0,    1.0,    0.1,    4.0,    4.0,    4.0,    6.0,
3406         };
3407
3408         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4 | D3DTTFF_PROJECTED);
3409         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3410         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &proj_quads[0*7], 7 * sizeof(float));
3411         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3412
3413         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3 | D3DTTFF_PROJECTED);
3414         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3415         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &proj_quads[4*7], 7 * sizeof(float));
3416         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3417
3418         hr = IDirect3DDevice9_EndScene(device);
3419         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3420     }
3421
3422     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3423     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3424     IDirect3DTexture9_Release(texture);
3425
3426     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3427     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3428     color = getPixelColor(device, 158, 118);
3429     ok(color == 0x00000000, "proj: Pixel 158/118 has color 0x%08x, expected 0x00000000\n", color);
3430     color = getPixelColor(device, 162, 118);
3431     ok(color == 0x00000000, "proj: Pixel 162/118 has color 0x%08x, expected 0x00000000\n", color);
3432     color = getPixelColor(device, 158, 122);
3433     ok(color == 0x00000000, "proj: Pixel 158/122 has color 0x%08x, expected 0x00000000\n", color);
3434     color = getPixelColor(device, 162, 122);
3435     ok(color == 0x00FFFFFF, "proj: Pixel 162/122 has color 0x%08x, expected 0x00FFFFFF\n", color);
3436
3437     color = getPixelColor(device, 158, 178);
3438     ok(color == 0x00000000, "proj: Pixel 158/178 has color 0x%08x, expected 0x00000000\n", color);
3439     color = getPixelColor(device, 162, 178);
3440     ok(color == 0x00FFFFFF, "proj: Pixel 158/178 has color 0x%08x, expected 0x00FFFFFF\n", color);
3441     color = getPixelColor(device, 158, 182);
3442     ok(color == 0x00000000, "proj: Pixel 158/182 has color 0x%08x, expected 0x00000000\n", color);
3443     color = getPixelColor(device, 162, 182);
3444     ok(color == 0x00000000, "proj: Pixel 158/182 has color 0x%08x, expected 0x00000000\n", color);
3445
3446     color = getPixelColor(device, 318, 118);
3447     ok(color == 0x00000000, "proj: Pixel 318/118 has color 0x%08x, expected 0x00000000\n", color);
3448     color = getPixelColor(device, 322, 118);
3449     ok(color == 0x00000000, "proj: Pixel 322/118 has color 0x%08x, expected 0x00000000\n", color);
3450     color = getPixelColor(device, 318, 122);
3451     ok(color == 0x00FFFFFF, "proj: Pixel 318/122 has color 0x%08x, expected 0x00FFFFFF\n", color);
3452     color = getPixelColor(device, 322, 122);
3453     ok(color == 0x00000000, "proj: Pixel 322/122 has color 0x%08x, expected 0x00000000\n", color);
3454
3455     color = getPixelColor(device, 318, 178);
3456     ok(color == 0x00FFFFFF, "proj: Pixel 318/178 has color 0x%08x, expected 0x00FFFFFF\n", color);
3457     color = getPixelColor(device, 322, 178);
3458     ok(color == 0x00000000, "proj: Pixel 322/178 has color 0x%08x, expected 0x00000000\n", color);
3459     color = getPixelColor(device, 318, 182);
3460     ok(color == 0x00000000, "proj: Pixel 318/182 has color 0x%08x, expected 0x00000000\n", color);
3461     color = getPixelColor(device, 322, 182);
3462     ok(color == 0x00000000, "proj: Pixel 322/182 has color 0x%08x, expected 0x00000000\n", color);
3463
3464     color = getPixelColor(device, 238, 298);
3465     ok(color == 0x00000000, "proj: Pixel 238/298 has color 0x%08x, expected 0x00000000\n", color);
3466     color = getPixelColor(device, 242, 298);
3467     ok(color == 0x00000000, "proj: Pixel 242/298 has color 0x%08x, expected 0x00000000\n", color);
3468     color = getPixelColor(device, 238, 302);
3469     ok(color == 0x00000000, "proj: Pixel 238/302 has color 0x%08x, expected 0x00000000\n", color);
3470     color = getPixelColor(device, 242, 302);
3471     ok(color == 0x00FFFFFF, "proj: Pixel 242/302 has color 0x%08x, expected 0x00FFFFFF\n", color);
3472
3473     color = getPixelColor(device, 238, 388);
3474     ok(color == 0x00000000, "proj: Pixel 238/388 has color 0x%08x, expected 0x00000000\n", color);
3475     color = getPixelColor(device, 242, 388);
3476     ok(color == 0x00FFFFFF, "proj: Pixel 242/388 has color 0x%08x, expected 0x00FFFFFF\n", color);
3477     color = getPixelColor(device, 238, 392);
3478     ok(color == 0x00000000, "proj: Pixel 238/392 has color 0x%08x, expected 0x00000000\n", color);
3479     color = getPixelColor(device, 242, 392);
3480     ok(color == 0x00000000, "proj: Pixel 242/392 has color 0x%08x, expected 0x00000000\n", color);
3481
3482     color = getPixelColor(device, 478, 298);
3483     ok(color == 0x00000000, "proj: Pixel 478/298 has color 0x%08x, expected 0x00000000\n", color);
3484     color = getPixelColor(device, 482, 298);
3485     ok(color == 0x00000000, "proj: Pixel 482/298 has color 0x%08x, expected 0x00000000\n", color);
3486     color = getPixelColor(device, 478, 302);
3487     ok(color == 0x00FFFFFF, "proj: Pixel 478/302 has color 0x%08x, expected 0x00FFFFFF\n", color);
3488     color = getPixelColor(device, 482, 302);
3489     ok(color == 0x00000000, "proj: Pixel 482/302 has color 0x%08x, expected 0x00000000\n", color);
3490
3491     color = getPixelColor(device, 478, 388);
3492     ok(color == 0x00FFFFFF, "proj: Pixel 478/388 has color 0x%08x, expected 0x00FFFFFF\n", color);
3493     color = getPixelColor(device, 482, 388);
3494     ok(color == 0x00000000, "proj: Pixel 482/388 has color 0x%08x, expected 0x00000000\n", color);
3495     color = getPixelColor(device, 478, 392);
3496     ok(color == 0x00000000, "proj: Pixel 478/392 has color 0x%08x, expected 0x00000000\n", color);
3497     color = getPixelColor(device, 482, 392);
3498     ok(color == 0x00000000, "proj: Pixel 482/392 has color 0x%08x, expected 0x00000000\n", color);
3499
3500     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff203040, 0.0, 0);
3501     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3502     /* Use a smaller volume texture than the biggest possible size for memory and performance reasons
3503      * Thus watch out if sampling from texels between 0 and 1.
3504      */
3505     hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 32, 1, 0, fmt, D3DPOOL_MANAGED, &volume, 0);
3506     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
3507        "IDirect3DDevice9_CreateVolumeTexture failed with %08x\n", hr);
3508     if(!volume) {
3509         skip("Failed to create a volume texture\n");
3510         goto out;
3511     }
3512
3513     hr = IDirect3DVolumeTexture9_LockBox(volume, 0, &lb, NULL, 0);
3514     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_LockBox failed with %08x\n", hr);
3515     for(z = 0; z < 32; z++) {
3516         for(y = 0; y < 32; y++) {
3517             for(x = 0; x < 32; x++) {
3518                 char size = (fmt == D3DFMT_A16B16G16R16 ? 8 : 4);
3519                 void *mem = ((char *)  lb.pBits) + y * lb.RowPitch + z * lb.SlicePitch + x * size;
3520                 float r_f = (float) x / 31.0;
3521                 float g_f = (float) y / 31.0;
3522                 float b_f = (float) z / 31.0;
3523
3524                 if(fmt == D3DFMT_A16B16G16R16) {
3525                     unsigned short *mem_s = mem;
3526                     mem_s[0]  = r_f * 65535.0;
3527                     mem_s[1]  = g_f * 65535.0;
3528                     mem_s[2]  = b_f * 65535.0;
3529                     mem_s[3]  = 65535;
3530                 } else {
3531                     unsigned char *mem_c = mem;
3532                     mem_c[0]  = b_f * 255.0;
3533                     mem_c[1]  = g_f * 255.0;
3534                     mem_c[2]  = r_f * 255.0;
3535                     mem_c[3]  = 255;
3536                 }
3537             }
3538         }
3539     }
3540     hr = IDirect3DVolumeTexture9_UnlockBox(volume, 0);
3541     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %08x\n", hr);
3542
3543     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) volume);
3544     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %08x\n", hr);
3545
3546     hr = IDirect3DDevice9_BeginScene(device);
3547     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3548     if(SUCCEEDED(hr))
3549     {
3550         float quad1[] = {
3551             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3552             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
3553              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3554              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
3555         };
3556         float quad2[] = {
3557             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
3558             -1.0,       1.0,       0.1,     1.0,    1.0,    1.0,
3559              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
3560              0.0,       1.0,       0.1,     1.0,    1.0,    1.0
3561         };
3562         float quad3[] = {
3563              0.0,       0.0,       0.1,     0.0,    0.0,
3564              0.0,       1.0,       0.1,     0.0,    0.0,
3565              1.0,       0.0,       0.1,     0.0,    0.0,
3566              1.0,       1.0,       0.1,     0.0,    0.0
3567         };
3568         float quad4[] = {
3569              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3570              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
3571              1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3572              1.0,       0.0,       0.1,     1.0,    1.0,    1.0
3573         };
3574         float mat[16] = {1.0, 0.0, 0.0, 0.0,
3575                          0.0, 0.0, 1.0, 0.0,
3576                          0.0, 1.0, 0.0, 0.0,
3577                          0.0, 0.0, 0.0, 1.0};
3578         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3579         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
3580
3581         /* Draw a quad with all 3 coords enabled. Nothing fancy. v and w are swapped, but have the same
3582          * values
3583          */
3584         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
3585         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3586         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
3587         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3588         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
3589         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3590
3591         /* Now disable the w coordinate. Does that change the input, or the output. The coordinates
3592          * are swapped by the matrix. If it changes the input, the v coord will be missing(green),
3593          * otherwise the w will be missing(blue).
3594          * turns out that on nvidia cards the blue color is missing, so it is an output modification.
3595          * On ATI cards the COUNT2 is ignored, and it behaves in the same way as COUNT3.
3596          */
3597         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3598         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3599         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
3600         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3601
3602         /* default values? Set up the identity matrix, pass in 2 vertex coords, and enable 4 */
3603         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
3604         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3605         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
3606         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3607         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3608         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3609         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
3610         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3611
3612         /* D3DTTFF_COUNT1. Set a NULL matrix, and count1, pass in all values as 1.0. Nvidia has count1 ==
3613          * disable. ATI extends it up to the amount of values needed for the volume texture
3614          */
3615         memset(mat, 0, sizeof(mat));
3616         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
3617         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3618         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
3619         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3620         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3621         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
3622         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
3623         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3624
3625         hr = IDirect3DDevice9_EndScene(device);
3626         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3627     }
3628     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3629     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3630
3631     color = getPixelColor(device, 160, 360);
3632     ok(color == 0x00ffffff, "quad 1 has color %08x, expected 0x00ffffff\n", color);
3633     color = getPixelColor(device, 160, 120);
3634     ok(color == 0x00ffff00 /* NV*/ || color == 0x00ffffff /* ATI */,
3635        "quad 2 has color %08x, expected 0x00ffff00\n", color);
3636     color = getPixelColor(device, 480, 120);
3637     ok(color == 0x000000ff, "quad 3 has color %08x, expected 0x000000ff\n", color);
3638     color = getPixelColor(device, 480, 360);
3639     ok(color == 0x00ffffff || color == 0x0000ff00, "quad 4 has color %08x, expected 0x00ffffff\n", color);
3640
3641     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff303030, 0.0, 0);
3642     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3643     hr = IDirect3DDevice9_BeginScene(device);
3644     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3645     if(SUCCEEDED(hr))
3646     {
3647         float quad1[] = {
3648             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3649             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
3650              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3651              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
3652         };
3653         float quad2[] = {
3654             -1.0,       0.0,       0.1,
3655             -1.0,       1.0,       0.1,
3656              0.0,       0.0,       0.1,
3657              0.0,       1.0,       0.1,
3658         };
3659         float quad3[] = {
3660              0.0,       0.0,       0.1,     1.0,
3661              0.0,       1.0,       0.1,     1.0,
3662              1.0,       0.0,       0.1,     1.0,
3663              1.0,       1.0,       0.1,     1.0
3664         };
3665         float mat[16] =  {0.0, 0.0, 0.0, 0.0,
3666                            0.0, 0.0, 0.0, 0.0,
3667                            0.0, 0.0, 0.0, 0.0,
3668                            0.0, 1.0, 0.0, 0.0};
3669         float mat2[16] = {0.0, 0.0, 0.0, 1.0,
3670                            1.0, 0.0, 0.0, 0.0,
3671                            0.0, 1.0, 0.0, 0.0,
3672                            0.0, 0.0, 1.0, 0.0};
3673         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3674         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
3675
3676         /* Default values? 4 coords used, 3 passed. What happens to the 4th?
3677          */
3678         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
3679         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3680         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
3681         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3682         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
3683         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3684
3685         /* None passed */
3686         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
3687         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3688         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
3689         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3690         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
3691         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3692
3693         /* 4 used, 1 passed */
3694         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl2);
3695         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
3696         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat2);
3697         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3698         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 4 * sizeof(float));
3699         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3700
3701         hr = IDirect3DDevice9_EndScene(device);
3702         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3703     }
3704     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3705     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3706     color = getPixelColor(device, 160, 360);
3707     ok(color == 0x0000ff00, "quad 1 has color %08x, expected 0x0000ff00\n", color);
3708     color = getPixelColor(device, 160, 120);
3709     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x00000000\n", color);
3710     color = getPixelColor(device, 480, 120);
3711     ok(color == 0x00ff0000, "quad 3 has color %08x, expected 0x00ff0000\n", color);
3712     /* Quad4: unused */
3713
3714     IDirect3DVolumeTexture9_Release(volume);
3715
3716     out:
3717     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
3718     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
3719     IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
3720     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3721     hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &identity);
3722     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3723     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3724     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
3725     IDirect3DVertexDeclaration9_Release(decl);
3726     IDirect3DVertexDeclaration9_Release(decl2);
3727     IDirect3DVertexDeclaration9_Release(decl3);
3728 }
3729
3730 static void texdepth_test(IDirect3DDevice9 *device)
3731 {
3732     IDirect3DPixelShader9 *shader;
3733     HRESULT hr;
3734     const float texdepth_test_data1[] = { 0.25,  2.0, 0.0, 0.0};
3735     const float texdepth_test_data2[] = { 0.25,  0.5, 0.0, 0.0};
3736     const float texdepth_test_data3[] = {-1.00,  0.1, 0.0, 0.0};
3737     const float texdepth_test_data4[] = {-0.25, -0.5, 0.0, 0.0};
3738     const float texdepth_test_data5[] = { 1.00, -0.1, 0.0, 0.0};
3739     const float texdepth_test_data6[] = { 1.00,  0.5, 0.0, 0.0};
3740     const float texdepth_test_data7[] = { 0.50,  0.0, 0.0, 0.0};
3741     DWORD shader_code[] = {
3742         0xffff0104,                                                                 /* ps_1_4               */
3743         0x00000051, 0xa00f0001, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000,     /* def c1, 0, 0, 1, 1   */
3744         0x00000001, 0x800f0005, 0xa0e40000,                                         /* mov r5, c0           */
3745         0x0000fffd,                                                                 /* phase                */
3746         0x00000057, 0x800f0005,                                                     /* texdepth r5          */
3747         0x00000001, 0x800f0000, 0xa0e40001,                                         /* mov r0, c1           */
3748         0x0000ffff                                                                  /* end                  */
3749     };
3750     DWORD color;
3751     float vertex[] = {
3752        -1.0,   -1.0,    0.0,
3753         1.0,   -1.0,    1.0,
3754        -1.0,    1.0,    0.0,
3755         1.0,    1.0,    1.0
3756     };
3757
3758     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
3759     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
3760
3761     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffff00, 0.0, 0);
3762     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3763     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
3764     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
3765     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
3766     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
3767     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
3768     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
3769     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
3770
3771     /* Fill the depth buffer with a gradient */
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         hr = IDirect3DDevice9_EndScene(device);
3779         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3780     }
3781
3782     /* Now perform the actual tests. Same geometry, but with the shader */
3783     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
3784     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
3785     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
3786     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
3787     hr = IDirect3DDevice9_SetPixelShader(device, shader);
3788     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
3789
3790     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data1, 1);
3791     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
3792     hr = IDirect3DDevice9_BeginScene(device);
3793     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3794     if(SUCCEEDED(hr))
3795     {
3796         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3797         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3798
3799         hr = IDirect3DDevice9_EndScene(device);
3800         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3801     }
3802
3803     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3804     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3805     color = getPixelColor(device, 158, 240);
3806     ok(color == 0x000000ff, "Pixel 158(25%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
3807     color = getPixelColor(device, 162, 240);
3808     ok(color == 0x00ffffff, "Pixel 158(25%% + 2 pixel) has color %08x, expected 0x00ffffff\n", color);
3809
3810     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
3811
3812     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data2, 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
3825     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3826     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3827     color = getPixelColor(device, 318, 240);
3828     ok(color == 0x000000ff, "Pixel 318(50%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
3829     color = getPixelColor(device, 322, 240);
3830     ok(color == 0x00ffff00, "Pixel 322(50%% + 2 pixel) has color %08x, expected 0x00ffff00\n", color);
3831
3832     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
3833
3834     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data3, 1);
3835     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
3836     hr = IDirect3DDevice9_BeginScene(device);
3837     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3838     if(SUCCEEDED(hr))
3839     {
3840         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3841         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3842
3843         hr = IDirect3DDevice9_EndScene(device);
3844         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3845     }
3846     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3847     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3848
3849     color = getPixelColor(device, 1, 240);
3850     ok(color == 0x00ff0000, "Pixel 1(0%% + 2 pixel) has color %08x, expected 0x00ff0000\n", color);
3851
3852     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
3853
3854     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data4, 1);
3855     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
3856     hr = IDirect3DDevice9_BeginScene(device);
3857     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3858     if(SUCCEEDED(hr))
3859     {
3860         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3861         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3862
3863         hr = IDirect3DDevice9_EndScene(device);
3864         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3865     }
3866     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3867     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3868     color = getPixelColor(device, 318, 240);
3869     ok(color == 0x000000ff, "Pixel 318(50%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
3870     color = getPixelColor(device, 322, 240);
3871     ok(color == 0x0000ff00, "Pixel 322(50%% + 2 pixel) has color %08x, expected 0x0000ff00\n", color);
3872
3873     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
3874
3875     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data5, 1);
3876     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
3877     hr = IDirect3DDevice9_BeginScene(device);
3878     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3879     if(SUCCEEDED(hr))
3880     {
3881         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3882         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3883
3884         hr = IDirect3DDevice9_EndScene(device);
3885         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3886     }
3887     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3888     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3889
3890     color = getPixelColor(device, 1, 240);
3891     ok(color == 0x00ffff00, "Pixel 1(0%% + 2 pixel) has color %08x, expected 0x00ffff00\n", color);
3892
3893     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
3894
3895     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data6, 1);
3896     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
3897     hr = IDirect3DDevice9_BeginScene(device);
3898     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3899     if(SUCCEEDED(hr))
3900     {
3901         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3902         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3903
3904         hr = IDirect3DDevice9_EndScene(device);
3905         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3906     }
3907     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3908     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3909
3910     color = getPixelColor(device, 638, 240);
3911     ok(color == 0x000000ff, "Pixel 638(100%% + 2 pixel) has color %08x, expected 0x000000ff\n", color);
3912
3913     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
3914
3915     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data7, 1);
3916     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
3917     hr = IDirect3DDevice9_BeginScene(device);
3918     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3919     if(SUCCEEDED(hr))
3920     {
3921         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3922         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3923
3924         hr = IDirect3DDevice9_EndScene(device);
3925         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3926     }
3927     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3928     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3929
3930     color = getPixelColor(device, 638, 240);
3931     ok(color == 0x000000ff, "Pixel 638(100%% + 2 pixel) has color %08x, expected 0x000000ff\n", color);
3932
3933     /* Cleanup */
3934     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
3935     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
3936     IDirect3DPixelShader9_Release(shader);
3937
3938     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
3939     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
3940     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
3941     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
3942 }
3943
3944 static void texkill_test(IDirect3DDevice9 *device)
3945 {
3946     IDirect3DPixelShader9 *shader;
3947     HRESULT hr;
3948     DWORD color;
3949
3950     const float vertex[] = {
3951     /*                          bottom  top    right    left */
3952         -1.0,   -1.0,   1.0,   -0.1,    0.9,    0.9,   -0.1,
3953          1.0,   -1.0,   0.0,    0.9,   -0.1,    0.9,   -0.1,
3954         -1.0,    1.0,   1.0,   -0.1,    0.9,   -0.1,    0.9,
3955          1.0,    1.0,   0.0,    0.9,   -0.1,   -0.1,    0.9,
3956     };
3957
3958     DWORD shader_code_11[] = {
3959     0xffff0101,                                                             /* ps_1_1                     */
3960     0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0 */
3961     0x00000041, 0xb00f0000,                                                 /* texkill t0                 */
3962     0x00000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                 */
3963     0x0000ffff                                                              /* end                        */
3964     };
3965     DWORD shader_code_20[] = {
3966     0xffff0200,                                                             /* ps_2_0                     */
3967     0x0200001f, 0x80000000, 0xb00f0000,                                     /* dcl t0                     */
3968     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c0, 0.0, 0.0, 1.0, 1.0 */
3969     0x01000041, 0xb00f0000,                                                 /* texkill t0                 */
3970     0x02000001, 0x800f0800, 0xa0e40000,                                     /* mov oC0, c0                */
3971     0x0000ffff                                                              /* end                        */
3972     };
3973
3974     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
3975     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
3976     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader);
3977     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
3978
3979     hr = IDirect3DDevice9_SetPixelShader(device, shader);
3980     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
3981     hr = IDirect3DDevice9_BeginScene(device);
3982     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
3983     if(SUCCEEDED(hr))
3984     {
3985         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1);
3986         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
3987         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 7 * sizeof(float));
3988         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3989         hr = IDirect3DDevice9_EndScene(device);
3990         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
3991     }
3992     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3993     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3994     color = getPixelColor(device, 63, 46);
3995     ok(color == 0x0000ff00, "Pixel 63/46 has color %08x, expected 0x0000ff00\n", color);
3996     color = getPixelColor(device, 66, 46);
3997     ok(color == 0x0000ff00, "Pixel 66/64 has color %08x, expected 0x0000ff00\n", color);
3998     color = getPixelColor(device, 63, 49);
3999     ok(color == 0x0000ff00, "Pixel 63/49 has color %08x, expected 0x0000ff00\n", color);
4000     color = getPixelColor(device, 66, 49);
4001     ok(color == 0x00ff0000, "Pixel 66/49 has color %08x, expected 0x00ff0000\n", color);
4002
4003     color = getPixelColor(device, 578, 46);
4004     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
4005     color = getPixelColor(device, 575, 46);
4006     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
4007     color = getPixelColor(device, 578, 49);
4008     ok(color == 0x0000ff00, "Pixel 578/49 has color %08x, expected 0x0000ff00\n", color);
4009     color = getPixelColor(device, 575, 49);
4010     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
4011
4012     color = getPixelColor(device, 63, 430);
4013     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
4014     color = getPixelColor(device, 63, 433);
4015     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
4016     color = getPixelColor(device, 66, 433);
4017     ok(color == 0x00ff0000, "Pixel 578/49 has color %08x, expected 0x00ff0000\n", color);
4018     color = getPixelColor(device, 66, 430);
4019     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
4020
4021     color = getPixelColor(device, 578, 430);
4022     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
4023     color = getPixelColor(device, 578, 433);
4024     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
4025     color = getPixelColor(device, 575, 433);
4026     ok(color == 0x00ff0000, "Pixel 578/49 has color %08x, expected 0x00ff0000\n", color);
4027     color = getPixelColor(device, 575, 430);
4028     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
4029
4030     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4031     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4032     IDirect3DPixelShader9_Release(shader);
4033
4034     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
4035     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4036     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_20, &shader);
4037     if(FAILED(hr)) {
4038         skip("Failed to create 2.0 test shader, most likely not supported\n");
4039         return;
4040     }
4041
4042     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4043     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4044     hr = IDirect3DDevice9_BeginScene(device);
4045     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4046     if(SUCCEEDED(hr))
4047     {
4048         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 7 * sizeof(float));
4049         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4050         hr = IDirect3DDevice9_EndScene(device);
4051         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4052     }
4053     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4054
4055     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4056     color = getPixelColor(device, 63, 46);
4057     ok(color == 0x00ffff00, "Pixel 63/46 has color %08x, expected 0x00ffff00\n", color);
4058     color = getPixelColor(device, 66, 46);
4059     ok(color == 0x00ffff00, "Pixel 66/64 has color %08x, expected 0x00ffff00\n", color);
4060     color = getPixelColor(device, 63, 49);
4061     ok(color == 0x00ffff00, "Pixel 63/49 has color %08x, expected 0x00ffff00\n", color);
4062     color = getPixelColor(device, 66, 49);
4063     ok(color == 0x000000ff, "Pixel 66/49 has color %08x, expected 0x000000ff\n", color);
4064
4065     color = getPixelColor(device, 578, 46);
4066     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
4067     color = getPixelColor(device, 575, 46);
4068     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
4069     color = getPixelColor(device, 578, 49);
4070     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
4071     color = getPixelColor(device, 575, 49);
4072     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
4073
4074     color = getPixelColor(device, 63, 430);
4075     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
4076     color = getPixelColor(device, 63, 433);
4077     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
4078     color = getPixelColor(device, 66, 433);
4079     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
4080     color = getPixelColor(device, 66, 430);
4081     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
4082
4083     color = getPixelColor(device, 578, 430);
4084     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
4085     color = getPixelColor(device, 578, 433);
4086     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
4087     color = getPixelColor(device, 575, 433);
4088     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
4089     color = getPixelColor(device, 575, 430);
4090     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
4091
4092     /* Cleanup */
4093     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4094     ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
4095     IDirect3DPixelShader9_Release(shader);
4096 }
4097
4098 static void x8l8v8u8_test(IDirect3DDevice9 *device)
4099 {
4100     IDirect3D9 *d3d9;
4101     HRESULT hr;
4102     IDirect3DTexture9 *texture;
4103     IDirect3DPixelShader9 *shader;
4104     IDirect3DPixelShader9 *shader2;
4105     D3DLOCKED_RECT lr;
4106     DWORD color;
4107     DWORD shader_code[] = {
4108         0xffff0101,                             /* ps_1_1       */
4109         0x00000042, 0xb00f0000,                 /* tex t0       */
4110         0x00000001, 0x800f0000, 0xb0e40000,     /* mov r0, t0   */
4111         0x0000ffff                              /* end          */
4112     };
4113     DWORD shader_code2[] = {
4114         0xffff0101,                             /* ps_1_1       */
4115         0x00000042, 0xb00f0000,                 /* tex t0       */
4116         0x00000001, 0x800f0000, 0xb0ff0000,     /* mov r0, t0.w */
4117         0x0000ffff                              /* end          */
4118     };
4119
4120     float quad[] = {
4121        -1.0,   -1.0,   0.1,     0.5,    0.5,
4122         1.0,   -1.0,   0.1,     0.5,    0.5,
4123        -1.0,    1.0,   0.1,     0.5,    0.5,
4124         1.0,    1.0,   0.1,     0.5,    0.5,
4125     };
4126
4127     memset(&lr, 0, sizeof(lr));
4128     IDirect3DDevice9_GetDirect3D(device, &d3d9);
4129     hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4130                                       0,  D3DRTYPE_TEXTURE, D3DFMT_X8L8V8U8);
4131     IDirect3D9_Release(d3d9);
4132     if(FAILED(hr)) {
4133         skip("No D3DFMT_X8L8V8U8 support\n");
4134     };
4135
4136     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
4137     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4138
4139     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_X8L8V8U8, D3DPOOL_MANAGED, &texture, NULL);
4140     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed (%08x)\n", hr);
4141     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
4142     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed (%08x)\n", hr);
4143     *((DWORD *) lr.pBits) = 0x11ca3141;
4144     hr = IDirect3DTexture9_UnlockRect(texture, 0);
4145     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed (%08x)\n", hr);
4146
4147     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
4148     ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr);
4149     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code2, &shader2);
4150     ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr);
4151
4152     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4153     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed (%08x)\n", hr);
4154     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4155     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4156     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
4157     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
4158
4159     hr = IDirect3DDevice9_BeginScene(device);
4160     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4161     if(SUCCEEDED(hr))
4162     {
4163         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
4164         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4165
4166         hr = IDirect3DDevice9_EndScene(device);
4167         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4168     }
4169     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4170     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4171     color = getPixelColor(device, 578, 430);
4172     ok(color == 0x008262ca || color == 0x008363ca || color == 0x008362ca,
4173        "D3DFMT_X8L8V8U8 = 0x112131ca returns color %08x, expected 0x008262ca\n", color);
4174
4175     hr = IDirect3DDevice9_SetPixelShader(device, shader2);
4176     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4177     hr = IDirect3DDevice9_BeginScene(device);
4178     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4179     if(SUCCEEDED(hr))
4180     {
4181         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
4182         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4183
4184         hr = IDirect3DDevice9_EndScene(device);
4185         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4186     }
4187     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4188     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4189     color = getPixelColor(device, 578, 430);
4190     ok(color == 0x00ffffff, "w component of D3DFMT_X8L8V8U8 = 0x11ca3141 returns color %08x\n", color);
4191
4192     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4193     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4194     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4195     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
4196     IDirect3DPixelShader9_Release(shader);
4197     IDirect3DPixelShader9_Release(shader2);
4198     IDirect3DTexture9_Release(texture);
4199 }
4200
4201 static void autogen_mipmap_test(IDirect3DDevice9 *device)
4202 {
4203     HRESULT hr;
4204     IDirect3D9 *d3d;
4205     IDirect3DTexture9 *texture = NULL;
4206     IDirect3DSurface9 *surface;
4207     DWORD color;
4208     const RECT r1 = {256, 256, 512, 512};
4209     const RECT r2 = {512, 256, 768, 512};
4210     const RECT r3 = {256, 512, 512, 768};
4211     const RECT r4 = {512, 512, 768, 768};
4212     unsigned int x, y;
4213     D3DLOCKED_RECT lr;
4214     memset(&lr, 0, sizeof(lr));
4215
4216     IDirect3DDevice9_GetDirect3D(device, &d3d);
4217     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4218        D3DUSAGE_AUTOGENMIPMAP,  D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8) != D3D_OK) {
4219         skip("No autogenmipmap support\n");
4220         IDirect3D9_Release(d3d);
4221         return;
4222     }
4223     IDirect3D9_Release(d3d);
4224
4225     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
4226     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4227
4228     /* Make the mipmap big, so that a smaller mipmap is used
4229      */
4230     hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 0, D3DUSAGE_AUTOGENMIPMAP,
4231                                         D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4232     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
4233
4234     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
4235     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel returned %08x\n", hr);
4236     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
4237     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
4238     for(y = 0; y < 1024; y++) {
4239         for(x = 0; x < 1024; x++) {
4240             DWORD *dst = (DWORD *) (((BYTE *) lr.pBits) + y * lr.Pitch + x * 4);
4241             POINT pt;
4242
4243             pt.x = x;
4244             pt.y = y;
4245             if(PtInRect(&r1, pt)) {
4246                 *dst = 0xffff0000;
4247             } else if(PtInRect(&r2, pt)) {
4248                 *dst = 0xff00ff00;
4249             } else if(PtInRect(&r3, pt)) {
4250                 *dst = 0xff0000ff;
4251             } else if(PtInRect(&r4, pt)) {
4252                 *dst = 0xff000000;
4253             } else {
4254                 *dst = 0xffffffff;
4255             }
4256         }
4257     }
4258     hr = IDirect3DSurface9_UnlockRect(surface);
4259     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect returned %08x\n", hr);
4260     IDirect3DSurface9_Release(surface);
4261
4262     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
4263     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
4264     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
4265     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
4266
4267     hr = IDirect3DDevice9_BeginScene(device);
4268     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4269     if(SUCCEEDED(hr)) {
4270         const float quad[] =  {
4271            -0.5,   -0.5,    0.1,    0.0,    0.0,
4272            -0.5,    0.5,    0.1,    0.0,    1.0,
4273             0.5,   -0.5,    0.1,    1.0,    0.0,
4274             0.5,    0.5,    0.1,    1.0,    1.0
4275         };
4276
4277         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4278         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
4279         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
4280         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4281         hr = IDirect3DDevice9_EndScene(device);
4282         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4283     }
4284     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4285     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
4286     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
4287     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
4288     IDirect3DTexture9_Release(texture);
4289
4290     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4291     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4292     color = getPixelColor(device, 200, 200);
4293     ok(color == 0x00ffffff, "pixel 200/200 has color %08x, expected 0x00ffffff\n", color);
4294     color = getPixelColor(device, 280, 200);
4295     ok(color == 0x000000ff, "pixel 280/200 has color %08x, expected 0x000000ff\n", color);
4296     color = getPixelColor(device, 360, 200);
4297     ok(color == 0x00000000, "pixel 360/200 has color %08x, expected 0x00000000\n", color);
4298     color = getPixelColor(device, 440, 200);
4299     ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
4300     color = getPixelColor(device, 200, 270);
4301     ok(color == 0x00ffffff, "pixel 200/270 has color %08x, expected 0x00ffffff\n", color);
4302     color = getPixelColor(device, 280, 270);
4303     ok(color == 0x00ff0000, "pixel 280/270 has color %08x, expected 0x00ff0000\n", color);
4304     color = getPixelColor(device, 360, 270);
4305     ok(color == 0x0000ff00, "pixel 360/270 has color %08x, expected 0x0000ff00\n", color);
4306     color = getPixelColor(device, 440, 270);
4307     ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
4308 }
4309
4310 static void test_constant_clamp_vs(IDirect3DDevice9 *device)
4311 {
4312     IDirect3DVertexShader9 *shader_11, *shader_11_2, *shader_20, *shader_20_2;
4313     IDirect3DVertexDeclaration9 *decl;
4314     HRESULT hr;
4315     DWORD color;
4316     DWORD shader_code_11[] =  {
4317         0xfffe0101,                                         /* vs_1_1           */
4318         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4319         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4320         0x00000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4321         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4322         0x0000ffff                                          /* end              */
4323     };
4324     DWORD shader_code_11_2[] =  {
4325         0xfffe0101,                                         /* vs_1_1           */
4326         0x00000051, 0xa00f0001, 0x3fa00000, 0xbf000000, 0xbfc00000, 0x3f800000, /* dcl ... */
4327         0x00000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000, /* dcl ... */
4328         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4329         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4330         0x00000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4331         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4332         0x0000ffff                                          /* end              */
4333     };
4334     DWORD shader_code_20[] =  {
4335         0xfffe0200,                                         /* vs_2_0           */
4336         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4337         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4338         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4339         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4340         0x0000ffff                                          /* end              */
4341     };
4342     DWORD shader_code_20_2[] =  {
4343         0xfffe0200,                                         /* vs_2_0           */
4344         0x05000051, 0xa00f0001, 0x3fa00000, 0xbf000000, 0xbfc00000, 0x3f800000,
4345         0x05000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000,
4346         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4347         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4348         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4349         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4350         0x0000ffff                                          /* end              */
4351     };
4352     static const D3DVERTEXELEMENT9 decl_elements[] = {
4353         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4354         D3DDECL_END()
4355     };
4356     float quad1[] = {
4357         -1.0,   -1.0,   0.1,
4358          0.0,   -1.0,   0.1,
4359         -1.0,    0.0,   0.1,
4360          0.0,    0.0,   0.1
4361     };
4362     float quad2[] = {
4363          0.0,   -1.0,   0.1,
4364          1.0,   -1.0,   0.1,
4365          0.0,    0.0,   0.1,
4366          1.0,    0.0,   0.1
4367     };
4368     float quad3[] = {
4369          0.0,    0.0,   0.1,
4370          1.0,    0.0,   0.1,
4371          0.0,    1.0,   0.1,
4372          1.0,    1.0,   0.1
4373     };
4374     float quad4[] = {
4375         -1.0,    0.0,   0.1,
4376          0.0,    0.0,   0.1,
4377         -1.0,    1.0,   0.1,
4378          0.0,    1.0,   0.1
4379     };
4380     float test_data_c1[4] = {  1.25, -0.50, -1.50, 1.0};
4381     float test_data_c2[4] = { -0.50,  1.25,  2.00, 1.0};
4382
4383     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
4384     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4385
4386     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_11, &shader_11);
4387     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
4388     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_11_2, &shader_11_2);
4389     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
4390     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_20, &shader_20);
4391     if(FAILED(hr)) shader_20 = NULL;
4392     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_20_2, &shader_20_2);
4393     if(FAILED(hr)) shader_20_2 = NULL;
4394     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
4395     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
4396
4397     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, test_data_c1, 1);
4398     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned %08x\n", hr);
4399     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 2, test_data_c2, 1);
4400     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned %08x\n", hr);
4401     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
4402     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
4403
4404     hr = IDirect3DDevice9_BeginScene(device);
4405     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4406     if(SUCCEEDED(hr))
4407     {
4408         hr = IDirect3DDevice9_SetVertexShader(device, shader_11);
4409         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4410         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 3 * sizeof(float));
4411         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4412
4413         hr = IDirect3DDevice9_SetVertexShader(device, shader_11_2);
4414         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4415         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
4416         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4417
4418         if(shader_20) {
4419             hr = IDirect3DDevice9_SetVertexShader(device, shader_20);
4420             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4421             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 3 * sizeof(float));
4422             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4423         }
4424
4425         if(shader_20_2) {
4426             hr = IDirect3DDevice9_SetVertexShader(device, shader_20_2);
4427             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4428             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 3 * sizeof(float));
4429             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4430         }
4431
4432         hr = IDirect3DDevice9_EndScene(device);
4433         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4434     }
4435     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4436     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4437
4438     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
4439     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4440     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
4441     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
4442
4443     color = getPixelColor(device, 160, 360);
4444     ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
4445        "quad 1 has color %08x, expected 0x00bfbf80\n", color);
4446     color = getPixelColor(device, 480, 360);
4447     ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
4448        "quad 2 has color %08x, expected 0x00bfbf80\n", color);
4449     if(shader_20) {
4450         color = getPixelColor(device, 160, 120);
4451         ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
4452            "quad 3 has color %08x, expected 0x00bfbf80\n", color);
4453     }
4454     if(shader_20_2) {
4455         color = getPixelColor(device, 480, 120);
4456         ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
4457            "quad 4 has color %08x, expected 0x00bfbf80\n", color);
4458     }
4459
4460     IDirect3DVertexDeclaration9_Release(decl);
4461     if(shader_20_2) IDirect3DVertexShader9_Release(shader_20_2);
4462     if(shader_20) IDirect3DVertexShader9_Release(shader_20);
4463     IDirect3DVertexShader9_Release(shader_11_2);
4464     IDirect3DVertexShader9_Release(shader_11);
4465 }
4466
4467 static void constant_clamp_ps_test(IDirect3DDevice9 *device)
4468 {
4469     IDirect3DPixelShader9 *shader_11, *shader_12, *shader_14, *shader_20;
4470     HRESULT hr;
4471     DWORD color;
4472     DWORD shader_code_11[] =  {
4473         0xffff0101,                                         /* ps_1_1           */
4474         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4475         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
4476         0x0000ffff                                          /* end              */
4477     };
4478     DWORD shader_code_12[] =  {
4479         0xffff0102,                                         /* ps_1_2           */
4480         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4481         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
4482         0x0000ffff                                          /* end              */
4483     };
4484     /* Skip 1.3 shaders because we have only 4 quads(ok, could make them smaller if needed).
4485      * 1.2 and 1.4 shaders behave the same, so it's unlikely that 1.3 shaders are different.
4486      * During development of this test, 1.3 shaders were verified too
4487      */
4488     DWORD shader_code_14[] =  {
4489         0xffff0104,                                         /* ps_1_4           */
4490         /* Try to make one constant local. It gets clamped too, although the binary contains
4491          * the bigger numbers
4492          */
4493         0x00000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000, /* def c2, -0.5, 1.25, 2, 1 */
4494         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4495         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
4496         0x0000ffff                                          /* end              */
4497     };
4498     DWORD shader_code_20[] =  {
4499         0xffff0200,                                         /* ps_2_0           */
4500         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4501         0x03000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
4502         0x02000001, 0x800f0800, 0x80e40000,                 /* mov oC0, r0      */
4503         0x0000ffff                                          /* end              */
4504     };
4505     float quad1[] = {
4506         -1.0,   -1.0,   0.1,
4507          0.0,   -1.0,   0.1,
4508         -1.0,    0.0,   0.1,
4509          0.0,    0.0,   0.1
4510     };
4511     float quad2[] = {
4512          0.0,   -1.0,   0.1,
4513          1.0,   -1.0,   0.1,
4514          0.0,    0.0,   0.1,
4515          1.0,    0.0,   0.1
4516     };
4517     float quad3[] = {
4518          0.0,    0.0,   0.1,
4519          1.0,    0.0,   0.1,
4520          0.0,    1.0,   0.1,
4521          1.0,    1.0,   0.1
4522     };
4523     float quad4[] = {
4524         -1.0,    0.0,   0.1,
4525          0.0,    0.0,   0.1,
4526         -1.0,    1.0,   0.1,
4527          0.0,    1.0,   0.1
4528     };
4529     float test_data_c1[4] = {  1.25, -0.50, -1.50, 1.0};
4530     float test_data_c2[4] = { -0.50,  1.25,  2.00, 1.0};
4531
4532     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
4533     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4534
4535     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader_11);
4536     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4537     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12, &shader_12);
4538     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4539     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14, &shader_14);
4540     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4541     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_20, &shader_20);
4542     if(FAILED(hr)) shader_20 = NULL;
4543
4544     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1, 1);
4545     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4546     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2, 1);
4547     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4548     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4549     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
4550
4551     hr = IDirect3DDevice9_BeginScene(device);
4552     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4553     if(SUCCEEDED(hr))
4554     {
4555         hr = IDirect3DDevice9_SetPixelShader(device, shader_11);
4556         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4557         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 3 * sizeof(float));
4558         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4559
4560         hr = IDirect3DDevice9_SetPixelShader(device, shader_12);
4561         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4562         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
4563         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4564
4565         hr = IDirect3DDevice9_SetPixelShader(device, shader_14);
4566         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4567         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 3 * sizeof(float));
4568         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4569
4570         if(shader_20) {
4571             hr = IDirect3DDevice9_SetPixelShader(device, shader_20);
4572             ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4573             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 3 * sizeof(float));
4574             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4575         }
4576
4577         hr = IDirect3DDevice9_EndScene(device);
4578         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4579     }
4580     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4581     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4582
4583     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4584     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4585
4586     color = getPixelColor(device, 160, 360);
4587     ok(color == 0x00808000 || color == 0x007f7f00 || color == 0x00818100,
4588        "quad 1 has color %08x, expected 0x00808000\n", color);
4589     color = getPixelColor(device, 480, 360);
4590     ok(color == 0x00808000 || color == 0x007f7f00 || color == 0x00818100,
4591        "quad 2 has color %08x, expected 0x00808000\n", color);
4592     color = getPixelColor(device, 480, 120);
4593     ok(color == 0x00808000 || color == 0x007f7f00 || color == 0x00818100,
4594        "quad 3 has color %08x, expected 0x00808000\n", color);
4595     if(shader_20) {
4596         color = getPixelColor(device, 160, 120);
4597         ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
4598            "quad 4 has color %08x, expected 0x00bfbf80\n", color);
4599     }
4600
4601     if(shader_20) IDirect3DPixelShader9_Release(shader_20);
4602     IDirect3DPixelShader9_Release(shader_14);
4603     IDirect3DPixelShader9_Release(shader_12);
4604     IDirect3DPixelShader9_Release(shader_11);
4605 }
4606
4607 static void dp2add_ps_test(IDirect3DDevice9 *device)
4608 {
4609     IDirect3DPixelShader9 *shader_dp2add = NULL;
4610     IDirect3DPixelShader9 *shader_dp2add_sat = NULL;
4611     HRESULT hr;
4612     DWORD color;
4613
4614     /* DP2ADD is defined as:  (src0.r * src1.r) + (src0.g * src1.g) + src2.
4615      * One D3D restriction of all shader instructions except SINCOS is that no more than 2
4616      * source tokens can be constants.  So, for this exercise, we move contents of c0 to
4617      * r0 first.
4618      * The result here for the r,g,b components should be roughly 0.5:
4619      *   (0.5 * 0.5) + (0.5 * 0.5) + 0.0 = 0.5 */
4620     static const DWORD shader_code_dp2add[] =  {
4621         0xffff0200,                                                             /* ps_2_0                       */
4622         0x05000051, 0xa00f0000, 0x3f000000, 0x3f000000, 0x3f800000, 0x00000000, /* def c0, 0.5, 0.5, 1.0, 0     */
4623
4624         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                   */
4625         0x0400005a, 0x80070000, 0x80000000, 0x80000000, 0x80ff0000,             /* dp2add r0.rgb, r0, r0, r0.a  */
4626
4627         0x02000001, 0x80080000, 0xa0aa0000,                                     /* mov r0.a, c0.b               */
4628         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
4629         0x0000ffff                                                              /* end                          */
4630     };
4631
4632     /* Test the _sat modifier, too.  Result here should be:
4633      *   DP2: (-0.5 * -0.5) + (-0.5 * -0.5) + 2.0 = 2.5
4634      *      _SAT: ==> 1.0
4635      *   ADD: (1.0 + -0.5) = 0.5
4636      */
4637     static const DWORD shader_code_dp2add_sat[] =  {
4638         0xffff0200,                                                             /* ps_2_0                           */
4639         0x05000051, 0xa00f0000, 0xbf000000, 0xbf000000, 0x3f800000, 0x40000000, /* def c0, -0.5, -0.5, 1.0, 2.0     */
4640
4641         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                       */
4642         0x0400005a, 0x80170000, 0x80000000, 0x80000000, 0x80ff0000,             /* dp2add_sat r0.rgb, r0, r0, r0.a  */
4643         0x03000002, 0x80070000, 0x80e40000, 0xa0000000,                         /* add r0.rgb, r0, c0.r             */
4644
4645         0x02000001, 0x80080000, 0xa0aa0000,                                     /* mov r0.a, c0.b                   */
4646         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                      */
4647         0x0000ffff                                                              /* end                              */
4648     };
4649
4650     const float quad[] = {
4651         -1.0,   -1.0,   0.1,
4652          1.0,   -1.0,   0.1,
4653         -1.0,    1.0,   0.1,
4654          1.0,    1.0,   0.1
4655     };
4656
4657
4658     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
4659     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4660
4661     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_dp2add, &shader_dp2add);
4662     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4663
4664     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_dp2add_sat, &shader_dp2add_sat);
4665     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4666
4667     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4668     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
4669
4670     if (shader_dp2add) {
4671
4672         hr = IDirect3DDevice9_SetPixelShader(device, shader_dp2add);
4673         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4674
4675         hr = IDirect3DDevice9_BeginScene(device);
4676         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4677         if(SUCCEEDED(hr))
4678         {
4679             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
4680             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4681
4682             hr = IDirect3DDevice9_EndScene(device);
4683             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4684         }
4685         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4686         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4687
4688         color = getPixelColor(device, 360, 240);
4689         ok(color == 0x007f7f7f || color == 0x00808080, "dp2add pixel has color %08x, expected ~0x007f7f7f\n", color);
4690
4691         IDirect3DPixelShader9_Release(shader_dp2add);
4692     } else {
4693         skip("dp2add shader creation failed\n");
4694     }
4695
4696     if (shader_dp2add_sat) {
4697
4698         hr = IDirect3DDevice9_SetPixelShader(device, shader_dp2add_sat);
4699         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4700
4701         hr = IDirect3DDevice9_BeginScene(device);
4702         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4703         if(SUCCEEDED(hr))
4704         {
4705             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
4706             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4707
4708             hr = IDirect3DDevice9_EndScene(device);
4709             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4710         }
4711         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4712         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4713
4714         color = getPixelColor(device, 360, 240);
4715         ok(color == 0x007f7f7f || color == 0x00808080, "dp2add pixel has color %08x, expected ~0x007f7f7f\n", color);
4716
4717         IDirect3DPixelShader9_Release(shader_dp2add_sat);
4718     } else {
4719         skip("dp2add shader creation failed\n");
4720     }
4721
4722     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4723     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4724 }
4725
4726 static void cnd_test(IDirect3DDevice9 *device)
4727 {
4728     IDirect3DPixelShader9 *shader_11, *shader_12, *shader_13, *shader_14;
4729     IDirect3DPixelShader9 *shader_11_coissue, *shader_12_coissue, *shader_13_coissue, *shader_14_coissue;
4730     HRESULT hr;
4731     DWORD color;
4732     /* ps 1.x shaders are rather picky with writemasks and source swizzles. The dp3 is
4733      * used to copy r0.r to all components of r1, then copy r1.a to c0.a. Essentially it
4734      * does a mov r0.a, r0.r, which isn't allowed as-is in 1.x pixel shaders.
4735      */
4736     DWORD shader_code_11[] =  {
4737         0xffff0101,                                                                 /* ps_1_1               */
4738         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
4739         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
4740         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, ???(t0)      */
4741         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3 r1, r0, c0       */
4742         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
4743         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
4744         0x0000ffff                                                                  /* end                  */
4745     };
4746     DWORD shader_code_12[] =  {
4747         0xffff0102,                                                                 /* ps_1_2               */
4748         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
4749         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
4750         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, t0           */
4751         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3 r1, r0, c0       */
4752         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
4753         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
4754         0x0000ffff                                                                  /* end                  */
4755     };
4756     DWORD shader_code_13[] =  {
4757         0xffff0103,                                                                 /* ps_1_3               */
4758         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
4759         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
4760         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, t0           */
4761         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3, r1, r0, c0      */
4762         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
4763         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
4764         0x0000ffff                                                                  /* end                  */
4765     };
4766     DWORD shader_code_14[] =  {
4767         0xffff0104,                                                                 /* ps_1_3               */
4768         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,     /* def c0, 0, 0, 0, 1   */
4769         0x00000040, 0x80070000, 0xb0e40000,                                         /* texcrd r0, t0        */
4770         0x00000001, 0x80080000, 0xa0ff0000,                                         /* mov r0.a, c0.a       */
4771         0x00000050, 0x800f0000, 0x80e40000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0, c1, c2   */
4772         0x0000ffff                                                                  /* end                  */
4773     };
4774
4775     /* Special fun: The coissue flag on cnd: Apparently cnd always selects the 2nd source,
4776      * as if the src0 comparison against 0.5 always evaluates to true. The coissue flag isn't
4777      * set by the compiler, it was added manually after compilation. It isn't always allowed,
4778      * only if there's a mov r0.a, XXXX, and the cnd instruction writes to r0.xyz, otherwise
4779      * native CreatePixelShader returns an error.
4780      *
4781      * The shader attempts to test the range [-1;1] against coissued cnd, which is a bit tricky.
4782      * The input from t0 is [0;1]. 0.5 is substracted, then we have to multiply with 2. Since
4783      * constants are clamped to [-1;1], a 2.0 is constructed by adding c0.r(=1.0) to c0.r into r1.r,
4784      * then r1(2.0, 0.0, 0.0, 0.0) is passed to dp3(explained above).
4785      */
4786     DWORD shader_code_11_coissue[] =  {
4787         0xffff0101,                                                             /* ps_1_1                   */
4788         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
4789         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
4790         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
4791         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
4792         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
4793         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
4794         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
4795         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
4796         /* 0x40000000 = D3DSI_COISSUE */
4797         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
4798         0x0000ffff                                                              /* end                      */
4799     };
4800     DWORD shader_code_12_coissue[] =  {
4801         0xffff0102,                                                             /* ps_1_2                   */
4802         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
4803         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
4804         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
4805         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
4806         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
4807         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
4808         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
4809         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
4810         /* 0x40000000 = D3DSI_COISSUE */
4811         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
4812         0x0000ffff                                                              /* end                      */
4813     };
4814     DWORD shader_code_13_coissue[] =  {
4815         0xffff0103,                                                             /* ps_1_3                   */
4816         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
4817         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
4818         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
4819         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
4820         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
4821         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
4822         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
4823         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
4824         /* 0x40000000 = D3DSI_COISSUE */
4825         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
4826         0x0000ffff                                                              /* end                      */
4827     };
4828     /* ps_1_4 does not have a different cnd behavior, just pass the [0;1] texcrd result to cnd, it will
4829      * compare against 0.5
4830      */
4831     DWORD shader_code_14_coissue[] =  {
4832         0xffff0104,                                                             /* ps_1_4                   */
4833         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0, 0, 0, 1       */
4834         0x00000040, 0x80070000, 0xb0e40000,                                     /* texcrd r0, t0            */
4835         0x00000001, 0x80080000, 0xa0ff0000,                                     /* mov r0.a, c0.a           */
4836         /* 0x40000000 = D3DSI_COISSUE */
4837         0x40000050, 0x80070000, 0x80e40000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0, c1, c2   */
4838         0x0000ffff                                                              /* end                      */
4839     };
4840     float quad1[] = {
4841         -1.0,   -1.0,   0.1,     0.0,    0.0,    1.0,
4842          0.0,   -1.0,   0.1,     1.0,    0.0,    1.0,
4843         -1.0,    0.0,   0.1,     0.0,    1.0,    0.0,
4844          0.0,    0.0,   0.1,     1.0,    1.0,    0.0
4845     };
4846     float quad2[] = {
4847          0.0,   -1.0,   0.1,     0.0,    0.0,    1.0,
4848          1.0,   -1.0,   0.1,     1.0,    0.0,    1.0,
4849          0.0,    0.0,   0.1,     0.0,    1.0,    0.0,
4850          1.0,    0.0,   0.1,     1.0,    1.0,    0.0
4851     };
4852     float quad3[] = {
4853          0.0,    0.0,   0.1,     0.0,    0.0,    1.0,
4854          1.0,    0.0,   0.1,     1.0,    0.0,    1.0,
4855          0.0,    1.0,   0.1,     0.0,    1.0,    0.0,
4856          1.0,    1.0,   0.1,     1.0,    1.0,    0.0
4857     };
4858     float quad4[] = {
4859         -1.0,    0.0,   0.1,     0.0,    0.0,    1.0,
4860          0.0,    0.0,   0.1,     1.0,    0.0,    1.0,
4861         -1.0,    1.0,   0.1,     0.0,    1.0,    0.0,
4862          0.0,    1.0,   0.1,     1.0,    1.0,    0.0
4863     };
4864     float test_data_c1[4] = {  0.0, 0.0, 0.0, 0.0};
4865     float test_data_c2[4] = {  1.0, 1.0, 1.0, 1.0};
4866     float test_data_c1_coi[4] = {  0.0, 1.0, 0.0, 0.0};
4867     float test_data_c2_coi[4] = {  1.0, 0.0, 1.0, 1.0};
4868
4869     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
4870     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4871
4872     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader_11);
4873     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4874     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12, &shader_12);
4875     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4876     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_13, &shader_13);
4877     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4878     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14, &shader_14);
4879     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4880     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11_coissue, &shader_11_coissue);
4881     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4882     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12_coissue, &shader_12_coissue);
4883     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4884     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_13_coissue, &shader_13_coissue);
4885     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4886     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14_coissue, &shader_14_coissue);
4887     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4888
4889     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1, 1);
4890     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4891     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2, 1);
4892     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4893     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4894     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
4895
4896     hr = IDirect3DDevice9_BeginScene(device);
4897     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4898     if(SUCCEEDED(hr))
4899     {
4900         hr = IDirect3DDevice9_SetPixelShader(device, shader_11);
4901         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4902         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
4903         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4904
4905         hr = IDirect3DDevice9_SetPixelShader(device, shader_12);
4906         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4907         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
4908         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4909
4910         hr = IDirect3DDevice9_SetPixelShader(device, shader_13);
4911         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4912         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 6 * sizeof(float));
4913         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4914
4915         hr = IDirect3DDevice9_SetPixelShader(device, shader_14);
4916         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4917         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
4918         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4919
4920         hr = IDirect3DDevice9_EndScene(device);
4921         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4922     }
4923     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4924     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4925
4926     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4927     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
4928
4929     /* This is the 1.4 test. Each component(r, g, b) is tested separately against 0.5 */
4930     color = getPixelColor(device, 158, 118);
4931     ok(color == 0x00ff00ff, "pixel 158, 118 has color %08x, expected 0x00ff00ff\n", color);
4932     color = getPixelColor(device, 162, 118);
4933     ok(color == 0x000000ff, "pixel 162, 118 has color %08x, expected 0x000000ff\n", color);
4934     color = getPixelColor(device, 158, 122);
4935     ok(color == 0x00ffffff, "pixel 162, 122 has color %08x, expected 0x00ffffff\n", color);
4936     color = getPixelColor(device, 162, 122);
4937     ok(color == 0x0000ffff, "pixel 162, 122 has color %08x, expected 0x0000ffff\n", color);
4938
4939     /* 1.1 shader. All 3 components get set, based on the .w comparison */
4940     color = getPixelColor(device, 158, 358);
4941     ok(color == 0x00ffffff, "pixel 158, 358 has color %08x, expected 0x00ffffff\n", color);
4942     color = getPixelColor(device, 162, 358);
4943     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4944         "pixel 162, 358 has color %08x, expected 0x00000000\n", color);
4945     color = getPixelColor(device, 158, 362);
4946     ok(color == 0x00ffffff, "pixel 158, 362 has color %08x, expected 0x00ffffff\n", color);
4947     color = getPixelColor(device, 162, 362);
4948     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4949         "pixel 162, 362 has color %08x, expected 0x00000000\n", color);
4950
4951     /* 1.2 shader */
4952     color = getPixelColor(device, 478, 358);
4953     ok(color == 0x00ffffff, "pixel 478, 358 has color %08x, expected 0x00ffffff\n", color);
4954     color = getPixelColor(device, 482, 358);
4955     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4956         "pixel 482, 358 has color %08x, expected 0x00000000\n", color);
4957     color = getPixelColor(device, 478, 362);
4958     ok(color == 0x00ffffff, "pixel 478, 362 has color %08x, expected 0x00ffffff\n", color);
4959     color = getPixelColor(device, 482, 362);
4960     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4961         "pixel 482, 362 has color %08x, expected 0x00000000\n", color);
4962
4963     /* 1.3 shader */
4964     color = getPixelColor(device, 478, 118);
4965     ok(color == 0x00ffffff, "pixel 478, 118 has color %08x, expected 0x00ffffff\n", color);
4966     color = getPixelColor(device, 482, 118);
4967     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4968         "pixel 482, 118 has color %08x, expected 0x00000000\n", color);
4969     color = getPixelColor(device, 478, 122);
4970     ok(color == 0x00ffffff, "pixel 478, 122 has color %08x, expected 0x00ffffff\n", color);
4971     color = getPixelColor(device, 482, 122);
4972     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4973         "pixel 482, 122 has color %08x, expected 0x00000000\n", color);
4974
4975     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
4976     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4977     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1_coi, 1);
4978     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4979     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2_coi, 1);
4980     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4981
4982     hr = IDirect3DDevice9_BeginScene(device);
4983     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4984     if(SUCCEEDED(hr))
4985     {
4986         hr = IDirect3DDevice9_SetPixelShader(device, shader_11_coissue);
4987         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4988         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
4989         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4990
4991         hr = IDirect3DDevice9_SetPixelShader(device, shader_12_coissue);
4992         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4993         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
4994         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4995
4996         hr = IDirect3DDevice9_SetPixelShader(device, shader_13_coissue);
4997         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4998         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 6 * sizeof(float));
4999         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5000
5001         hr = IDirect3DDevice9_SetPixelShader(device, shader_14_coissue);
5002         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5003         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
5004         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5005
5006         hr = IDirect3DDevice9_EndScene(device);
5007         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5008     }
5009     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5010     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5011
5012     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5013     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5014
5015     /* This is the 1.4 test. The coissue doesn't change the behavior here, but keep in mind
5016      * that we swapped the values in c1 and c2 to make the other tests return some color
5017      */
5018     color = getPixelColor(device, 158, 118);
5019     ok(color == 0x00ffffff, "pixel 158, 118 has color %08x, expected 0x00ffffff\n", color);
5020     color = getPixelColor(device, 162, 118);
5021     ok(color == 0x0000ffff, "pixel 162, 118 has color %08x, expected 0x0000ffff\n", color);
5022     color = getPixelColor(device, 158, 122);
5023     ok(color == 0x00ff00ff, "pixel 162, 122 has color %08x, expected 0x00ff00ff\n", color);
5024     color = getPixelColor(device, 162, 122);
5025     ok(color == 0x000000ff, "pixel 162, 122 has color %08x, expected 0x000000ff\n", color);
5026
5027     /* 1.1 shader. coissue flag changed the semantic of cnd, c1 is always selected */
5028     color = getPixelColor(device, 158, 358);
5029     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5030         "pixel 158, 358 has color %08x, expected 0x0000ff00\n", color);
5031     color = getPixelColor(device, 162, 358);
5032     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5033         "pixel 162, 358 has color %08x, expected 0x0000ff00\n", color);
5034     color = getPixelColor(device, 158, 362);
5035     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5036         "pixel 158, 362 has color %08x, expected 0x0000ff00\n", color);
5037     color = getPixelColor(device, 162, 362);
5038     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5039         "pixel 162, 362 has color %08x, expected 0x0000ff00\n", color);
5040
5041     /* 1.2 shader */
5042     color = getPixelColor(device, 478, 358);
5043     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5044         "pixel 478, 358 has color %08x, expected 0x0000ff00\n", color);
5045     color = getPixelColor(device, 482, 358);
5046     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5047         "pixel 482, 358 has color %08x, expected 0x0000ff00\n", color);
5048     color = getPixelColor(device, 478, 362);
5049     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5050         "pixel 478, 362 has color %08x, expected 0x0000ff00\n", color);
5051     color = getPixelColor(device, 482, 362);
5052     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5053         "pixel 482, 362 has color %08x, expected 0x0000ff00\n", color);
5054
5055     /* 1.3 shader */
5056     color = getPixelColor(device, 478, 118);
5057     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5058         "pixel 478, 118 has color %08x, expected 0x0000ff00\n", color);
5059     color = getPixelColor(device, 482, 118);
5060     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5061         "pixel 482, 118 has color %08x, expected 0x0000ff00\n", color);
5062     color = getPixelColor(device, 478, 122);
5063     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5064         "pixel 478, 122 has color %08x, expected 0x0000ff00\n", color);
5065     color = getPixelColor(device, 482, 122);
5066     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
5067         "pixel 482, 122 has color %08x, expected 0x0000ff00\n", color);
5068
5069     IDirect3DPixelShader9_Release(shader_14_coissue);
5070     IDirect3DPixelShader9_Release(shader_13_coissue);
5071     IDirect3DPixelShader9_Release(shader_12_coissue);
5072     IDirect3DPixelShader9_Release(shader_11_coissue);
5073     IDirect3DPixelShader9_Release(shader_14);
5074     IDirect3DPixelShader9_Release(shader_13);
5075     IDirect3DPixelShader9_Release(shader_12);
5076     IDirect3DPixelShader9_Release(shader_11);
5077 }
5078
5079 static void nested_loop_test(IDirect3DDevice9 *device) {
5080     const DWORD shader_code[] = {
5081         0xffff0300,                                                             /* ps_3_0               */
5082         0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0, 0, 0, 1   */
5083         0x05000051, 0xa00f0001, 0x3d000000, 0x00000000, 0x00000000, 0x00000000, /* def c1, 1/32, 0, 0, 0*/
5084         0x05000030, 0xf00f0000, 0x00000004, 0x00000000, 0x00000002, 0x00000000, /* defi i0, 4, 0, 2, 0  */
5085         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0           */
5086         0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0          */
5087         0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0          */
5088         0x03000002, 0x800f0000, 0x80e40000, 0xa0e40001,                         /* add r0, r0, c1       */
5089         0x0000001d,                                                             /* endloop              */
5090         0x0000001d,                                                             /* endloop              */
5091         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0          */
5092         0x0000ffff                                                              /* end                  */
5093     };
5094     IDirect3DPixelShader9 *shader;
5095     HRESULT hr;
5096     DWORD color;
5097     const float quad[] = {
5098         -1.0,   -1.0,   0.1,
5099          1.0,   -1.0,   0.1,
5100         -1.0,    1.0,   0.1,
5101          1.0,    1.0,   0.1
5102     };
5103
5104     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
5105     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed with %08x\n", hr);
5106     hr = IDirect3DDevice9_SetPixelShader(device, shader);
5107     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with %08x\n", hr);
5108     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5109     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
5110     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 0.0, 0);
5111     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5112
5113     hr = IDirect3DDevice9_BeginScene(device);
5114     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5115     if(SUCCEEDED(hr))
5116     {
5117         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
5118         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5119         hr = IDirect3DDevice9_EndScene(device);
5120         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5121     }
5122     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5123     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5124
5125     color = getPixelColor(device, 360, 240);
5126     ok(color == 0x007f0000 || color == 0x00800000 || color == 0x00810000,
5127        "Nested loop test returned color 0x%08x, expected 0x00800000\n", color);
5128
5129     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5130     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with %08x\n", hr);
5131     IDirect3DPixelShader9_Release(shader);
5132 }
5133
5134 struct varying_test_struct
5135 {
5136     const DWORD             *shader_code;
5137     IDirect3DPixelShader9   *shader;
5138     DWORD                   color, color_rhw;
5139     const char              *name;
5140     BOOL                    todo, todo_rhw;
5141 };
5142
5143 struct hugeVertex
5144 {
5145     float pos_x,        pos_y,      pos_z,      rhw;
5146     float weight_1,     weight_2,   weight_3,   weight_4;
5147     float index_1,      index_2,    index_3,    index_4;
5148     float normal_1,     normal_2,   normal_3,   normal_4;
5149     float fog_1,        fog_2,      fog_3,      fog_4;
5150     float texcoord_1,   texcoord_2, texcoord_3, texcoord_4;
5151     float tangent_1,    tangent_2,  tangent_3,  tangent_4;
5152     float binormal_1,   binormal_2, binormal_3, binormal_4;
5153     float depth_1,      depth_2,    depth_3,    depth_4;
5154     DWORD diffuse, specular;
5155 };
5156
5157 static void fixed_function_varying_test(IDirect3DDevice9 *device) {
5158     /* dcl_position: fails to compile */
5159     const DWORD blendweight_code[] = {
5160         0xffff0300,                             /* ps_3_0                   */
5161         0x0200001f, 0x80000001, 0x900f0000,     /* dcl_blendweight, v0      */
5162         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5163         0x0000ffff                              /* end                      */
5164     };
5165     const DWORD blendindices_code[] = {
5166         0xffff0300,                             /* ps_3_0                   */
5167         0x0200001f, 0x80000002, 0x900f0000,     /* dcl_blendindices, v0     */
5168         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5169         0x0000ffff                              /* end                      */
5170     };
5171     const DWORD normal_code[] = {
5172         0xffff0300,                             /* ps_3_0                   */
5173         0x0200001f, 0x80000003, 0x900f0000,     /* dcl_normal, v0           */
5174         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5175         0x0000ffff                              /* end                      */
5176     };
5177     /* psize: fails? */
5178     const DWORD texcoord0_code[] = {
5179         0xffff0300,                             /* ps_3_0                   */
5180         0x0200001f, 0x80000005, 0x900f0000,     /* dcl_texcoord0, v0        */
5181         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5182         0x0000ffff                              /* end                      */
5183     };
5184     const DWORD tangent_code[] = {
5185         0xffff0300,                             /* ps_3_0                   */
5186         0x0200001f, 0x80000006, 0x900f0000,     /* dcl_tangent, v0          */
5187         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5188         0x0000ffff                              /* end                      */
5189     };
5190     const DWORD binormal_code[] = {
5191         0xffff0300,                             /* ps_3_0                   */
5192         0x0200001f, 0x80000007, 0x900f0000,     /* dcl_binormal, v0         */
5193         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5194         0x0000ffff                              /* end                      */
5195     };
5196     /* tessfactor: fails */
5197     /* positiont: fails */
5198     const DWORD color_code[] = {
5199         0xffff0300,                             /* ps_3_0                   */
5200         0x0200001f, 0x8000000a, 0x900f0000,     /* dcl_color0, v0           */
5201         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5202         0x0000ffff                              /* end                      */
5203     };
5204     const DWORD fog_code[] = {
5205         0xffff0300,                             /* ps_3_0                   */
5206         0x0200001f, 0x8000000b, 0x900f0000,     /* dcl_fog, v0              */
5207         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5208         0x0000ffff                              /* end                      */
5209     };
5210     const DWORD depth_code[] = {
5211         0xffff0300,                             /* ps_3_0                   */
5212         0x0200001f, 0x8000000c, 0x900f0000,     /* dcl_depth, v0            */
5213         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5214         0x0000ffff                              /* end                      */
5215     };
5216     const DWORD specular_code[] = {
5217         0xffff0300,                             /* ps_3_0                   */
5218         0x0200001f, 0x8001000a, 0x900f0000,     /* dcl_color1, v0           */
5219         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5220         0x0000ffff                              /* end                      */
5221     };
5222     /* sample: fails */
5223
5224     struct varying_test_struct tests[] = {
5225        {blendweight_code,       NULL,       0x00000000,     0x00191919,     "blendweight"   ,   FALSE,  TRUE  },
5226        {blendindices_code,      NULL,       0x00000000,     0x00000000,     "blendindices"  ,   FALSE,  FALSE },
5227        {normal_code,            NULL,       0x00000000,     0x004c4c4c,     "normal"        ,   FALSE,  TRUE  },
5228        /* Why does dx not forward the texcoord? */
5229        {texcoord0_code,         NULL,       0x00000000,     0x00808c8c,     "texcoord0"     ,   FALSE,  FALSE },
5230        {tangent_code,           NULL,       0x00000000,     0x00999999,     "tangent"       ,   FALSE,  TRUE  },
5231        {binormal_code,          NULL,       0x00000000,     0x00b2b2b2,     "binormal"      ,   FALSE,  TRUE  },
5232        {color_code,             NULL,       0x00e6e6e6,     0x00e6e6e6,     "color"         ,   FALSE,  FALSE },
5233        {fog_code,               NULL,       0x00000000,     0x00666666,     "fog"           ,   FALSE,  TRUE  },
5234        {depth_code,             NULL,       0x00000000,     0x00cccccc,     "depth"         ,   FALSE,  TRUE  },
5235        {specular_code,          NULL,       0x004488ff,     0x004488ff,     "specular"      ,   FALSE,  FALSE }
5236     };
5237     /* Declare a monster vertex type :-) */
5238     static const D3DVERTEXELEMENT9 decl_elements[] = {
5239         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
5240         {0,  16,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT,    0},
5241         {0,  32,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES,   0},
5242         {0,  48,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,         0},
5243         {0,  64,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_FOG,            0},
5244         {0,  80,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
5245         {0,  96,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT,        0},
5246         {0, 112,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL,       0},
5247         {0, 128,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_DEPTH,          0},
5248         {0, 144,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
5249         {0, 148,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          1},
5250         D3DDECL_END()
5251     };
5252     static const D3DVERTEXELEMENT9 decl_elements2[] = {
5253         {0,   0,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT,      0},
5254         {0,  16,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT,    0},
5255         {0,  32,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES,   0},
5256         {0,  48,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,         0},
5257         {0,  64,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_FOG,            0},
5258         {0,  80,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
5259         {0,  96,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT,        0},
5260         {0, 112,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL,       0},
5261         {0, 128,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_DEPTH,          0},
5262         {0, 144,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
5263         {0, 148,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          1},
5264         D3DDECL_END()
5265     };
5266     struct hugeVertex data[4] = {
5267         {
5268             -1.0,   -1.0,   0.1,    1.0,
5269              0.1,    0.1,   0.1,    0.1,
5270              0.2,    0.2,   0.2,    0.2,
5271              0.3,    0.3,   0.3,    0.3,
5272              0.4,    0.4,   0.4,    0.4,
5273              0.50,   0.55,  0.55,   0.55,
5274              0.6,    0.6,   0.6,    0.7,
5275              0.7,    0.7,   0.7,    0.6,
5276              0.8,    0.8,   0.8,    0.8,
5277              0xe6e6e6e6, /* 0.9 * 256 */
5278              0x224488ff  /* Nothing special */
5279         },
5280         {
5281              1.0,   -1.0,   0.1,    1.0,
5282              0.1,    0.1,   0.1,    0.1,
5283              0.2,    0.2,   0.2,    0.2,
5284              0.3,    0.3,   0.3,    0.3,
5285              0.4,    0.4,   0.4,    0.4,
5286              0.50,   0.55,  0.55,   0.55,
5287              0.6,    0.6,   0.6,    0.7,
5288              0.7,    0.7,   0.7,    0.6,
5289              0.8,    0.8,   0.8,    0.8,
5290              0xe6e6e6e6, /* 0.9 * 256 */
5291              0x224488ff /* Nothing special */
5292         },
5293         {
5294             -1.0,    1.0,   0.1,    1.0,
5295              0.1,    0.1,   0.1,    0.1,
5296              0.2,    0.2,   0.2,    0.2,
5297              0.3,    0.3,   0.3,    0.3,
5298              0.4,    0.4,   0.4,    0.4,
5299              0.50,   0.55,  0.55,   0.55,
5300              0.6,    0.6,   0.6,    0.7,
5301              0.7,    0.7,   0.7,    0.6,
5302              0.8,    0.8,   0.8,    0.8,
5303              0xe6e6e6e6, /* 0.9 * 256 */
5304              0x224488ff /* Nothing special */
5305         },
5306         {
5307              1.0,    1.0,   0.1,    1.0,
5308              0.1,    0.1,   0.1,    0.1,
5309              0.2,    0.2,   0.2,    0.2,
5310              0.3,    0.3,   0.3,    0.3,
5311              0.4,    0.4,   0.4,    0.4,
5312              0.50,   0.55,  0.55,   0.55,
5313              0.6,    0.6,   0.6,    0.7,
5314              0.7,    0.7,   0.7,    0.6,
5315              0.8,    0.8,   0.8,    0.8,
5316              0xe6e6e6e6, /* 0.9 * 256 */
5317              0x224488ff /* Nothing special */
5318         },
5319     };
5320     struct hugeVertex data2[4];
5321     IDirect3DVertexDeclaration9 *decl;
5322     IDirect3DVertexDeclaration9 *decl2;
5323     HRESULT hr;
5324     unsigned int i;
5325     DWORD color, r, g, b, r_e, g_e, b_e;
5326     BOOL drawok;
5327
5328     memcpy(data2, data, sizeof(data2));
5329     data2[0].pos_x = 0;     data2[0].pos_y = 0;
5330     data2[1].pos_x = 640;   data2[1].pos_y = 0;
5331     data2[2].pos_x = 0;     data2[2].pos_y = 480;
5332     data2[3].pos_x = 640;   data2[3].pos_y = 480;
5333
5334     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
5335     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
5336     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements2, &decl2);
5337     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
5338     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
5339     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
5340
5341     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
5342     {
5343         hr = IDirect3DDevice9_CreatePixelShader(device, tests[i].shader_code, &tests[i].shader);
5344         ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed for shader %s, hr = %08x\n",
5345            tests[i].name, hr);
5346     }
5347
5348     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
5349     {
5350         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
5351         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5352
5353         IDirect3DDevice9_SetPixelShader(device, tests[i].shader);
5354         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5355
5356         hr = IDirect3DDevice9_BeginScene(device);
5357         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5358         drawok = FALSE;
5359         if(SUCCEEDED(hr))
5360         {
5361             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, data, sizeof(data[0]));
5362             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed (%08x)\n", hr);
5363             drawok = SUCCEEDED(hr);
5364             hr = IDirect3DDevice9_EndScene(device);
5365             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5366         }
5367         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5368         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5369
5370         /* Some drivers reject the combination of ps_3_0 and fixed function vertex processing. Accept
5371          * the failure and do not check the color if it failed
5372          */
5373         if(!drawok) {
5374             continue;
5375         }
5376
5377         color = getPixelColor(device, 360, 240);
5378         r = color & 0x00ff0000 >> 16;
5379         g = color & 0x0000ff00 >>  8;
5380         b = color & 0x000000ff;
5381         r_e = tests[i].color & 0x00ff0000 >> 16;
5382         g_e = tests[i].color & 0x0000ff00 >>  8;
5383         b_e = tests[i].color & 0x000000ff;
5384
5385         if(tests[i].todo) {
5386             todo_wine ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
5387                          "Test %s returned color 0x%08x, expected 0x%08x(todo)\n",
5388                          tests[i].name, color, tests[i].color);
5389         } else {
5390             ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
5391                "Test %s returned color 0x%08x, expected 0x%08x\n",
5392                tests[i].name, color, tests[i].color);
5393         }
5394     }
5395
5396     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl2);
5397     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
5398     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
5399     {
5400         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
5401         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5402
5403         IDirect3DDevice9_SetPixelShader(device, tests[i].shader);
5404         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5405
5406         hr = IDirect3DDevice9_BeginScene(device);
5407         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5408         if(SUCCEEDED(hr))
5409         {
5410             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, data2, sizeof(data2[0]));
5411             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5412             hr = IDirect3DDevice9_EndScene(device);
5413             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5414         }
5415         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5416         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5417
5418         color = getPixelColor(device, 360, 240);
5419         r = color & 0x00ff0000 >> 16;
5420         g = color & 0x0000ff00 >>  8;
5421         b = color & 0x000000ff;
5422         r_e = tests[i].color_rhw & 0x00ff0000 >> 16;
5423         g_e = tests[i].color_rhw & 0x0000ff00 >>  8;
5424         b_e = tests[i].color_rhw & 0x000000ff;
5425
5426         if(tests[i].todo_rhw) {
5427             /* This isn't a weekend's job to fix, ignore the problem for now. Needs a replacement
5428              * pipeline
5429              */
5430             todo_wine ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
5431                          "Test %s returned color 0x%08x, expected 0x%08x(todo)\n",
5432                          tests[i].name, color, tests[i].color_rhw);
5433         } else {
5434             ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
5435                "Test %s returned color 0x%08x, expected 0x%08x\n",
5436                tests[i].name, color, tests[i].color_rhw);
5437         }
5438     }
5439
5440     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
5441     {
5442         IDirect3DPixelShader9_Release(tests[i].shader);
5443     }
5444
5445     IDirect3DVertexDeclaration9_Release(decl2);
5446     IDirect3DVertexDeclaration9_Release(decl);
5447 }
5448
5449 static void vshader_version_varying_test(IDirect3DDevice9 *device) {
5450     static const DWORD ps_code[] = {
5451     0xffff0300,                                                             /* ps_3_0                       */
5452     0x05000030, 0xf00f0000, 0x00000003, 0x00000003, 0x00000001, 0x00000000, /* defi i0, 3, 3, 1, 0          */
5453     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0   */
5454     0x0200001f, 0x8001000a, 0x900f0003,                                     /* dcl_color1 v3                */
5455     0x0200001f, 0x8000000b, 0x900f0004,                                     /* dcl_fog v4                   */
5456     0x0200001f, 0x80030005, 0x900f0005,                                     /* dcl_texcoord3 v5             */
5457     0x0200001f, 0x80000003, 0x900f0006,                                     /* dcl_normal v6                */
5458     0x0200001f, 0x80000006, 0x900f0007,                                     /* dcl_tangent v7               */
5459     0x0200001f, 0x80000001, 0x900f0008,                                     /* dcl_blendweight v8           */
5460     0x0200001f, 0x8000000c, 0x900f0009,                                     /* dcl_depth v9                 */
5461
5462     0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                   */
5463     0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0                  */
5464     0x04000002, 0x800f0000, 0x80e40000, 0x90e42000, 0xf0e40800,             /* add r0, r0, v0[aL]           */
5465     0x0000001d,                                                             /* endloop                      */
5466     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
5467     0x0000ffff                                                              /* end                          */
5468     };
5469     static const DWORD vs_1_code[] = {
5470     0xfffe0101,                                                             /* vs_1_1                       */
5471     0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
5472     0x00000051, 0xa00f0000, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.1, 0.0, 0.0, 0.0   */
5473     0x00000051, 0xa00f0001, 0x00000000, 0x3e4ccccd, 0x00000000, 0x00000000, /* def c1, 0.0, 0.2, 0.0, 0.0   */
5474     0x00000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3ecccccd, 0x00000000, /* def c2, 0.0, 0.0, 0.4, 0.0   */
5475     0x00000051, 0xa00f0003, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 1.0, 1.0, 1.0, 1.0   */
5476     0x00000001, 0xd00f0000, 0xa0e40002,                                     /* mov oD0, c2                  */
5477     0x00000001, 0xd00f0001, 0xa0e40000,                                     /* mov oD1, c0                  */
5478     0x00000001, 0xc00f0001, 0xa0550001,                                     /* mov oFog, c1.g               */
5479     0x00000001, 0xe00f0000, 0xa0e40003,                                     /* mov oT0, c3                  */
5480     0x00000001, 0xe00f0001, 0xa0e40003,                                     /* mov oT1, c3                  */
5481     0x00000001, 0xe00f0002, 0xa0e40003,                                     /* mov oT2, c3                  */
5482     0x00000001, 0xe00f0003, 0xa0e40002,                                     /* mov oT3, c2                  */
5483     0x00000001, 0xe00f0004, 0xa0e40003,                                     /* mov oT4, c3                  */
5484     0x00000001, 0xe00f0005, 0xa0e40003,                                     /* mov oT5, c3                  */
5485     0x00000001, 0xe00f0006, 0xa0e40003,                                     /* mov oT6, c3                  */
5486     0x00000001, 0xe00f0007, 0xa0e40003,                                     /* mov oT7, c3                  */
5487     0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
5488     0x0000ffff
5489     };
5490     DWORD vs_2_code[] = {
5491     0xfffe0200,                                                             /* vs_2_0                       */
5492     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
5493     0x05000051, 0xa00f0000, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.1, 0.0, 0.0, 0.0   */
5494     0x05000051, 0xa00f0001, 0x00000000, 0x3e4ccccd, 0x00000000, 0x00000000, /* def c1, 0.0, 0.2, 0.0, 0.0   */
5495     0x05000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3ecccccd, 0x00000000, /* def c2, 0.0, 0.0, 0.4, 0.0   */
5496     0x05000051, 0xa00f0003, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 1.0, 1.0, 1.0, 1.0   */
5497     0x02000001, 0xd00f0000, 0xa0e40002,                                     /* mov oD0, c2                  */
5498     0x02000001, 0xd00f0001, 0xa0e40000,                                     /* mov oD1, c0                  */
5499     0x02000001, 0xc00f0001, 0xa0550001,                                     /* mov oFog, c1.g               */
5500     0x02000001, 0xe00f0000, 0xa0e40003,                                     /* mov oT0, c3                  */
5501     0x02000001, 0xe00f0001, 0xa0e40003,                                     /* mov oT1, c3                  */
5502     0x02000001, 0xe00f0002, 0xa0e40003,                                     /* mov oT2, c3                  */
5503     0x02000001, 0xe00f0003, 0xa0e40002,                                     /* mov oT3, c2                  */
5504     0x02000001, 0xe00f0004, 0xa0e40003,                                     /* mov oT4, c3                  */
5505     0x02000001, 0xe00f0005, 0xa0e40003,                                     /* mov oT5, c3                  */
5506     0x02000001, 0xe00f0006, 0xa0e40003,                                     /* mov oT6, c3                  */
5507     0x02000001, 0xe00f0007, 0xa0e40003,                                     /* mov oT7, c3                  */
5508     0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
5509     0x0000ffff                                                              /* end                          */
5510     };
5511     /* TODO: Define normal, tangent, blendweight and depth here */
5512     static const DWORD vs_3_code[] = {
5513     0xfffe0300,                                                             /* vs_3_0                       */
5514     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
5515     0x0200001f, 0x8001000a, 0xe00f0009,                                     /* dcl_color1 o9                */
5516     0x0200001f, 0x8000000b, 0xe00f0002,                                     /* dcl_fog o2                   */
5517     0x0200001f, 0x80030005, 0xe00f0005,                                     /* dcl_texcoord3 o5             */
5518     0x0200001f, 0x80000000, 0xe00f000b,                                     /* dcl_position o11             */
5519     0x05000051, 0xa00f0000, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.1, 0.0, 0.0, 0.0   */
5520     0x05000051, 0xa00f0001, 0x00000000, 0x3e4ccccd, 0x00000000, 0x00000000, /* def c1, 0.0, 0.2, 0.0, 0.0   */
5521     0x05000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3ecccccd, 0x00000000, /* def c2, 0.0, 0.0, 0.4, 0.0   */
5522     0x05000051, 0xa00f0003, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 1.0, 1.0, 1.0, 1.0   */
5523     0x02000001, 0xe00f0009, 0xa0e40000,                                     /* mov o9, c0                   */
5524     0x02000001, 0xe00f0002, 0xa0e40001,                                     /* mov o2, c1                   */
5525     0x02000001, 0xe00f0005, 0xa0e40002,                                     /* mov o5, c2                   */
5526     0x02000001, 0xe00f000b, 0x90e40000,                                     /* mov o11, v0                  */
5527     0x0000ffff                                                              /* end                          */
5528     };
5529     float quad1[] =  {
5530         -1.0,   -1.0,   0.1,
5531          0.0,   -1.0,   0.1,
5532         -1.0,    0.0,   0.1,
5533          0.0,    0.0,   0.1
5534     };
5535     float quad2[] =  {
5536          0.0,   -1.0,   0.1,
5537          1.0,   -1.0,   0.1,
5538          0.0,    0.0,   0.1,
5539          1.0,    0.0,   0.1
5540     };
5541     float quad3[] =  {
5542         -1.0,    0.0,   0.1,
5543          0.0,    0.0,   0.1,
5544         -1.0,    1.0,   0.1,
5545          0.0,    1.0,   0.1
5546     };
5547
5548     HRESULT hr;
5549     DWORD color;
5550     IDirect3DPixelShader9 *pixelshader = NULL;
5551     IDirect3DVertexShader9 *vs_1_shader = NULL;
5552     IDirect3DVertexShader9 *vs_2_shader = NULL;
5553     IDirect3DVertexShader9 *vs_3_shader = NULL;
5554
5555     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff110000, 0.0, 0);
5556
5557     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code, &pixelshader);
5558     ok(hr == D3D_OK, "IDirect3DDevice_CreatePixelShader returned %08x\n", hr);
5559     hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_code, &vs_1_shader);
5560     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5561     hr = IDirect3DDevice9_CreateVertexShader(device, vs_2_code, &vs_2_shader);
5562     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5563     hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_code, &vs_3_shader);
5564     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5565     hr = IDirect3DDevice9_SetPixelShader(device, pixelshader);
5566     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5567     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5568
5569     hr = IDirect3DDevice9_BeginScene(device);
5570     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5571     if(SUCCEEDED(hr))
5572     {
5573         hr = IDirect3DDevice9_SetVertexShader(device, vs_1_shader);
5574         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5575         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 3);
5576         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5577
5578         hr = IDirect3DDevice9_SetVertexShader(device, vs_2_shader);
5579         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5580         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2,  quad2, sizeof(float) * 3);
5581         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5582
5583         hr = IDirect3DDevice9_SetVertexShader(device, vs_3_shader);
5584         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5585         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 3);
5586         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5587
5588         hr = IDirect3DDevice9_EndScene(device);
5589         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5590     }
5591     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5592     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5593
5594     color = getPixelColor(device, 160, 120);
5595     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x1a, 0x34, 0x67), 1),
5596        "vs_3_0 returned color 0x%08x, expected 0x00193366\n", color);
5597     color = getPixelColor(device, 160, 360);
5598     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x4d, 0x00, 0x67), 1),
5599        "vs_1_1 returned color 0x%08x, expected 0x004c0066\n", color);
5600     color = getPixelColor(device, 480, 360);
5601     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x4d, 0x00, 0x67), 1),
5602        "vs_2_0 returned color 0x%08x, expected 0x004c0066\n", color);
5603
5604     /* cleanup */
5605     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5606     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5607     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
5608     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5609     if(pixelshader) IDirect3DPixelShader9_Release(pixelshader);
5610     if(vs_1_shader) IDirect3DVertexShader9_Release(vs_1_shader);
5611     if(vs_2_shader) IDirect3DVertexShader9_Release(vs_2_shader);
5612     if(vs_3_shader) IDirect3DVertexShader9_Release(vs_3_shader);
5613 }
5614
5615 static void pshader_version_varying_test(IDirect3DDevice9 *device) {
5616     static const DWORD vs_code[] = {
5617     0xfffe0300,                                                             /* vs_3_0                       */
5618     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
5619     0x0200001f, 0x80000000, 0xe00f0000,                                     /* dcl_position o0              */
5620     0x0200001f, 0x8000000a, 0xe00f0001,                                     /* dcl_color0 o1                */
5621     0x0200001f, 0x80000005, 0xe00f0002,                                     /* dcl_texcoord0 o2             */
5622     0x0200001f, 0x8000000b, 0xe00f0003,                                     /* dcl_fog o3                   */
5623     0x0200001f, 0x80000003, 0xe00f0004,                                     /* dcl_normal o4                */
5624     0x0200001f, 0x8000000c, 0xe00f0005,                                     /* dcl_depth o5                 */
5625     0x0200001f, 0x80000006, 0xe00f0006,                                     /* dcl_tangent o6               */
5626     0x0200001f, 0x80000001, 0xe00f0007,                                     /* dcl_blendweight o7           */
5627     0x05000051, 0xa00f0001, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c1, 0.1, 0.0, 0.0, 0.0   */
5628     0x05000051, 0xa00f0002, 0x00000000, 0x3e4ccccd, 0x00000000, 0x3f800000, /* def c2, 0.0, 0.2, 0.0, 1.0   */
5629     0x05000051, 0xa00f0003, 0x3ecccccd, 0x3f59999a, 0x3f666666, 0x00000000, /* def c3, 0.4, 0.85,0.9, 0.0   */
5630     0x05000051, 0xa00f0000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c0, 1.0, 1.0, 1.0, 1.0   */
5631
5632     0x02000001, 0xe00f0000, 0x90e40000,                                     /* mov o0, v0                   */
5633     0x02000001, 0xe00f0001, 0xa0e40001,                                     /* mov o1, c1                   */
5634     0x02000001, 0xe00f0002, 0xa0e40002,                                     /* mov o2, c2                   */
5635     0x02000001, 0xe00f0003, 0xa0e40003,                                     /* mov o3, c3                   */
5636     0x02000001, 0xe00f0004, 0xa0e40000,                                     /* mov o4, c0                   */
5637     0x02000001, 0xe00f0005, 0xa0e40000,                                     /* mov o5, c0                   */
5638     0x02000001, 0xe00f0006, 0xa0e40000,                                     /* mov o6, c0                   */
5639     0x02000001, 0xe00f0007, 0xa0e40000,                                     /* mov o7, c0                   */
5640     0x0000ffff                                                              /* end                          */
5641     };
5642     static const DWORD ps_1_code[] = {
5643     0xffff0104,                                                             /* ps_1_4                       */
5644     0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0   */
5645     0x00000040, 0x80070001, 0xb0e40000,                                     /* texcrd r1.xyz, t0            */
5646     0x00000001, 0x80080001, 0xa0ff0000,                                     /* mov r1.a, c0.a               */
5647     0x00000002, 0x800f0000, 0x90e40000, 0x80e40001,                         /* add r0, v0, r1               */
5648     0x0000ffff                                                              /* end                          */
5649     };
5650     static const DWORD ps_2_code[] = {
5651     0xffff0200,                                                             /* ps_2_0                       */
5652     0x0200001f, 0x80000000, 0xb00f0000,                                     /* dcl t0                       */
5653     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl v0                       */
5654     0x0200001f, 0x80000000, 0x900f0001,                                     /* dcl v1                       */
5655
5656     0x02000001, 0x800f0000, 0x90e40000,                                     /* mov r0, v0                   */
5657     0x03000002, 0x800f0000, 0x80e40000,0xb0e40000,                          /* add r0, r0, t0               */
5658     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
5659     0x0000ffff                                                              /* end                          */
5660     };
5661     static const DWORD ps_3_code[] = {
5662     0xffff0300,                                                             /* ps_3_0                       */
5663     0x0200001f, 0x80000005, 0x900f0000,                                     /* dcl_texcoord0 v0             */
5664     0x0200001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                */
5665     0x0200001f, 0x8000000b, 0x900f0002,                                     /* dcl_fog v2                   */
5666
5667     0x02000001, 0x800f0000, 0x90e40000,                                     /* mov r0, v0                   */
5668     0x03000002, 0x800f0000, 0x80e40000, 0x90e40001,                         /* add r0, r0, v1               */
5669     0x03000002, 0x800f0000, 0x80e40000, 0x90e40002,                         /* mov r0, r0, v2               */
5670     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
5671     0x0000ffff                                                              /* end                          */
5672     };
5673
5674     float quad1[] =  {
5675         -1.0,   -1.0,   0.1,
5676          0.0,   -1.0,   0.1,
5677         -1.0,    0.0,   0.1,
5678          0.0,    0.0,   0.1
5679     };
5680     float quad2[] =  {
5681          0.0,   -1.0,   0.1,
5682          1.0,   -1.0,   0.1,
5683          0.0,    0.0,   0.1,
5684          1.0,    0.0,   0.1
5685     };
5686     float quad3[] =  {
5687         -1.0,    0.0,   0.1,
5688          0.0,    0.0,   0.1,
5689         -1.0,    1.0,   0.1,
5690          0.0,    1.0,   0.1
5691     };
5692     float quad4[] =  {
5693          0.0,    0.0,   0.1,
5694          1.0,    0.0,   0.1,
5695          0.0,    1.0,   0.1,
5696          1.0,    1.0,   0.1
5697     };
5698
5699     HRESULT hr;
5700     DWORD color;
5701     IDirect3DVertexShader9 *vertexshader = NULL;
5702     IDirect3DPixelShader9 *ps_1_shader = NULL;
5703     IDirect3DPixelShader9 *ps_2_shader = NULL;
5704     IDirect3DPixelShader9 *ps_3_shader = NULL;
5705     IDirect3DTexture9 *texture = NULL;
5706     D3DLOCKED_RECT lr;
5707     unsigned int x, y;
5708
5709     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
5710
5711     hr = IDirect3DDevice9_CreateTexture(device, 512,  512, 1, 0, D3DFMT_A16B16G16R16, D3DPOOL_MANAGED, &texture, NULL);
5712     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
5713     if(FAILED(hr)) {
5714         skip("D3DFMT_A16B16G16R16 textures not supported\n");
5715         return;
5716     }
5717     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
5718     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %08x\n", hr);
5719     for(y = 0; y < 512; y++) {
5720         for(x = 0; x < 512; x++) {
5721             double r_f = (double) x / (double) 512;
5722             double g_f = (double) y / (double) 512;
5723             unsigned short *dst = (unsigned short *) (((unsigned char *) lr.pBits) + y * lr.Pitch + x * 8);
5724             unsigned short r = (unsigned short) (r_f * 65535.0);
5725             unsigned short g = (unsigned short) (g_f * 65535.0);
5726             dst[0] = r;
5727             dst[1] = g;
5728             dst[2] = 0;
5729             dst[3] = 65535;
5730         }
5731     }
5732     hr = IDirect3DTexture9_UnlockRect(texture, 0);
5733     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect returned %08x\n", hr);
5734
5735     hr = IDirect3DDevice9_CreateVertexShader(device, vs_code, &vertexshader);
5736     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5737     hr = IDirect3DDevice9_CreatePixelShader(device, ps_1_code, &ps_1_shader);
5738     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5739     hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_code, &ps_2_shader);
5740     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5741     hr = IDirect3DDevice9_CreatePixelShader(device, ps_3_code, &ps_3_shader);
5742     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5743     hr = IDirect3DDevice9_SetVertexShader(device, vertexshader);
5744     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5745     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5746
5747     hr = IDirect3DDevice9_BeginScene(device);
5748     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5749     if(SUCCEEDED(hr))
5750     {
5751         hr = IDirect3DDevice9_SetPixelShader(device, ps_1_shader);
5752         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5753         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 3);
5754         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5755
5756         hr = IDirect3DDevice9_SetPixelShader(device, ps_2_shader);
5757         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5758         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2,  quad2, sizeof(float) * 3);
5759         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5760
5761         hr = IDirect3DDevice9_SetPixelShader(device, ps_3_shader);
5762         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5763         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 3);
5764         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5765
5766         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5767         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5768         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
5769         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
5770         hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
5771         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
5772         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
5773         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
5774         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 3);
5775         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5776
5777         hr = IDirect3DDevice9_EndScene(device);
5778         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5779     }
5780     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5781     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5782
5783     color = getPixelColor(device, 160, 120);
5784     ok((color & 0x00ff0000) >= 0x00790000 && (color & 0x00ff0000) <= 0x00810000 &&
5785        (color & 0x0000ff00) == 0x0000ff00 &&
5786        (color & 0x000000ff) >= 0x000000e4 && (color & 0x000000ff) <= 0x000000e6,
5787        "ps_3_0 returned color 0x%08x, expected 0x0080ffe5\n", color);
5788     color = getPixelColor(device, 160, 360);
5789     ok((color & 0x00ff0000) >= 0x00190000 && (color & 0x00ff0000) <= 0x00210000 &&
5790        (color & 0x0000ff00) >= 0x00003300 && (color & 0x0000ff00) <= 0x00003400 &&
5791        (color & 0x000000ff) == 0x00000000,
5792        "ps_1_4 returned color 0x%08x, expected 0x00203300\n", color);
5793     color = getPixelColor(device, 480, 360);
5794     ok((color & 0x00ff0000) >= 0x00190000 && (color & 0x00ff0000) <= 0x00210000 &&
5795        (color & 0x0000ff00) >= 0x00003200 && (color & 0x0000ff00) <= 0x00003400 &&
5796        (color & 0x000000ff) == 0x00000000,
5797        "ps_2_0 returned color 0x%08x, expected 0x00203300\n", color);
5798     color = getPixelColor(device, 480, 160);
5799     ok( color == 0x00ffffff /* Nvidia driver garbage with HW vp */ || (
5800        (color & 0x00ff0000) >= 0x00190000 && (color & 0x00ff0000) <= 0x00210000 &&
5801        (color & 0x0000ff00) >= 0x00003200 && (color & 0x0000ff00) <= 0x00003400 &&
5802        (color & 0x000000ff) == 0x00000000),
5803        "fixed function fragment processing returned color 0x%08x, expected 0x00203300\n", color);
5804
5805     /* cleanup */
5806     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
5807     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
5808     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5809     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5810     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
5811     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5812     if(vertexshader) IDirect3DVertexShader9_Release(vertexshader);
5813     if(ps_1_shader) IDirect3DPixelShader9_Release(ps_1_shader);
5814     if(ps_2_shader) IDirect3DPixelShader9_Release(ps_2_shader);
5815     if(ps_3_shader) IDirect3DPixelShader9_Release(ps_3_shader);
5816     if(texture) IDirect3DTexture9_Release(texture);
5817 }
5818
5819 static void test_compare_instructions(IDirect3DDevice9 *device)
5820 {
5821     DWORD shader_sge_vec_code[] = {
5822         0xfffe0101,                                         /* vs_1_1                   */
5823         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
5824         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
5825         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
5826         0x0000000d, 0xd00f0000, 0x80e40000, 0xa0e40001,     /* sge oD0, r0, c1          */
5827         0x0000ffff                                          /* end                      */
5828     };
5829     DWORD shader_slt_vec_code[] = {
5830         0xfffe0101,                                         /* vs_1_1                   */
5831         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
5832         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
5833         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
5834         0x0000000c, 0xd00f0000, 0x80e40000, 0xa0e40001,     /* slt oD0, r0, c1          */
5835         0x0000ffff                                          /* end                      */
5836     };
5837     DWORD shader_sge_scalar_code[] = {
5838         0xfffe0101,                                         /* vs_1_1                   */
5839         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
5840         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
5841         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
5842         0x0000000d, 0xd0010000, 0x80000000, 0xa0550001,     /* slt oD0.r, r0.r, c1.b    */
5843         0x0000000d, 0xd0020000, 0x80550000, 0xa0aa0001,     /* slt oD0.g, r0.g, c1.r    */
5844         0x0000000d, 0xd0040000, 0x80aa0000, 0xa0000001,     /* slt oD0.b, r0.b, c1.g    */
5845         0x0000ffff                                          /* end                      */
5846     };
5847     DWORD shader_slt_scalar_code[] = {
5848         0xfffe0101,                                         /* vs_1_1                   */
5849         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
5850         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
5851         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
5852         0x0000000c, 0xd0010000, 0x80000000, 0xa0aa0001,     /* slt oD0.r, r0.r, c1.b    */
5853         0x0000000c, 0xd0020000, 0x80550000, 0xa0000001,     /* slt oD0.g, r0.g, c1.r    */
5854         0x0000000c, 0xd0040000, 0x80aa0000, 0xa0550001,     /* slt oD0.b, r0.b, c1.g    */
5855         0x0000ffff                                          /* end                      */
5856     };
5857     IDirect3DVertexShader9 *shader_sge_vec;
5858     IDirect3DVertexShader9 *shader_slt_vec;
5859     IDirect3DVertexShader9 *shader_sge_scalar;
5860     IDirect3DVertexShader9 *shader_slt_scalar;
5861     HRESULT hr, color;
5862     float quad1[] =  {
5863         -1.0,   -1.0,   0.1,
5864          0.0,   -1.0,   0.1,
5865         -1.0,    0.0,   0.1,
5866          0.0,    0.0,   0.1
5867     };
5868     float quad2[] =  {
5869          0.0,   -1.0,   0.1,
5870          1.0,   -1.0,   0.1,
5871          0.0,    0.0,   0.1,
5872          1.0,    0.0,   0.1
5873     };
5874     float quad3[] =  {
5875         -1.0,    0.0,   0.1,
5876          0.0,    0.0,   0.1,
5877         -1.0,    1.0,   0.1,
5878          0.0,    1.0,   0.1
5879     };
5880     float quad4[] =  {
5881          0.0,    0.0,   0.1,
5882          1.0,    0.0,   0.1,
5883          0.0,    1.0,   0.1,
5884          1.0,    1.0,   0.1
5885     };
5886     const float const0[4] = {0.8, 0.2, 0.2, 0.2};
5887     const float const1[4] = {0.2, 0.8, 0.2, 0.2};
5888
5889     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
5890
5891     hr = IDirect3DDevice9_CreateVertexShader(device, shader_sge_vec_code, &shader_sge_vec);
5892     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5893     hr = IDirect3DDevice9_CreateVertexShader(device, shader_slt_vec_code, &shader_slt_vec);
5894     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5895     hr = IDirect3DDevice9_CreateVertexShader(device, shader_sge_scalar_code, &shader_sge_scalar);
5896     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5897     hr = IDirect3DDevice9_CreateVertexShader(device, shader_slt_scalar_code, &shader_slt_scalar);
5898     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5899     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, const0, 1);
5900     ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
5901     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, const1, 1);
5902     ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
5903     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5904     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetFVF failed (%08x)\n", hr);
5905
5906     hr = IDirect3DDevice9_BeginScene(device);
5907     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5908     if(SUCCEEDED(hr))
5909     {
5910         hr = IDirect3DDevice9_SetVertexShader(device, shader_sge_vec);
5911         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5912         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 3);
5913         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5914
5915         hr = IDirect3DDevice9_SetVertexShader(device, shader_slt_vec);
5916         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5917         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2,  quad2, sizeof(float) * 3);
5918         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5919
5920         hr = IDirect3DDevice9_SetVertexShader(device, shader_sge_scalar);
5921         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5922         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 3);
5923         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5924
5925         hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, const0, 1);
5926         ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
5927
5928         hr = IDirect3DDevice9_SetVertexShader(device, shader_slt_scalar);
5929         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5930         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 3);
5931         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5932
5933         hr = IDirect3DDevice9_EndScene(device);
5934         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5935     }
5936
5937     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5938     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5939     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
5940     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5941
5942     color = getPixelColor(device, 160, 360);
5943     ok(color == 0x00FF00FF, "Compare test: Quad 1(sge vec) returned color 0x%08x, expected 0x00FF00FF\n", color);
5944     color = getPixelColor(device, 480, 360);
5945     ok(color == 0x0000FF00, "Compare test: Quad 2(slt vec) returned color 0x%08x, expected 0x0000FF00\n", color);
5946     color = getPixelColor(device, 160, 120);
5947     ok(color == 0x00FFFFFF, "Compare test: Quad 3(sge scalar) returned color 0x%08x, expected 0x00FFFFFF\n", color);
5948     color = getPixelColor(device, 480, 160);
5949     ok(color == 0x000000ff, "Compare test: Quad 4(slt scalar) returned color 0x%08x, expected 0x000000ff\n", color);
5950
5951     IDirect3DVertexShader9_Release(shader_sge_vec);
5952     IDirect3DVertexShader9_Release(shader_slt_vec);
5953     IDirect3DVertexShader9_Release(shader_sge_scalar);
5954     IDirect3DVertexShader9_Release(shader_slt_scalar);
5955 }
5956
5957 static void test_vshader_input(IDirect3DDevice9 *device)
5958 {
5959     DWORD swapped_shader_code_3[] = {
5960         0xfffe0300,                                         /* vs_3_0               */
5961         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
5962         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
5963         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5964         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
5965         0x0200001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
5966         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
5967         0x02000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
5968         0x03000002, 0xe00f0001, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
5969         0x0000ffff                                          /* end                  */
5970     };
5971     DWORD swapped_shader_code_1[] = {
5972         0xfffe0101,                                         /* vs_1_1               */
5973         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5974         0x0000001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
5975         0x0000001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
5976         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov o0, v0           */
5977         0x00000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
5978         0x00000002, 0xd00f0000, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
5979         0x0000ffff                                          /* end                  */
5980     };
5981     DWORD swapped_shader_code_2[] = {
5982         0xfffe0200,                                         /* vs_2_0               */
5983         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5984         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
5985         0x0200001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
5986         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov o0, v0           */
5987         0x02000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
5988         0x03000002, 0xd00f0000, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
5989         0x0000ffff                                          /* end                  */
5990     };
5991     DWORD texcoord_color_shader_code_3[] = {
5992         0xfffe0300,                                         /* vs_3_0               */
5993         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
5994         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
5995         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5996         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
5997         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
5998         0x02000001, 0xe00f0001, 0x90e40001,                 /* mov o1, v1           */
5999         0x0000ffff                                          /* end                  */
6000     };
6001     DWORD texcoord_color_shader_code_2[] = {
6002         0xfffe0200,                                         /* vs_2_0               */
6003         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6004         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
6005         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
6006         0x02000001, 0xd00f0000, 0x90e40001,                 /* mov oD0, v1          */
6007         0x0000ffff                                          /* end                  */
6008     };
6009     DWORD texcoord_color_shader_code_1[] = {
6010         0xfffe0101,                                         /* vs_1_1               */
6011         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6012         0x0000001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
6013         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
6014         0x00000001, 0xd00f0000, 0x90e40001,                 /* mov oD0, v1          */
6015         0x0000ffff                                          /* end                  */
6016     };
6017     DWORD color_color_shader_code_3[] = {
6018         0xfffe0300,                                         /* vs_3_0               */
6019         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
6020         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
6021         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6022         0x0200001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
6023         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
6024         0x03000005, 0xe00f0001, 0xa0e40000, 0x90e40001,     /* mul o1, c0, v1       */
6025         0x0000ffff                                          /* end                  */
6026     };
6027     DWORD color_color_shader_code_2[] = {
6028         0xfffe0200,                                         /* vs_2_0               */
6029         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6030         0x0200001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
6031         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
6032         0x03000005, 0xd00f0000, 0xa0e40000, 0x90e40001,     /* mul oD0, c0, v1       */
6033         0x0000ffff                                          /* end                  */
6034     };
6035     DWORD color_color_shader_code_1[] = {
6036         0xfffe0101,                                         /* vs_1_1               */
6037         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6038         0x0000001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
6039         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
6040         0x00000005, 0xd00f0000, 0xa0e40000, 0x90e40001,     /* mul oD0, c0, v1       */
6041         0x0000ffff                                          /* end                  */
6042     };
6043     IDirect3DVertexShader9 *swapped_shader, *texcoord_color_shader, *color_color_shader;
6044     HRESULT hr;
6045     DWORD color;
6046     float quad1[] =  {
6047         -1.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6048          0.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6049         -1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6050          0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6051     };
6052     float quad2[] =  {
6053          0.0,   -1.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6054          1.0,   -1.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6055          0.0,    0.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6056          1.0,    0.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6057     };
6058     float quad3[] =  {
6059         -1.0,    0.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    1.0,    -1.0,   0.0,    0.0,
6060          0.0,    0.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    1.0,     0.0,   0.0,    0.0,
6061         -1.0,    1.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    0.0,    -1.0,   1.0,    0.0,
6062          0.0,    1.0,   0.1,   -1.0,    0.0,    0.0,    0.0,   -1.0,     0.0,   0.0,    0.0,
6063     };
6064     float quad4[] =  {
6065          0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6066          1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6067          0.0,    1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6068          1.0,    1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6069     };
6070     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd[] = {
6071         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6072         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6073         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
6074         D3DDECL_END()
6075     };
6076     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd_rightorder[] = {
6077         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6078         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
6079         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6080         D3DDECL_END()
6081     };
6082     static const D3DVERTEXELEMENT9 decl_elements_onetexcrd[] = {
6083         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6084         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6085         D3DDECL_END()
6086     };
6087     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd_wrongidx[] = {
6088         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6089         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
6090         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       2},
6091         D3DDECL_END()
6092     };
6093     static const D3DVERTEXELEMENT9 decl_elements_texcoord_color[] = {
6094         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6095         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6096         D3DDECL_END()
6097     };
6098     static const D3DVERTEXELEMENT9 decl_elements_color_color[] = {
6099         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6100         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6101         D3DDECL_END()
6102     };
6103     static const D3DVERTEXELEMENT9 decl_elements_color_ubyte[] = {
6104         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6105         {0,  12,  D3DDECLTYPE_UBYTE4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6106         D3DDECL_END()
6107     };
6108     static const D3DVERTEXELEMENT9 decl_elements_color_float[] = {
6109         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6110         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6111         D3DDECL_END()
6112     };
6113     IDirect3DVertexDeclaration9 *decl_twotexcrd, *decl_onetexcrd, *decl_twotex_wrongidx, *decl_twotexcrd_rightorder;
6114     IDirect3DVertexDeclaration9 *decl_texcoord_color, *decl_color_color, *decl_color_ubyte, *decl_color_float;
6115     unsigned int i;
6116     float normalize[4] = {1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0};
6117     float no_normalize[4] = {1.0, 1.0, 1.0, 1.0};
6118
6119     struct vertex quad1_color[] =  {
6120        {-1.0,   -1.0,   0.1,    0x00ff8040},
6121        { 0.0,   -1.0,   0.1,    0x00ff8040},
6122        {-1.0,    0.0,   0.1,    0x00ff8040},
6123        { 0.0,    0.0,   0.1,    0x00ff8040}
6124     };
6125     struct vertex quad2_color[] =  {
6126        { 0.0,   -1.0,   0.1,    0x00ff8040},
6127        { 1.0,   -1.0,   0.1,    0x00ff8040},
6128        { 0.0,    0.0,   0.1,    0x00ff8040},
6129        { 1.0,    0.0,   0.1,    0x00ff8040}
6130     };
6131     struct vertex quad3_color[] =  {
6132        {-1.0,    0.0,   0.1,    0x00ff8040},
6133        { 0.0,    0.0,   0.1,    0x00ff8040},
6134        {-1.0,    1.0,   0.1,    0x00ff8040},
6135        { 0.0,    1.0,   0.1,    0x00ff8040}
6136     };
6137     float quad4_color[] =  {
6138          0.0,    0.0,   0.1,    1.0,    1.0,    0.0,    0.0,
6139          1.0,    0.0,   0.1,    1.0,    1.0,    0.0,    1.0,
6140          0.0,    1.0,   0.1,    1.0,    1.0,    0.0,    0.0,
6141          1.0,    1.0,   0.1,    1.0,    1.0,    0.0,    1.0,
6142     };
6143
6144     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd, &decl_twotexcrd);
6145     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6146     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_onetexcrd, &decl_onetexcrd);
6147     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6148     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd_wrongidx, &decl_twotex_wrongidx);
6149     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6150     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd_rightorder, &decl_twotexcrd_rightorder);
6151     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6152
6153     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_texcoord_color, &decl_texcoord_color);
6154     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6155     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_color, &decl_color_color);
6156     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6157     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_ubyte, &decl_color_ubyte);
6158     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6159     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_float, &decl_color_float);
6160     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6161
6162     for(i = 1; i <= 3; i++) {
6163         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
6164         if(i == 3) {
6165             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_3, &swapped_shader);
6166             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6167         } else if(i == 2){
6168             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_2, &swapped_shader);
6169             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6170         } else if(i == 1) {
6171             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_1, &swapped_shader);
6172             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6173         }
6174
6175         hr = IDirect3DDevice9_BeginScene(device);
6176         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6177         if(SUCCEEDED(hr))
6178         {
6179             hr = IDirect3DDevice9_SetVertexShader(device, swapped_shader);
6180             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6181
6182             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd);
6183             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6184             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 11);
6185             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6186
6187             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_onetexcrd);
6188             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6189             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(float) * 11);
6190             if(i == 3 || i == 2) {
6191                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
6192             } else if(i == 1) {
6193                 /* Succeeds or fails, depending on SW or HW vertex processing */
6194                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x), i = 1\n", hr);
6195             }
6196
6197             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd_rightorder);
6198             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6199             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 11);
6200             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6201
6202             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotex_wrongidx);
6203             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6204             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 11);
6205             if(i == 3 || i == 2) {
6206                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
6207             } else if(i == 1) {
6208                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = 1\n", hr);
6209             }
6210
6211             hr = IDirect3DDevice9_EndScene(device);
6212             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6213         }
6214
6215         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6216         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6217
6218         if(i == 3 || i == 2) {
6219             color = getPixelColor(device, 160, 360);
6220             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x80), 1),
6221                "Input test: Quad 1(2crd) returned color 0x%08x, expected 0x00FFFF80\n", color);
6222
6223             /* The last value of the read but undefined stream is used, it is 0x00. The defined input is vec4(1, 0, 0, 0) */
6224             color = getPixelColor(device, 480, 360);
6225             ok(color == 0x00FFFF00 || color ==0x00FF0000,
6226                "Input test: Quad 2(1crd) returned color 0x%08x, expected 0x00FFFF00\n", color);
6227             color = getPixelColor(device, 160, 120);
6228             /* Same as above, accept both the last used value and 0.0 for the undefined streams */
6229             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x80), 1) || color == D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00),
6230                "Input test: Quad 3(2crd-wrongidx) returned color 0x%08x, expected 0x00FF0080\n", color);
6231
6232             color = getPixelColor(device, 480, 160);
6233             ok(color == 0x00000000, "Input test: Quad 4(2crd-rightorder) returned color 0x%08x, expected 0x00000000\n", color);
6234         } else if(i == 1) {
6235             color = getPixelColor(device, 160, 360);
6236             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x80), 1),
6237                "Input test: Quad 1(2crd) returned color 0x%08x, expected 0x00FFFF80\n", color);
6238             color = getPixelColor(device, 480, 360);
6239             /* Accept the clear color as well in this case, since SW VP returns an error */
6240             ok(color == 0x00FFFF00 || color == 0x00FF0000, "Input test: Quad 2(1crd) returned color 0x%08x, expected 0x00FFFF00\n", color);
6241             color = getPixelColor(device, 160, 120);
6242             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x80), 1) || color == D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00),
6243                "Input test: Quad 3(2crd-wrongidx) returned color 0x%08x, expected 0x00FF0080\n", color);
6244             color = getPixelColor(device, 480, 160);
6245             ok(color == 0x00000000, "Input test: Quad 4(2crd-rightorder) returned color 0x%08x, expected 0x00000000\n", color);
6246         }
6247
6248         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff808080, 0.0, 0);
6249         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
6250
6251         /* Now find out if the whole streams are re-read, or just the last active value for the
6252          * vertices is used.
6253          */
6254         hr = IDirect3DDevice9_BeginScene(device);
6255         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6256         if(SUCCEEDED(hr))
6257         {
6258             float quad1_modified[] =  {
6259                 -1.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,   -1.0,     0.0,   0.0,    0.0,
6260                  0.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.0,    0.0,
6261                 -1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,     0.0,  -1.0,    0.0,
6262                  0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,   -1.0,    -1.0,  -1.0,    0.0,
6263             };
6264             float quad2_modified[] =  {
6265                  0.0,   -1.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6266                  1.0,   -1.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6267                  0.0,    0.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6268                  1.0,    0.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6269             };
6270
6271             hr = IDirect3DDevice9_SetVertexShader(device, swapped_shader);
6272             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6273
6274             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd);
6275             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6276             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 3, quad1_modified, sizeof(float) * 11);
6277             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6278
6279             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_onetexcrd);
6280             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6281             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2_modified, sizeof(float) * 11);
6282             if(i == 3 || i == 2) {
6283                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
6284             } else if(i == 1) {
6285                 /* Succeeds or fails, depending on SW or HW vertex processing */
6286                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x), i = 1\n", hr);
6287             }
6288
6289             hr = IDirect3DDevice9_EndScene(device);
6290             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6291         }
6292         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6293         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6294
6295         color = getPixelColor(device, 480, 350);
6296         /* vs_1_1 may fail, accept the clear color. Some drivers also set the undefined streams to 0, accept that
6297          * as well.
6298          *
6299          * NOTE: This test fails on the reference rasterizer. In the refrast, the 4 vertices have different colors,
6300          * i.e., the whole old stream is read, and not just the last used attribute. Some games require that this
6301          * does *not* happen, otherwise they can crash because of a read from a bad pointer, so do not accept the
6302          * refrast's result.
6303          *
6304          * A test app for this behavior is Half Life 2 Episode 2 in dxlevel 95, and related games(Portal, TF2).
6305          */
6306         ok(color == 0x000000FF || color == 0x00808080 || color == 0x00000000,
6307            "Input test: Quad 2(different colors) returned color 0x%08x, expected 0x000000FF, 0x00808080 or 0x00000000\n", color);
6308         color = getPixelColor(device, 160, 120);
6309
6310         IDirect3DDevice9_SetVertexShader(device, NULL);
6311         IDirect3DDevice9_SetVertexDeclaration(device, NULL);
6312
6313         IDirect3DVertexShader9_Release(swapped_shader);
6314     }
6315
6316     for(i = 1; i <= 3; i++) {
6317         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
6318         if(i == 3) {
6319             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_3, &texcoord_color_shader);
6320             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6321             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_3, &color_color_shader);
6322             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6323         } else if(i == 2){
6324             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_2, &texcoord_color_shader);
6325             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6326             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_2, &color_color_shader);
6327             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6328         } else if(i == 1) {
6329             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_1, &texcoord_color_shader);
6330             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6331             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_1, &color_color_shader);
6332             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6333         }
6334
6335         hr = IDirect3DDevice9_BeginScene(device);
6336         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6337         if(SUCCEEDED(hr))
6338         {
6339             hr = IDirect3DDevice9_SetVertexShader(device, texcoord_color_shader);
6340             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6341             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_texcoord_color);
6342             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6343             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1_color, sizeof(quad1_color[0]));
6344             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6345
6346             hr = IDirect3DDevice9_SetVertexShader(device, color_color_shader);
6347             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6348
6349             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, normalize, 1);
6350             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6351             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_ubyte);
6352             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6353             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2_color, sizeof(quad2_color[0]));
6354             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6355
6356             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, no_normalize, 1);
6357             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6358             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_color);
6359             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6360             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3_color, sizeof(quad3_color[0]));
6361             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6362
6363             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_float);
6364             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6365             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4_color, sizeof(float) * 7);
6366             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6367
6368             hr = IDirect3DDevice9_EndScene(device);
6369             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6370         }
6371         IDirect3DDevice9_SetVertexShader(device, NULL);
6372         IDirect3DDevice9_SetVertexDeclaration(device, NULL);
6373
6374         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6375         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6376
6377         color = getPixelColor(device, 160, 360);
6378         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x80, 0x40), 1),
6379            "Input test: Quad 1(color-texcoord) returned color 0x%08x, expected 0x00ff8040\n", color);
6380         color = getPixelColor(device, 480, 360);
6381         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x40, 0x80, 0xff), 1),
6382            "Input test: Quad 2(color-ubyte) returned color 0x%08x, expected 0x004080ff\n", color);
6383         color = getPixelColor(device, 160, 120);
6384         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x80, 0x40), 1),
6385            "Input test: Quad 3(color-color) returned color 0x%08x, expected 0x00ff8040\n", color);
6386         color = getPixelColor(device, 480, 160);
6387         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00), 1),
6388            "Input test: Quad 4(color-float) returned color 0x%08x, expected 0x00FFFF00\n", color);
6389
6390         IDirect3DVertexShader9_Release(texcoord_color_shader);
6391         IDirect3DVertexShader9_Release(color_color_shader);
6392     }
6393
6394     IDirect3DVertexDeclaration9_Release(decl_twotexcrd);
6395     IDirect3DVertexDeclaration9_Release(decl_onetexcrd);
6396     IDirect3DVertexDeclaration9_Release(decl_twotex_wrongidx);
6397     IDirect3DVertexDeclaration9_Release(decl_twotexcrd_rightorder);
6398
6399     IDirect3DVertexDeclaration9_Release(decl_texcoord_color);
6400     IDirect3DVertexDeclaration9_Release(decl_color_color);
6401     IDirect3DVertexDeclaration9_Release(decl_color_ubyte);
6402     IDirect3DVertexDeclaration9_Release(decl_color_float);
6403 }
6404
6405 static void srgbtexture_test(IDirect3DDevice9 *device)
6406 {
6407     /* Fill a texture with 0x7f (~ .5), and then turn on the D3DSAMP_SRGBTEXTURE
6408      * texture stage state to render a quad using that texture.  The resulting
6409      * color components should be 0x36 (~ 0.21), per this formula:
6410      *    linear_color = ((srgb_color + 0.055) / 1.055) ^ 2.4
6411      * This is true where srgb_color > 0.04045.
6412      */
6413     IDirect3D9 *d3d = NULL;
6414     HRESULT hr;
6415     LPDIRECT3DTEXTURE9 texture = NULL;
6416     LPDIRECT3DSURFACE9 surface = NULL;
6417     D3DLOCKED_RECT lr;
6418     DWORD color;
6419     float quad[] = {
6420         -1.0,       1.0,       0.0,     0.0,    0.0,
6421          1.0,       1.0,       0.0,     1.0,    0.0,
6422         -1.0,      -1.0,       0.0,     0.0,    1.0,
6423          1.0,      -1.0,       0.0,     1.0,    1.0,
6424     };
6425
6426
6427     memset(&lr, 0, sizeof(lr));
6428     IDirect3DDevice9_GetDirect3D(device, &d3d);
6429     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6430                                     D3DUSAGE_QUERY_SRGBREAD, D3DRTYPE_TEXTURE,
6431                                     D3DFMT_A8R8G8B8) != D3D_OK) {
6432         skip("D3DFMT_A8R8G8B8 textures with SRGBREAD not supported\n");
6433         goto out;
6434     }
6435
6436     hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0,
6437                                         D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
6438                                         &texture, NULL);
6439     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
6440     if(!texture) {
6441         skip("Failed to create A8R8G8B8 texture with SRGBREAD\n");
6442         goto out;
6443     }
6444     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
6445     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
6446
6447     fill_surface(surface, 0xff7f7f7f);
6448     IDirect3DSurface9_Release(surface);
6449
6450     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
6451     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6452     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
6453     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
6454
6455     hr = IDirect3DDevice9_BeginScene(device);
6456     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
6457     if(SUCCEEDED(hr))
6458     {
6459         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, TRUE);
6460         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
6461
6462         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
6463         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
6464
6465
6466         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
6467         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with %08x\n", hr);
6468
6469         hr = IDirect3DDevice9_EndScene(device);
6470         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
6471     }
6472
6473     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6474     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
6475     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, FALSE);
6476     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
6477
6478     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6479     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6480
6481     color = getPixelColor(device, 320, 240);
6482     ok(color == 0x00363636 || color == 0x00373737, "srgb quad has color %08x, expected 0x00363636\n", color);
6483
6484 out:
6485     if(texture) IDirect3DTexture9_Release(texture);
6486     IDirect3D9_Release(d3d);
6487 }
6488
6489 static void shademode_test(IDirect3DDevice9 *device)
6490 {
6491     /* Render a quad and try all of the different fixed function shading models. */
6492     HRESULT hr;
6493     DWORD color0, color1;
6494     DWORD color0_gouraud = 0, color1_gouraud = 0;
6495     DWORD shademode = D3DSHADE_FLAT;
6496     DWORD primtype = D3DPT_TRIANGLESTRIP;
6497     LPVOID data = NULL;
6498     LPDIRECT3DVERTEXBUFFER9 vb_strip = NULL;
6499     LPDIRECT3DVERTEXBUFFER9 vb_list = NULL;
6500     UINT i, j;
6501     struct vertex quad_strip[] =
6502     {
6503         {-1.0f, -1.0f,  0.0f, 0xffff0000  },
6504         {-1.0f,  1.0f,  0.0f, 0xff00ff00  },
6505         { 1.0f, -1.0f,  0.0f, 0xff0000ff  },
6506         { 1.0f,  1.0f,  0.0f, 0xffffffff  }
6507     };
6508     struct vertex quad_list[] =
6509     {
6510         {-1.0f, -1.0f,  0.0f, 0xffff0000  },
6511         {-1.0f,  1.0f,  0.0f, 0xff00ff00  },
6512         { 1.0f, -1.0f,  0.0f, 0xff0000ff  },
6513
6514         {-1.0f,  1.0f,  0.0f, 0xff00ff00  },
6515         { 1.0f, -1.0f,  0.0f, 0xff0000ff  },
6516         { 1.0f,  1.0f,  0.0f, 0xffffffff  }
6517     };
6518
6519     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad_strip),
6520                                              0, 0, D3DPOOL_MANAGED, &vb_strip, NULL);
6521     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
6522     if (FAILED(hr)) goto bail;
6523
6524     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad_list),
6525                                              0, 0, D3DPOOL_MANAGED, &vb_list, NULL);
6526     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
6527     if (FAILED(hr)) goto bail;
6528
6529     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
6530     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6531
6532     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
6533     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
6534
6535     hr = IDirect3DVertexBuffer9_Lock(vb_strip, 0, sizeof(quad_strip), &data, 0);
6536     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
6537     memcpy(data, quad_strip, sizeof(quad_strip));
6538     hr = IDirect3DVertexBuffer9_Unlock(vb_strip);
6539     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
6540
6541     hr = IDirect3DVertexBuffer9_Lock(vb_list, 0, sizeof(quad_list), &data, 0);
6542     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
6543     memcpy(data, quad_list, sizeof(quad_list));
6544     hr = IDirect3DVertexBuffer9_Unlock(vb_list);
6545     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
6546
6547     /* Try it first with a TRIANGLESTRIP.  Do it with different geometry because
6548      * the color fixups we have to do for FLAT shading will be dependent on that. */
6549     hr = IDirect3DDevice9_SetStreamSource(device, 0, vb_strip, 0, sizeof(quad_strip[0]));
6550     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
6551
6552     /* First loop uses a TRIANGLESTRIP geometry, 2nd uses a TRIANGLELIST */
6553     for (j=0; j<2; j++) {
6554
6555         /* Inner loop just changes the D3DRS_SHADEMODE */
6556         for (i=0; i<3; i++) {
6557             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
6558             ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
6559
6560             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SHADEMODE, shademode);
6561             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6562
6563             hr = IDirect3DDevice9_BeginScene(device);
6564             ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
6565             if(SUCCEEDED(hr))
6566             {
6567                 hr = IDirect3DDevice9_DrawPrimitive(device, primtype, 0, 2);
6568                 ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed with %08x\n", hr);
6569
6570                 hr = IDirect3DDevice9_EndScene(device);
6571                 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
6572             }
6573
6574             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6575             ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6576
6577             /* Sample two spots from the output */
6578             color0 = getPixelColor(device, 100, 100); /* Inside first triangle */
6579             color1 = getPixelColor(device, 500, 350); /* Inside second triangle */
6580             switch(shademode) {
6581                 case D3DSHADE_FLAT:
6582                     /* Should take the color of the first vertex of each triangle */
6583                     todo_wine ok(color0 == 0x00ff0000, "FLAT shading has color0 %08x, expected 0x00ff0000 (todo)\n", color0);
6584                     todo_wine ok(color1 == 0x0000ff00, "FLAT shading has color1 %08x, expected 0x0000ff00 (todo)\n", color1);
6585                     shademode = D3DSHADE_GOURAUD;
6586                     break;
6587                 case D3DSHADE_GOURAUD:
6588                     /* Should be an interpolated blend */
6589
6590                     ok(color_match(color0, D3DCOLOR_ARGB(0x00, 0x0d, 0xca, 0x28), 2),
6591                        "GOURAUD shading has color0 %08x, expected 0x00dca28\n", color0);
6592                     ok(color_match(color1, D3DCOLOR_ARGB(0x00, 0x0d, 0x45, 0xc7), 2),
6593                        "GOURAUD shading has color1 %08x, expected 0x000d45c7\n", color1);
6594
6595                     color0_gouraud = color0;
6596                     color1_gouraud = color1;
6597
6598                     shademode = D3DSHADE_PHONG;
6599                     break;
6600                 case D3DSHADE_PHONG:
6601                     /* Should be the same as GOURAUD, since no hardware implements this */
6602                     ok(color_match(color0, D3DCOLOR_ARGB(0x00, 0x0d, 0xca, 0x28), 2),
6603                        "PHONG shading has color0 %08x, expected 0x000dca28\n", color0);
6604                     ok(color_match(color1, D3DCOLOR_ARGB(0x00, 0x0d, 0x45, 0xc7), 2),
6605                        "PHONG shading has color1 %08x, expected 0x000d45c7\n", color1);
6606
6607                     ok(color0 == color0_gouraud, "difference between GOURAUD and PHONG shading detected: %08x %08x\n",
6608                             color0_gouraud, color0);
6609                     ok(color1 == color1_gouraud, "difference between GOURAUD and PHONG shading detected: %08x %08x\n",
6610                             color1_gouraud, color1);
6611                     break;
6612             }
6613         }
6614         /* Now, do it all over again with a TRIANGLELIST */
6615         hr = IDirect3DDevice9_SetStreamSource(device, 0, vb_list, 0, sizeof(quad_list[0]));
6616         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
6617         primtype = D3DPT_TRIANGLELIST;
6618         shademode = D3DSHADE_FLAT;
6619     }
6620
6621 bail:
6622     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
6623     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
6624     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
6625     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6626
6627     if (vb_strip)
6628         IDirect3DVertexBuffer9_Release(vb_strip);
6629     if (vb_list)
6630         IDirect3DVertexBuffer9_Release(vb_list);
6631 }
6632
6633
6634 static void fog_srgbwrite_test(IDirect3DDevice9 *device)
6635 {
6636     /* Draw a black quad, half fogged with white fog -> grey color. Enable sRGB writing.
6637      * if sRGB writing is applied before fogging, the 0.0 will be multiplied with ~ 12.92, so still
6638      * stay 0.0. After that the fog gives 0.5. If sRGB writing is applied after fogging, the
6639      * 0.5 will run through the alternative path(0^5 ^ 0.41666 * 1.055 - 0.055), resulting in approx.
6640      * 0.73
6641      *
6642      * At the time of this writing, wined3d could not apply sRGB correction to fixed function rendering,
6643      * so use shaders for this task
6644      */
6645     IDirect3DPixelShader9 *pshader;
6646     IDirect3DVertexShader9 *vshader;
6647     IDirect3D9 *d3d;
6648     DWORD vshader_code[] = {
6649         0xfffe0101,                                                             /* vs_1_1                       */
6650         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
6651         0x00000051, 0xa00f0000, 0x3f000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.5, 0.0, 0.0, 0.0   */
6652         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
6653         0x00000001, 0xc00f0001, 0xa0000000,                                     /* mov oFog, c0.x               */
6654         0x0000ffff                                                              /* end                          */
6655     };
6656     DWORD pshader_code[] = {
6657         0xffff0101,                                                             /* ps_1_1                       */
6658         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0   */
6659         0x00000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                   */
6660         0x0000ffff                                                              /* end                          */
6661     };
6662     const float quad[] = {
6663        -1.0,   -1.0,    0.1,
6664         1.0,   -1.0,    0.1,
6665        -1.0,    1.0,    0.1,
6666         1.0,    1.0,    0.1
6667     };
6668     HRESULT hr;
6669     DWORD color;
6670
6671     IDirect3DDevice9_GetDirect3D(device, &d3d);
6672     /* Ask for srgb writing on D3DRTYPE_TEXTURE. Some Windows drivers do not report it on surfaces.
6673      * For some not entirely understood reasons D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE
6674      * passes on surfaces, while asking for SRGBWRITE alone fails. Textures advertize srgb writing
6675      * alone as well, so use that since it is not the point of this test to show how CheckDeviceFormat
6676      * works
6677      */
6678     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6679                                     D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE,
6680                                     D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8) != D3D_OK) {
6681         skip("No SRGBWRITEENABLE support on D3DFMT_X8R8G8B8\n");
6682         IDirect3D9_Release(d3d);
6683         return;
6684     }
6685     IDirect3D9_Release(d3d);
6686
6687     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
6688     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
6689
6690     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
6691     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6692     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
6693     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6694     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
6695     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6696     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xffffffff);
6697     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6698     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, TRUE);
6699     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6700
6701     hr = IDirect3DDevice9_CreateVertexShader(device, vshader_code, &vshader);
6702     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6703     hr = IDirect3DDevice9_CreatePixelShader(device, pshader_code, &pshader);
6704     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
6705     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
6706     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
6707     hr = IDirect3DDevice9_SetVertexShader(device, vshader);
6708     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6709     hr = IDirect3DDevice9_SetPixelShader(device, pshader);
6710     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
6711
6712     hr = IDirect3DDevice9_BeginScene(device);
6713     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6714     if(SUCCEEDED(hr)) {
6715         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 3);
6716         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6717
6718         hr = IDirect3DDevice9_EndScene(device);
6719         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6720     }
6721
6722     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
6723     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6724     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
6725     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
6726     IDirect3DPixelShader9_Release(pshader);
6727     IDirect3DVertexShader9_Release(vshader);
6728
6729     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
6730     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6731     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, FALSE);
6732     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6733
6734     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6735     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6736     color = getPixelColor(device, 160, 360);
6737     ok(color == 0x00808080 || color == 0x007f7f7f || color == 0x00818181,
6738        "Fog with D3DRS_SRGBWRITEENABLE returned color 0x%08x, expected 0x00808080\n", color);
6739 }
6740
6741 static void alpha_test(IDirect3DDevice9 *device)
6742 {
6743     HRESULT hr;
6744     IDirect3DTexture9 *offscreenTexture;
6745     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
6746     DWORD color;
6747
6748     struct vertex quad1[] =
6749     {
6750         {-1.0f, -1.0f,   0.1f,                          0x4000ff00},
6751         {-1.0f,  0.0f,   0.1f,                          0x4000ff00},
6752         { 1.0f, -1.0f,   0.1f,                          0x4000ff00},
6753         { 1.0f,  0.0f,   0.1f,                          0x4000ff00},
6754     };
6755     struct vertex quad2[] =
6756     {
6757         {-1.0f,  0.0f,   0.1f,                          0xc00000ff},
6758         {-1.0f,  1.0f,   0.1f,                          0xc00000ff},
6759         { 1.0f,  0.0f,   0.1f,                          0xc00000ff},
6760         { 1.0f,  1.0f,   0.1f,                          0xc00000ff},
6761     };
6762     static const float composite_quad[][5] = {
6763         { 0.0f, -1.0f, 0.1f, 0.0f, 1.0f},
6764         { 0.0f,  1.0f, 0.1f, 0.0f, 0.0f},
6765         { 1.0f, -1.0f, 0.1f, 1.0f, 1.0f},
6766         { 1.0f,  1.0f, 0.1f, 1.0f, 0.0f},
6767     };
6768
6769     /* Clear the render target with alpha = 0.5 */
6770     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
6771     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
6772
6773     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
6774     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr);
6775
6776     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
6777     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
6778     if(!backbuffer) {
6779         goto out;
6780     }
6781
6782     hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
6783     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %08x\n", hr);
6784     if(!offscreen) {
6785         goto out;
6786     }
6787
6788     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
6789     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr);
6790
6791     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
6792     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
6793     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
6794     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
6795     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
6796     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
6797     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
6798     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
6799     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
6800     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6801
6802     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
6803     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6804     if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
6805
6806         /* Draw two quads, one with src alpha blending, one with dest alpha blending. */
6807         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
6808         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6809         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
6810         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6811         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
6812         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6813
6814         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
6815         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6816         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
6817         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6818         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
6819         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6820
6821         /* Switch to the offscreen buffer, and redo the testing. The offscreen render target
6822          * doesn't have an alpha channel. DESTALPHA and INVDESTALPHA "don't work" on render
6823          * targets without alpha channel, they give essentially ZERO and ONE blend factors. */
6824         hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
6825         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
6826         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
6827         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
6828
6829         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
6830         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6831         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
6832         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6833         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
6834         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6835
6836         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
6837         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6838         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
6839         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6840         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
6841         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6842
6843         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
6844         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
6845
6846         /* Render the offscreen texture onto the frame buffer to be able to compare it regularly.
6847          * Disable alpha blending for the final composition
6848          */
6849         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
6850         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6851         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
6852         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr);
6853
6854         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
6855         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr = %08x\n", hr);
6856         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, composite_quad, sizeof(float) * 5);
6857         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6858         hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6859         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr = %08x\n", hr);
6860
6861         hr = IDirect3DDevice9_EndScene(device);
6862         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
6863     }
6864
6865     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6866
6867     color = getPixelColor(device, 160, 360);
6868     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1),
6869        "SRCALPHA on frame buffer returned color %08x, expected 0x00bf4000\n", color);
6870
6871     color = getPixelColor(device, 160, 120);
6872     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x7f, 0x00, 0x80), 2),
6873        "DSTALPHA on frame buffer returned color %08x, expected 0x007f0080\n", color);
6874
6875     color = getPixelColor(device, 480, 360);
6876     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1),
6877        "SRCALPHA on texture returned color %08x, expected 0x00bf4000\n", color);
6878
6879     color = getPixelColor(device, 480, 120);
6880     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xff), 1),
6881        "DSTALPHA on texture returned color %08x, expected 0x000000ff\n", color);
6882
6883     out:
6884     /* restore things */
6885     if(backbuffer) {
6886         IDirect3DSurface9_Release(backbuffer);
6887     }
6888     if(offscreenTexture) {
6889         IDirect3DTexture9_Release(offscreenTexture);
6890     }
6891     if(offscreen) {
6892         IDirect3DSurface9_Release(offscreen);
6893     }
6894 }
6895
6896 struct vertex_shortcolor {
6897     float x, y, z;
6898     unsigned short r, g, b, a;
6899 };
6900 struct vertex_floatcolor {
6901     float x, y, z;
6902     float r, g, b, a;
6903 };
6904
6905 static void fixed_function_decl_test(IDirect3DDevice9 *device)
6906 {
6907     HRESULT hr;
6908     BOOL s_ok, ub_ok, f_ok;
6909     DWORD color, size, i;
6910     void *data;
6911     static const D3DVERTEXELEMENT9 decl_elements_d3dcolor[] = {
6912         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6913         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6914         D3DDECL_END()
6915     };
6916     static const D3DVERTEXELEMENT9 decl_elements_d3dcolor_2streams[] = {
6917         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6918         {1,   0,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6919         D3DDECL_END()
6920     };
6921     static const D3DVERTEXELEMENT9 decl_elements_ubyte4n[] = {
6922         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6923         {0,  12,  D3DDECLTYPE_UBYTE4N,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6924         D3DDECL_END()
6925     };
6926     static const D3DVERTEXELEMENT9 decl_elements_ubyte4n_2streams[] = {
6927         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6928         {1,   0,  D3DDECLTYPE_UBYTE4N,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6929         D3DDECL_END()
6930     };
6931     static const D3DVERTEXELEMENT9 decl_elements_short4[] = {
6932         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6933         {0,  12,  D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6934         D3DDECL_END()
6935     };
6936     static const D3DVERTEXELEMENT9 decl_elements_float[] = {
6937         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6938         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6939         D3DDECL_END()
6940     };
6941     static const D3DVERTEXELEMENT9 decl_elements_positiont[] = {
6942         {0,   0,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT,      0},
6943         {0,  16,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6944         D3DDECL_END()
6945     };
6946     IDirect3DVertexDeclaration9 *dcl_float = NULL, *dcl_short = NULL, *dcl_ubyte = NULL, *dcl_color = NULL;
6947     IDirect3DVertexDeclaration9 *dcl_color_2 = NULL, *dcl_ubyte_2 = NULL, *dcl_positiont;
6948     IDirect3DVertexBuffer9 *vb, *vb2;
6949     struct vertex quad1[] =                             /* D3DCOLOR */
6950     {
6951         {-1.0f, -1.0f,   0.1f,                          0x00ffff00},
6952         {-1.0f,  0.0f,   0.1f,                          0x00ffff00},
6953         { 0.0f, -1.0f,   0.1f,                          0x00ffff00},
6954         { 0.0f,  0.0f,   0.1f,                          0x00ffff00},
6955     };
6956     struct vertex quad2[] =                             /* UBYTE4N */
6957     {
6958         {-1.0f,  0.0f,   0.1f,                          0x00ffff00},
6959         {-1.0f,  1.0f,   0.1f,                          0x00ffff00},
6960         { 0.0f,  0.0f,   0.1f,                          0x00ffff00},
6961         { 0.0f,  1.0f,   0.1f,                          0x00ffff00},
6962     };
6963     struct vertex_shortcolor quad3[] =                  /* short */
6964     {
6965         { 0.0f, -1.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
6966         { 0.0f,  0.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
6967         { 1.0f, -1.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
6968         { 1.0f,  0.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
6969     };
6970     struct vertex_floatcolor quad4[] =
6971     {
6972         { 0.0f,  0.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
6973         { 0.0f,  1.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
6974         { 1.0f,  0.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
6975         { 1.0f,  1.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
6976     };
6977     DWORD colors[] = {
6978         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6979         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6980         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6981         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6982         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6983         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6984         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6985         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6986         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6987         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6988         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6989         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6990         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6991         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6992         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6993         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6994     };
6995     float quads[] = {
6996         -1.0,   -1.0,     0.1,
6997         -1.0,    0.0,     0.1,
6998          0.0,   -1.0,     0.1,
6999          0.0,    0.0,     0.1,
7000
7001          0.0,   -1.0,     0.1,
7002          0.0,    0.0,     0.1,
7003          1.0,   -1.0,     0.1,
7004          1.0,    0.0,     0.1,
7005
7006          0.0,    0.0,     0.1,
7007          0.0,    1.0,     0.1,
7008          1.0,    0.0,     0.1,
7009          1.0,    1.0,     0.1,
7010
7011         -1.0,    0.0,     0.1,
7012         -1.0,    1.0,     0.1,
7013          0.0,    0.0,     0.1,
7014          0.0,    1.0,     0.1
7015     };
7016     struct tvertex quad_transformed[] = {
7017        {  90,    110,     0.1,      2.0,        0x00ffff00},
7018        { 570,    110,     0.1,      2.0,        0x00ffff00},
7019        {  90,    300,     0.1,      2.0,        0x00ffff00},
7020        { 570,    300,     0.1,      2.0,        0x00ffff00}
7021     };
7022     D3DCAPS9 caps;
7023
7024     memset(&caps, 0, sizeof(caps));
7025     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7026     ok(hr == D3D_OK, "GetDeviceCaps failed, hr = %08x\n", hr);
7027
7028     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
7029     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
7030
7031     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_d3dcolor, &dcl_color);
7032     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7033     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_short4, &dcl_short);
7034     ok(SUCCEEDED(hr) || hr == E_FAIL, "CreateVertexDeclaration failed (%08x)\n", hr);
7035     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_float, &dcl_float);
7036     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7037     if(caps.DeclTypes & D3DDTCAPS_UBYTE4N) {
7038         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_ubyte4n_2streams, &dcl_ubyte_2);
7039         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7040         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_ubyte4n, &dcl_ubyte);
7041         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7042     } else {
7043         trace("D3DDTCAPS_UBYTE4N not supported\n");
7044         dcl_ubyte_2 = NULL;
7045         dcl_ubyte = NULL;
7046     }
7047     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_d3dcolor_2streams, &dcl_color_2);
7048     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7049     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_positiont, &dcl_positiont);
7050     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7051
7052     size = max(sizeof(quad1), max(sizeof(quad2), max(sizeof(quad3), max(sizeof(quad4), sizeof(quads)))));
7053     hr = IDirect3DDevice9_CreateVertexBuffer(device, size,
7054                                              0, 0, D3DPOOL_MANAGED, &vb, NULL);
7055     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
7056
7057     hr = IDirect3DDevice9_BeginScene(device);
7058     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
7059     f_ok = FALSE; s_ok = FALSE; ub_ok = FALSE;
7060     if(SUCCEEDED(hr)) {
7061         if(dcl_color) {
7062             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color);
7063             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7064             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
7065             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7066         }
7067
7068         /* Tests with non-standard fixed function types fail on the refrast. The ATI driver partially
7069          * accepts them, the nvidia driver accepts them all. All those differences even though we're
7070          * using software vertex processing. Doh!
7071          */
7072         if(dcl_ubyte) {
7073             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte);
7074             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7075             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
7076             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7077             ub_ok = SUCCEEDED(hr);
7078         }
7079
7080         if(dcl_short) {
7081             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_short);
7082             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7083             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(quad3[0]));
7084             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7085             s_ok = SUCCEEDED(hr);
7086         }
7087
7088         if(dcl_float) {
7089             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_float);
7090             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7091             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(quad4[0]));
7092             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7093             f_ok = SUCCEEDED(hr);
7094         }
7095
7096         hr = IDirect3DDevice9_EndScene(device);
7097         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr = %#08x\n", hr);
7098     }
7099
7100     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7101     if(dcl_short) {
7102         color = getPixelColor(device, 480, 360);
7103         ok(color == 0x000000ff || !s_ok,
7104            "D3DDECLTYPE_USHORT4N returned color %08x, expected 0x000000ff\n", color);
7105     }
7106     if(dcl_ubyte) {
7107         color = getPixelColor(device, 160, 120);
7108         ok(color == 0x0000ffff || !ub_ok,
7109            "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x0000ffff\n", color);
7110     }
7111     if(dcl_color) {
7112         color = getPixelColor(device, 160, 360);
7113         ok(color == 0x00ffff00,
7114            "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ffff00\n", color);
7115     }
7116     if(dcl_float) {
7117         color = getPixelColor(device, 480, 120);
7118         ok(color == 0x00ff0000 || !f_ok,
7119            "D3DDECLTYPE_FLOAT4 returned color %08x, expected 0x00ff0000\n", color);
7120     }
7121
7122     /* The following test with vertex buffers doesn't serve to find out new information from windows.
7123      * It is a plain regression test because wined3d uses different codepaths for attribute conversion
7124      * with vertex buffers. It makes sure that the vertex buffer one works, while the above tests
7125      * whether the immediate mode code works
7126      */
7127     f_ok = FALSE; s_ok = FALSE; ub_ok = FALSE;
7128     hr = IDirect3DDevice9_BeginScene(device);
7129     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
7130     if(SUCCEEDED(hr)) {
7131         if(dcl_color) {
7132             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad1), &data, 0);
7133             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7134             memcpy(data, quad1, sizeof(quad1));
7135             hr = IDirect3DVertexBuffer9_Unlock(vb);
7136             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7137             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color);
7138             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7139             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad1[0]));
7140             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7141             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7142             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7143         }
7144
7145         if(dcl_ubyte) {
7146             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad2), &data, 0);
7147             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7148             memcpy(data, quad2, sizeof(quad2));
7149             hr = IDirect3DVertexBuffer9_Unlock(vb);
7150             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7151             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte);
7152             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7153             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad2[0]));
7154             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7155             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7156             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7157                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7158             ub_ok = SUCCEEDED(hr);
7159         }
7160
7161         if(dcl_short) {
7162             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad3), &data, 0);
7163             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7164             memcpy(data, quad3, sizeof(quad3));
7165             hr = IDirect3DVertexBuffer9_Unlock(vb);
7166             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7167             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_short);
7168             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7169             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad3[0]));
7170             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7171             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7172             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7173                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7174             s_ok = SUCCEEDED(hr);
7175         }
7176
7177         if(dcl_float) {
7178             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad4), &data, 0);
7179             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7180             memcpy(data, quad4, sizeof(quad4));
7181             hr = IDirect3DVertexBuffer9_Unlock(vb);
7182             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7183             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_float);
7184             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7185             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad4[0]));
7186             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7187             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7188             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7189                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7190             f_ok = SUCCEEDED(hr);
7191         }
7192
7193         hr = IDirect3DDevice9_EndScene(device);
7194         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr = %#08x\n", hr);
7195     }
7196
7197     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
7198     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7199     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
7200     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7201
7202     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7203     if(dcl_short) {
7204         color = getPixelColor(device, 480, 360);
7205         ok(color == 0x000000ff || !s_ok,
7206            "D3DDECLTYPE_USHORT4N returned color %08x, expected 0x000000ff\n", color);
7207     }
7208     if(dcl_ubyte) {
7209         color = getPixelColor(device, 160, 120);
7210         ok(color == 0x0000ffff || !ub_ok,
7211            "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x0000ffff\n", color);
7212     }
7213     if(dcl_color) {
7214         color = getPixelColor(device, 160, 360);
7215         ok(color == 0x00ffff00,
7216            "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ffff00\n", color);
7217     }
7218     if(dcl_float) {
7219         color = getPixelColor(device, 480, 120);
7220         ok(color == 0x00ff0000 || !f_ok,
7221            "D3DDECLTYPE_FLOAT4 returned color %08x, expected 0x00ff0000\n", color);
7222     }
7223
7224     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
7225     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
7226
7227     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad_transformed), &data, 0);
7228     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7229     memcpy(data, quad_transformed, sizeof(quad_transformed));
7230     hr = IDirect3DVertexBuffer9_Unlock(vb);
7231     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7232
7233     hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_positiont);
7234     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7235
7236     hr = IDirect3DDevice9_BeginScene(device);
7237     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7238     if(SUCCEEDED(hr)) {
7239         hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad_transformed[0]));
7240         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7241         hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7242         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7243
7244         hr = IDirect3DDevice9_EndScene(device);
7245         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7246     }
7247
7248     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7249     color = getPixelColor(device, 88, 108);
7250     ok(color == 0x000000ff,
7251        "pixel 88/108 has color %08x, expected 0x000000ff\n", color);
7252     color = getPixelColor(device, 92, 108);
7253     ok(color == 0x000000ff,
7254        "pixel 92/108 has color %08x, expected 0x000000ff\n", color);
7255     color = getPixelColor(device, 88, 112);
7256     ok(color == 0x000000ff,
7257        "pixel 88/112 has color %08x, expected 0x000000ff\n", color);
7258     color = getPixelColor(device, 92, 112);
7259     ok(color == 0x00ffff00,
7260        "pixel 92/112 has color %08x, expected 0x00ffff00\n", color);
7261
7262     color = getPixelColor(device, 568, 108);
7263     ok(color == 0x000000ff,
7264        "pixel 568/108 has color %08x, expected 0x000000ff\n", color);
7265     color = getPixelColor(device, 572, 108);
7266     ok(color == 0x000000ff,
7267        "pixel 572/108 has color %08x, expected 0x000000ff\n", color);
7268     color = getPixelColor(device, 568, 112);
7269     ok(color == 0x00ffff00,
7270        "pixel 568/112 has color %08x, expected 0x00ffff00\n", color);
7271     color = getPixelColor(device, 572, 112);
7272     ok(color == 0x000000ff,
7273        "pixel 572/112 has color %08x, expected 0x000000ff\n", color);
7274
7275     color = getPixelColor(device, 88, 298);
7276     ok(color == 0x000000ff,
7277        "pixel 88/298 has color %08x, expected 0x000000ff\n", color);
7278     color = getPixelColor(device, 92, 298);
7279     ok(color == 0x00ffff00,
7280        "pixel 92/298 has color %08x, expected 0x00ffff00\n", color);
7281     color = getPixelColor(device, 88, 302);
7282     ok(color == 0x000000ff,
7283        "pixel 88/302 has color %08x, expected 0x000000ff\n", color);
7284     color = getPixelColor(device, 92, 302);
7285     ok(color == 0x000000ff,
7286        "pixel 92/302 has color %08x, expected 0x000000ff\n", color);
7287
7288     color = getPixelColor(device, 568, 298);
7289     ok(color == 0x00ffff00,
7290        "pixel 568/298 has color %08x, expected 0x00ffff00\n", color);
7291     color = getPixelColor(device, 572, 298);
7292     ok(color == 0x000000ff,
7293        "pixel 572/298 has color %08x, expected 0x000000ff\n", color);
7294     color = getPixelColor(device, 568, 302);
7295     ok(color == 0x000000ff,
7296        "pixel 568/302 has color %08x, expected 0x000000ff\n", color);
7297     color = getPixelColor(device, 572, 302);
7298     ok(color == 0x000000ff,
7299        "pixel 572/302 has color %08x, expected 0x000000ff\n", color);
7300
7301     /* This test is pointless without those two declarations: */
7302     if((!dcl_color_2) || (!dcl_ubyte_2)) {
7303         skip("color-ubyte switching test declarations aren't supported\n");
7304         goto out;
7305     }
7306
7307     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quads), &data, 0);
7308     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7309     memcpy(data, quads, sizeof(quads));
7310     hr = IDirect3DVertexBuffer9_Unlock(vb);
7311     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7312     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(colors),
7313                                              0, 0, D3DPOOL_MANAGED, &vb2, NULL);
7314     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
7315     hr = IDirect3DVertexBuffer9_Lock(vb2, 0, sizeof(colors), &data, 0);
7316     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7317     memcpy(data, colors, sizeof(colors));
7318     hr = IDirect3DVertexBuffer9_Unlock(vb2);
7319     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7320
7321     for(i = 0; i < 2; i++) {
7322         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
7323         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
7324
7325         hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(float) * 3);
7326         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7327         if(i == 0) {
7328             hr = IDirect3DDevice9_SetStreamSource(device, 1, vb2, 0, sizeof(DWORD) * 4);
7329         } else {
7330             hr = IDirect3DDevice9_SetStreamSource(device, 1, vb2, 8, sizeof(DWORD) * 4);
7331         }
7332         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7333
7334         hr = IDirect3DDevice9_BeginScene(device);
7335         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
7336         ub_ok = FALSE;
7337         if(SUCCEEDED(hr)) {
7338             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2);
7339             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7340             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7341             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7342                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7343             ub_ok = SUCCEEDED(hr);
7344
7345             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color_2);
7346             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7347             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 4, 2);
7348             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7349
7350             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2);
7351             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7352             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 8, 2);
7353             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7354                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7355             ub_ok = (SUCCEEDED(hr) && ub_ok);
7356
7357             hr = IDirect3DDevice9_EndScene(device);
7358             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
7359         }
7360
7361         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7362         if(i == 0) {
7363             color = getPixelColor(device, 480, 360);
7364             ok(color == 0x00ff0000,
7365                "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ff0000\n", color);
7366             color = getPixelColor(device, 160, 120);
7367             ok(color == 0x00ffffff,
7368                 "Unused quad returned color %08x, expected 0x00ffffff\n", color);
7369             color = getPixelColor(device, 160, 360);
7370             ok(color == 0x000000ff || !ub_ok,
7371                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x000000ff\n", color);
7372             color = getPixelColor(device, 480, 120);
7373             ok(color == 0x000000ff || !ub_ok,
7374                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x000000ff\n", color);
7375         } else {
7376             color = getPixelColor(device, 480, 360);
7377             ok(color == 0x000000ff,
7378                "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x000000ff\n", color);
7379             color = getPixelColor(device, 160, 120);
7380             ok(color == 0x00ffffff,
7381                "Unused quad returned color %08x, expected 0x00ffffff\n", color);
7382             color = getPixelColor(device, 160, 360);
7383             ok(color == 0x00ff0000 || !ub_ok,
7384                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x00ff0000\n", color);
7385             color = getPixelColor(device, 480, 120);
7386             ok(color == 0x00ff0000 || !ub_ok,
7387                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x00ff0000\n", color);
7388         }
7389     }
7390
7391     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
7392     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7393     hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
7394     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7395     IDirect3DVertexBuffer9_Release(vb2);
7396
7397     out:
7398     IDirect3DVertexBuffer9_Release(vb);
7399     if(dcl_float) IDirect3DVertexDeclaration9_Release(dcl_float);
7400     if(dcl_short) IDirect3DVertexDeclaration9_Release(dcl_short);
7401     if(dcl_ubyte) IDirect3DVertexDeclaration9_Release(dcl_ubyte);
7402     if(dcl_color) IDirect3DVertexDeclaration9_Release(dcl_color);
7403     if(dcl_color_2) IDirect3DVertexDeclaration9_Release(dcl_color_2);
7404     if(dcl_ubyte_2) IDirect3DVertexDeclaration9_Release(dcl_ubyte_2);
7405     if(dcl_positiont) IDirect3DVertexDeclaration9_Release(dcl_positiont);
7406 }
7407
7408 struct vertex_float16color {
7409     float x, y, z;
7410     DWORD c1, c2;
7411 };
7412
7413 static void test_vshader_float16(IDirect3DDevice9 *device)
7414 {
7415     HRESULT hr;
7416     DWORD color;
7417     void *data;
7418     static const D3DVERTEXELEMENT9 decl_elements[] = {
7419         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7420         {0,  12,  D3DDECLTYPE_FLOAT16_4,D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7421         D3DDECL_END()
7422     };
7423     IDirect3DVertexDeclaration9 *vdecl = NULL;
7424     IDirect3DVertexBuffer9 *buffer = NULL;
7425     IDirect3DVertexShader9 *shader;
7426     DWORD shader_code[] = {
7427         0xfffe0101, 0x0000001f, 0x80000000, 0x900f0000, 0x0000001f, 0x8000000a,
7428         0x900f0001, 0x00000001, 0xc00f0000, 0x90e40000, 0x00000001, 0xd00f0000,
7429         0x90e40001, 0x0000ffff
7430     };
7431     struct vertex_float16color quad[] = {
7432         { -1.0,   -1.0,     0.1,        0x3c000000, 0x00000000 }, /* green */
7433         { -1.0,    0.0,     0.1,        0x3c000000, 0x00000000 },
7434         {  0.0,   -1.0,     0.1,        0x3c000000, 0x00000000 },
7435         {  0.0,    0.0,     0.1,        0x3c000000, 0x00000000 },
7436
7437         {  0.0,   -1.0,     0.1,        0x00003c00, 0x00000000 }, /* red */
7438         {  0.0,    0.0,     0.1,        0x00003c00, 0x00000000 },
7439         {  1.0,   -1.0,     0.1,        0x00003c00, 0x00000000 },
7440         {  1.0,    0.0,     0.1,        0x00003c00, 0x00000000 },
7441
7442         {  0.0,    0.0,     0.1,        0x00000000, 0x00003c00 }, /* blue */
7443         {  0.0,    1.0,     0.1,        0x00000000, 0x00003c00 },
7444         {  1.0,    0.0,     0.1,        0x00000000, 0x00003c00 },
7445         {  1.0,    1.0,     0.1,        0x00000000, 0x00003c00 },
7446
7447         { -1.0,    0.0,     0.1,        0x00000000, 0x3c000000 }, /* alpha */
7448         { -1.0,    1.0,     0.1,        0x00000000, 0x3c000000 },
7449         {  0.0,    0.0,     0.1,        0x00000000, 0x3c000000 },
7450         {  0.0,    1.0,     0.1,        0x00000000, 0x3c000000 },
7451     };
7452
7453     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff102030, 0.0, 0);
7454     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7455
7456     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vdecl);
7457     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed hr=%08x\n", hr);
7458     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
7459     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexShader failed hr=%08x\n", hr);
7460     hr = IDirect3DDevice9_SetVertexShader(device, shader);
7461     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
7462
7463     hr = IDirect3DDevice9_BeginScene(device);
7464     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
7465     if(SUCCEEDED(hr)) {
7466         hr = IDirect3DDevice9_SetVertexDeclaration(device, vdecl);
7467         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%08x\n", hr);
7468         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad +  0, sizeof(quad[0]));
7469         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7470         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad +  4, sizeof(quad[0]));
7471         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7472         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad +  8, sizeof(quad[0]));
7473         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7474         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad + 12, sizeof(quad[0]));
7475         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7476
7477         hr = IDirect3DDevice9_EndScene(device);
7478         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%08x\n", hr);
7479     }
7480     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7481     color = getPixelColor(device, 480, 360);
7482     ok(color == 0x00ff0000,
7483        "Input 0x00003c00, 0x00000000 returned color %08x, expected 0x00ff0000\n", color);
7484     color = getPixelColor(device, 160, 120);
7485     ok(color == 0x00000000,
7486        "Input 0x00000000, 0x3c000000 returned color %08x, expected 0x00000000\n", color);
7487     color = getPixelColor(device, 160, 360);
7488     ok(color == 0x0000ff00,
7489        "Input 0x3c000000, 0x00000000 returned color %08x, expected 0x0000ff00\n", color);
7490     color = getPixelColor(device, 480, 120);
7491     ok(color == 0x000000ff,
7492        "Input 0x00000000, 0x00003c00 returned color %08x, expected 0x000000ff\n", color);
7493
7494     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff102030, 0.0, 0);
7495     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7496
7497     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0,
7498                                              D3DPOOL_MANAGED, &buffer, NULL);
7499     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexBuffer failed, hr=%08x\n", hr);
7500     hr = IDirect3DVertexBuffer9_Lock(buffer, 0, sizeof(quad), &data, 0);
7501     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed, hr=%08x\n", hr);
7502     memcpy(data, quad, sizeof(quad));
7503     hr = IDirect3DVertexBuffer9_Unlock(buffer);
7504     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed, hr=%08x\n", hr);
7505     hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(quad[0]));
7506     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed, hr=%08x\n", hr);
7507
7508     hr = IDirect3DDevice9_BeginScene(device);
7509     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
7510     if(SUCCEEDED(hr)) {
7511             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,  0, 2);
7512             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7513             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,  4, 2);
7514             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7515             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,  8, 2);
7516             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7517             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 12, 2);
7518             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7519
7520             hr = IDirect3DDevice9_EndScene(device);
7521             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%08x\n", hr);
7522     }
7523
7524     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7525     color = getPixelColor(device, 480, 360);
7526     ok(color == 0x00ff0000,
7527        "Input 0x00003c00, 0x00000000 returned color %08x, expected 0x00ff0000\n", color);
7528     color = getPixelColor(device, 160, 120);
7529     ok(color == 0x00000000,
7530        "Input 0x00000000, 0x3c000000 returned color %08x, expected 0x00000000\n", color);
7531     color = getPixelColor(device, 160, 360);
7532     ok(color == 0x0000ff00,
7533        "Input 0x3c000000, 0x00000000 returned color %08x, expected 0x0000ff00\n", color);
7534     color = getPixelColor(device, 480, 120);
7535     ok(color == 0x000000ff,
7536        "Input 0x00000000, 0x00003c00 returned color %08x, expected 0x000000ff\n", color);
7537
7538     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
7539     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed, hr=%08x\n", hr);
7540     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
7541     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%08x\n", hr);
7542     IDirect3DDevice9_SetVertexShader(device, NULL);
7543     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
7544
7545     IDirect3DVertexDeclaration9_Release(vdecl);
7546     IDirect3DVertexShader9_Release(shader);
7547     IDirect3DVertexBuffer9_Release(buffer);
7548 }
7549
7550 static void conditional_np2_repeat_test(IDirect3DDevice9 *device)
7551 {
7552     D3DCAPS9 caps;
7553     IDirect3DTexture9 *texture;
7554     HRESULT hr;
7555     D3DLOCKED_RECT rect;
7556     unsigned int x, y;
7557     DWORD *dst, color;
7558     const float quad[] = {
7559         -1.0,   -1.0,   0.1,   -0.2,   -0.2,
7560          1.0,   -1.0,   0.1,    1.2,   -0.2,
7561         -1.0,    1.0,   0.1,   -0.2,    1.2,
7562          1.0,    1.0,   0.1,    1.2,    1.2
7563     };
7564     memset(&caps, 0, sizeof(caps));
7565
7566     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7567     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%08x\n", hr);
7568     if(!(caps.TextureCaps & D3DPTEXTURECAPS_POW2)) {
7569         /* NP2 conditional requires the POW2 flag. Check that while we're at it */
7570         ok((caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) == 0,
7571            "Card has conditional NP2 support without power of two restriction set\n");
7572         skip("Card has unconditional pow2 support, skipping conditional NP2 tests\n");
7573         return;
7574     } else if(!(caps.TextureCaps & D3DPTEXTURECAPS_POW2)) {
7575         skip("No conditional NP2 support, skipping conditional NP2 tests\n");
7576         return;
7577     }
7578
7579     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
7580     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7581
7582     hr = IDirect3DDevice9_CreateTexture(device, 10, 10, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7583     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed hr=%08x\n", hr);
7584
7585     memset(&rect, 0, sizeof(rect));
7586     hr = IDirect3DTexture9_LockRect(texture, 0, &rect, NULL, 0);
7587     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed hr=%08x\n", hr);
7588     for(y = 0; y < 10; y++) {
7589         for(x = 0; x < 10; x++) {
7590             dst = (DWORD *) ((BYTE *) rect.pBits + y * rect.Pitch + x * sizeof(DWORD));
7591             if(x == 0 || x == 9 || y == 0 || y == 9) {
7592                 *dst = 0x00ff0000;
7593             } else {
7594                 *dst = 0x000000ff;
7595             }
7596         }
7597     }
7598     hr = IDirect3DTexture9_UnlockRect(texture, 0);
7599     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed hr=%08x\n", hr);
7600
7601     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
7602     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
7603     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
7604     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed hr=%08x\n", hr);
7605     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
7606     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed hr=%08x\n", hr);
7607     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7608     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%08x\n", hr);
7609
7610     hr = IDirect3DDevice9_BeginScene(device);
7611     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
7612     if(SUCCEEDED(hr)) {
7613         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
7614         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7615
7616         hr = IDirect3DDevice9_EndScene(device);
7617         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
7618     }
7619
7620     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7621
7622     color = getPixelColor(device,    1,  1);
7623     ok(color == 0x00ff0000, "NP2: Pixel   1,  1 has color %08x, expected 0x00ff0000\n", color);
7624     color = getPixelColor(device, 639, 479);
7625     ok(color == 0x00ff0000, "NP2: Pixel 639, 479 has color %08x, expected 0x00ff0000\n", color);
7626
7627     color = getPixelColor(device, 135, 101);
7628     ok(color == 0x00ff0000, "NP2: Pixel 135, 101 has color %08x, expected 0x00ff0000\n", color);
7629     color = getPixelColor(device, 140, 101);
7630     ok(color == 0x00ff0000, "NP2: Pixel 140, 101 has color %08x, expected 0x00ff0000\n", color);
7631     color = getPixelColor(device, 135, 105);
7632     ok(color == 0x00ff0000, "NP2: Pixel 135, 105 has color %08x, expected 0x00ff0000\n", color);
7633     color = getPixelColor(device, 140, 105);
7634     ok(color == 0x000000ff, "NP2: Pixel 140, 105 has color %08x, expected 0x000000ff\n", color);
7635
7636     color = getPixelColor(device, 135, 376);
7637     ok(color == 0x00ff0000, "NP2: Pixel 135, 376 has color %08x, expected 0x00ff0000\n", color);
7638     color = getPixelColor(device, 140, 376);
7639     ok(color == 0x000000ff, "NP2: Pixel 140, 376 has color %08x, expected 0x000000ff\n", color);
7640     color = getPixelColor(device, 135, 379);
7641     ok(color == 0x00ff0000, "NP2: Pixel 135, 379 has color %08x, expected 0x00ff0000\n", color);
7642     color = getPixelColor(device, 140, 379);
7643     ok(color == 0x00ff0000, "NP2: Pixel 140, 379 has color %08x, expected 0x00ff0000\n", color);
7644
7645     color = getPixelColor(device, 500, 101);
7646     ok(color == 0x00ff0000, "NP2: Pixel 500, 101 has color %08x, expected 0x00ff0000\n", color);
7647     color = getPixelColor(device, 504, 101);
7648     ok(color == 0x00ff0000, "NP2: Pixel 504, 101 has color %08x, expected 0x00ff0000\n", color);
7649     color = getPixelColor(device, 500, 105);
7650     ok(color == 0x000000ff, "NP2: Pixel 500, 105 has color %08x, expected 0x000000ff\n", color);
7651     color = getPixelColor(device, 504, 105);
7652     ok(color == 0x00ff0000, "NP2: Pixel 504, 105 has color %08x, expected 0x00ff0000\n", color);
7653
7654     color = getPixelColor(device, 500, 376);
7655     ok(color == 0x000000ff, "NP2: Pixel 500, 376 has color %08x, expected 0x000000ff\n", color);
7656     color = getPixelColor(device, 504, 376);
7657     ok(color == 0x00ff0000, "NP2: Pixel 504, 376 has color %08x, expected 0x00ff0000\n", color);
7658     color = getPixelColor(device, 500, 380);
7659     ok(color == 0x00ff0000, "NP2: Pixel 500, 380 has color %08x, expected 0x00ff0000\n", color);
7660     color = getPixelColor(device, 504, 380);
7661     ok(color == 0x00ff0000, "NP2: Pixel 504, 380 has color %08x, expected 0x00ff0000\n", color);
7662
7663     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7664     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
7665     IDirect3DTexture9_Release(texture);
7666 }
7667
7668 static void vFace_register_test(IDirect3DDevice9 *device)
7669 {
7670     HRESULT hr;
7671     DWORD color;
7672     const DWORD shader_code[] = {
7673         0xffff0300,                                                             /* ps_3_0                     */
7674         0x05000051, 0xa00f0000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c0, 0.0, 1.0, 0.0, 0.0 */
7675         0x05000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1, 1.0, 0.0, 0.0, 0.0 */
7676         0x0200001f, 0x80000000, 0x900f1001,                                     /* dcl vFace                  */
7677         0x02000001, 0x800f0001, 0xa0e40001,                                     /* mov r1, c1                 */
7678         0x04000058, 0x800f0000, 0x90e41001, 0xa0e40000, 0x80e40001,             /* cmp r0, vFace, c0, r1      */
7679         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                */
7680         0x0000ffff                                                              /* END                        */
7681     };
7682     IDirect3DPixelShader9 *shader;
7683     IDirect3DTexture9 *texture;
7684     IDirect3DSurface9 *surface, *backbuffer;
7685     const float quad[] = {
7686         -1.0,   -1.0,   0.1,
7687          1.0,   -1.0,   0.1,
7688         -1.0,    0.0,   0.1,
7689
7690          1.0,   -1.0,   0.1,
7691          1.0,    0.0,   0.1,
7692         -1.0,    0.0,   0.1,
7693
7694         -1.0,    0.0,   0.1,
7695         -1.0,    1.0,   0.1,
7696          1.0,    0.0,   0.1,
7697
7698          1.0,    0.0,   0.1,
7699         -1.0,    1.0,   0.1,
7700          1.0,    1.0,   0.1,
7701     };
7702     const float blit[] = {
7703          0.0,   -1.0,   0.1,    0.0,    0.0,
7704          1.0,   -1.0,   0.1,    1.0,    0.0,
7705          0.0,    1.0,   0.1,    0.0,    1.0,
7706          1.0,    1.0,   0.1,    1.0,    1.0,
7707     };
7708
7709     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
7710     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed hr=%08x\n", hr);
7711     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7712     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed hr=%08x\n", hr);
7713     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7714     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed hr=%08x\n", hr);
7715     hr = IDirect3DDevice9_SetPixelShader(device, shader);
7716     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
7717     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
7718     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
7719     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7720     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed hr=%08x\n", hr);
7721
7722     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
7723     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7724
7725     hr = IDirect3DDevice9_BeginScene(device);
7726     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
7727     if(SUCCEEDED(hr)) {
7728         /* First, draw to the texture and the back buffer to test both offscreen and onscreen cases */
7729         hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
7730         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
7731         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
7732         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7733         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 4, quad, sizeof(float) * 3);
7734         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7735         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
7736         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
7737         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 4, quad, sizeof(float) * 3);
7738         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7739
7740         /* Blit the texture onto the back buffer to make it visible */
7741         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
7742         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed, hr=%08x\n", hr);
7743         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
7744         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
7745         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
7746         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed, hr=%08x\n", hr);
7747         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
7748         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed, hr=%08x\n", hr);
7749         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7750         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
7751
7752         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, blit, sizeof(float) * 5);
7753         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7754
7755         hr = IDirect3DDevice9_EndScene(device);
7756         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
7757     }
7758
7759     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7760     color = getPixelColor(device, 160, 360);
7761     ok(color == 0x00ff0000, "vFace: Onscreen rendered front facing quad has color 0x%08x, expected 0x00ff0000\n", color);
7762     color = getPixelColor(device, 160, 120);
7763     ok(color == 0x0000ff00, "vFace: Onscreen rendered back facing quad has color 0x%08x, expected 0x0000ff00\n", color);
7764     color = getPixelColor(device, 480, 360);
7765     ok(color == 0x0000ff00, "vFace: Offscreen rendered back facing quad has color 0x%08x, expected 0x0000ff00\n", color);
7766     color = getPixelColor(device, 480, 120);
7767     ok(color == 0x00ff0000, "vFace: Offscreen rendered front facing quad has color 0x%08x, expected 0x00ff0000\n", color);
7768
7769     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
7770     IDirect3DDevice9_SetTexture(device, 0, NULL);
7771     IDirect3DPixelShader9_Release(shader);
7772     IDirect3DSurface9_Release(surface);
7773     IDirect3DSurface9_Release(backbuffer);
7774     IDirect3DTexture9_Release(texture);
7775 }
7776
7777 static void fixed_function_bumpmap_test(IDirect3DDevice9 *device)
7778 {
7779     HRESULT hr;
7780     DWORD color;
7781     int i;
7782     D3DCAPS9 caps;
7783     BOOL L6V5U5_supported = FALSE;
7784     IDirect3DTexture9 *tex1, *tex2;
7785     D3DLOCKED_RECT locked_rect;
7786
7787     static const float quad[][7] = {
7788         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f},
7789         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f},
7790         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 1.0f, 0.0f},
7791         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 1.0f, 1.0f},
7792     };
7793
7794     static const D3DVERTEXELEMENT9 decl_elements[] = {
7795         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7796         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
7797         {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
7798         D3DDECL_END()
7799     };
7800
7801     /* use asymmetric matrix to test loading */
7802     float bumpenvmat[4] = {0.0,0.5,-0.5,0.0};
7803     float scale, offset;
7804
7805     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
7806     IDirect3DTexture9           *texture            = NULL;
7807
7808     memset(&caps, 0, sizeof(caps));
7809     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7810     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%08x\n", hr);
7811     if(!(caps.TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAP)) {
7812         skip("D3DTEXOPCAPS_BUMPENVMAP not set, skipping bumpmap tests\n");
7813         return;
7814     } else {
7815         /* This check is disabled, some Windows drivers do not handle D3DUSAGE_QUERY_LEGACYBUMPMAP properly.
7816          * They report that it is not supported, but after that bump mapping works properly. So just test
7817          * if the format is generally supported, and check the BUMPENVMAP flag
7818          */
7819         IDirect3D9 *d3d9;
7820
7821         IDirect3DDevice9_GetDirect3D(device, &d3d9);
7822         hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
7823                                           D3DRTYPE_TEXTURE, D3DFMT_L6V5U5);
7824         L6V5U5_supported = SUCCEEDED(hr);
7825         hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
7826                                           D3DRTYPE_TEXTURE, D3DFMT_V8U8);
7827         IDirect3D9_Release(d3d9);
7828         if(FAILED(hr)) {
7829             skip("D3DFMT_V8U8 not supported for legacy bump mapping\n");
7830             return;
7831         }
7832     }
7833
7834     /* Generate the textures */
7835     generate_bumpmap_textures(device);
7836
7837     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
7838     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7839     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
7840     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7841     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
7842     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7843     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
7844     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7845
7846     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BUMPENVMAP);
7847     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7848     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
7849     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7850     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_CURRENT );
7851     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7852
7853     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
7854     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7855     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
7856     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7857     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
7858     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7859
7860     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
7861     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7862
7863     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
7864     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
7865
7866     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
7867     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
7868
7869
7870     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
7871     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
7872     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
7873     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
7874
7875     hr = IDirect3DDevice9_BeginScene(device);
7876     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
7877
7878     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
7879     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
7880
7881     hr = IDirect3DDevice9_EndScene(device);
7882     ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
7883
7884     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7885     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
7886
7887     /* on MacOS(10.5.4, radeon X1600), the white dots are have color 0x00fbfbfb rather than 0x00ffffff. This is
7888      * kinda strange since no calculations are done on the sampled colors, only on the texture coordinates.
7889      * But since testing the color match is not the purpose of the test don't be too picky
7890      */
7891     color = getPixelColor(device, 320-32, 240);
7892     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
7893     color = getPixelColor(device, 320+32, 240);
7894     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
7895     color = getPixelColor(device, 320, 240-32);
7896     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
7897     color = getPixelColor(device, 320, 240+32);
7898     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
7899     color = getPixelColor(device, 320, 240);
7900     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
7901     color = getPixelColor(device, 320+32, 240+32);
7902     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
7903     color = getPixelColor(device, 320-32, 240+32);
7904     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
7905     color = getPixelColor(device, 320+32, 240-32);
7906     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
7907     color = getPixelColor(device, 320-32, 240-32);
7908     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
7909
7910     for(i = 0; i < 2; i++) {
7911         hr = IDirect3DDevice9_GetTexture(device, i, (IDirect3DBaseTexture9 **) &texture);
7912         ok(SUCCEEDED(hr), "IDirect3DDevice9_GetTexture failed (0x%08x)\n", hr);
7913         IDirect3DTexture9_Release(texture); /* For the GetTexture */
7914         hr = IDirect3DDevice9_SetTexture(device, i, NULL);
7915         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
7916         IDirect3DTexture9_Release(texture); /* To destroy it */
7917     }
7918
7919     if(!(caps.TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAPLUMINANCE)) {
7920         skip("D3DTOP_BUMPENVMAPLUMINANCE not supported, skipping\n");
7921         goto cleanup;
7922     }
7923     if(L6V5U5_supported == FALSE) {
7924         skip("L6V5U5_supported not supported, skipping D3DTOP_BUMPENVMAPLUMINANCE test\n");
7925         goto cleanup;
7926     }
7927
7928     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0, 0x8);
7929     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
7930     /* This test only tests the luminance part. The bumpmapping part was already tested above and
7931      * would only make this test more complicated
7932      */
7933     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_L6V5U5, D3DPOOL_MANAGED, &tex1, NULL);
7934     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
7935     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &tex2, NULL);
7936     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
7937
7938     memset(&locked_rect, 0, sizeof(locked_rect));
7939     hr = IDirect3DTexture9_LockRect(tex1, 0, &locked_rect, NULL, 0);
7940     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
7941     *((DWORD *)locked_rect.pBits) = 0x4000; /* L = 0.25, V = 0.0, U = 0.0 */
7942     hr = IDirect3DTexture9_UnlockRect(tex1, 0);
7943     ok(SUCCEEDED(hr), "UnlockRect failed with 0x%08x\n", hr);
7944
7945     memset(&locked_rect, 0, sizeof(locked_rect));
7946     hr = IDirect3DTexture9_LockRect(tex2, 0, &locked_rect, NULL, 0);
7947     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
7948     *((DWORD *)locked_rect.pBits) = 0x00ff80c0;
7949     hr = IDirect3DTexture9_UnlockRect(tex2, 0);
7950     ok(SUCCEEDED(hr), "UnlockRect failed with 0x%08x\n", hr);
7951
7952     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex1);
7953     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
7954     hr = IDirect3DDevice9_SetTexture(device, 1, (IDirect3DBaseTexture9 *) tex2);
7955     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
7956
7957     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BUMPENVMAPLUMINANCE);
7958     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7959     scale = 2.0;
7960     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLSCALE, *((DWORD *)&scale));
7961     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7962     offset = 0.1;
7963     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLOFFSET, *((DWORD *)&offset));
7964     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7965
7966     hr = IDirect3DDevice9_BeginScene(device);
7967     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
7968     if(SUCCEEDED(hr)) {
7969         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
7970         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
7971         hr = IDirect3DDevice9_EndScene(device);
7972         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
7973     }
7974
7975     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7976     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
7977     color = getPixelColor(device, 320, 240);
7978     /* red:   1.0  * (0.25 * 2.0 + 0.1) = 1.0  * 0.6 = 0.6  = 0x99
7979      * green: 0.5  * (0.25 * 2.0 + 0.1) = 0.5  * 0.6 = 0.3  = 0x4c
7980      * green: 0.75 * (0.25 * 2.0 + 0.1) = 0.75 * 0.6 = 0.45 = 0x72
7981      */
7982     ok(color_match(color, 0x00994c72, 5), "bumpmap failed: Got color 0x%08x, expected 0x00994c72.\n", color);
7983
7984     /* Check a result scale factor > 1.0 */
7985     scale = 10;
7986     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLSCALE, *((DWORD *)&scale));
7987     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7988     offset = 10;
7989     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLOFFSET, *((DWORD *)&offset));
7990     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7991
7992     hr = IDirect3DDevice9_BeginScene(device);
7993     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
7994     if(SUCCEEDED(hr)) {
7995         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
7996         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
7997         hr = IDirect3DDevice9_EndScene(device);
7998         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
7999     }
8000     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8001     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
8002     color = getPixelColor(device, 320, 240);
8003     ok(color_match(color, 0x00ff80c0, 1), "bumpmap failed: Got color 0x%08x, expected 0x00ff80c0.\n", color);
8004
8005     /* Check clamping in the scale factor calculation */
8006     scale = 1000;
8007     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLSCALE, *((DWORD *)&scale));
8008     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8009     offset = -1;
8010     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLOFFSET, *((DWORD *)&offset));
8011     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8012
8013     hr = IDirect3DDevice9_BeginScene(device);
8014     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
8015     if(SUCCEEDED(hr)) {
8016         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
8017         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
8018         hr = IDirect3DDevice9_EndScene(device);
8019         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
8020     }
8021     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8022     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
8023     color = getPixelColor(device, 320, 240);
8024     ok(color_match(color, 0x00ff80c0, 1), "bumpmap failed: Got color 0x%08x, expected 0x00ff80c0.\n", color);
8025
8026     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
8027     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
8028     hr = IDirect3DDevice9_SetTexture(device, 1, NULL);
8029     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
8030
8031     IDirect3DTexture9_Release(tex1);
8032     IDirect3DTexture9_Release(tex2);
8033
8034 cleanup:
8035     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
8036     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8037     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
8038     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8039
8040     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
8041     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
8042     IDirect3DVertexDeclaration9_Release(vertex_declaration);
8043 }
8044
8045 static void stencil_cull_test(IDirect3DDevice9 *device) {
8046     HRESULT hr;
8047     IDirect3DSurface9 *depthstencil = NULL;
8048     D3DSURFACE_DESC desc;
8049     float quad1[] = {
8050         -1.0,   -1.0,   0.1,
8051          0.0,   -1.0,   0.1,
8052         -1.0,    0.0,   0.1,
8053          0.0,    0.0,   0.1,
8054     };
8055     float quad2[] = {
8056          0.0,   -1.0,   0.1,
8057          1.0,   -1.0,   0.1,
8058          0.0,    0.0,   0.1,
8059          1.0,    0.0,   0.1,
8060     };
8061     float quad3[] = {
8062         0.0,    0.0,   0.1,
8063         1.0,    0.0,   0.1,
8064         0.0,    1.0,   0.1,
8065         1.0,    1.0,   0.1,
8066     };
8067     float quad4[] = {
8068         -1.0,    0.0,   0.1,
8069          0.0,    0.0,   0.1,
8070         -1.0,    1.0,   0.1,
8071          0.0,    1.0,   0.1,
8072     };
8073     struct vertex painter[] = {
8074        {-1.0,   -1.0,   0.0,    0x00000000},
8075        { 1.0,   -1.0,   0.0,    0x00000000},
8076        {-1.0,    1.0,   0.0,    0x00000000},
8077        { 1.0,    1.0,   0.0,    0x00000000},
8078     };
8079     WORD indices_cw[]  = {0, 1, 3};
8080     WORD indices_ccw[] = {0, 2, 3};
8081     unsigned int i;
8082     DWORD color;
8083
8084     IDirect3DDevice9_GetDepthStencilSurface(device, &depthstencil);
8085     if(depthstencil == NULL) {
8086         skip("No depth stencil buffer\n");
8087         return;
8088     }
8089     hr = IDirect3DSurface9_GetDesc(depthstencil, &desc);
8090     ok(hr == D3D_OK, "IDirect3DSurface9_GetDesc failed with %08x\n", hr);
8091     IDirect3DSurface9_Release(depthstencil);
8092     if(desc.Format != D3DFMT_D24S8 && desc.Format != D3DFMT_D24X4S4) {
8093         skip("No 4 or 8 bit stencil surface\n");
8094         return;
8095     }
8096
8097     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_STENCIL, 0x00ff0000, 0.0, 0x8);
8098     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
8099     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8100
8101     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILFAIL, D3DSTENCILOP_INCR);
8102     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8103     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR);
8104     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8105     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
8106     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8107     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILREF, 0x3);
8108     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8109
8110     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_REPLACE);
8111     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8112     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_DECR);
8113     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8114     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CCW_STENCILPASS, D3DSTENCILOP_INCR);
8115     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8116
8117     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, TRUE);
8118     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8119     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TWOSIDEDSTENCILMODE, FALSE);
8120     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8121
8122     /* First pass: Fill the stencil buffer with some values... */
8123     hr = IDirect3DDevice9_BeginScene(device);
8124     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
8125     if(SUCCEEDED(hr))
8126     {
8127         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_CW);
8128         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8129         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8130                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad1, sizeof(float) * 3);
8131         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8132                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad1, sizeof(float) * 3);
8133
8134         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TWOSIDEDSTENCILMODE, TRUE);
8135         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8136         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
8137         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8138         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8139                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad2, sizeof(float) * 3);
8140         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8141                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad2, sizeof(float) * 3);
8142
8143         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_CW);
8144         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8145         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8146                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad3, sizeof(float) * 3);
8147         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8148                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad3, sizeof(float) * 3);
8149
8150         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_CCW);
8151         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8152         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8153                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad4, sizeof(float) * 3);
8154         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8155                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad4, sizeof(float) * 3);
8156
8157         hr = IDirect3DDevice9_EndScene(device);
8158         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
8159     }
8160
8161     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8162     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
8163     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8164     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
8165     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8166     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
8167     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8168     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TWOSIDEDSTENCILMODE, FALSE);
8169     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8170     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
8171     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8172     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILFUNC, D3DCMP_EQUAL);
8173     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8174
8175     /* 2nd pass: Make the stencil values visible */
8176     hr = IDirect3DDevice9_BeginScene(device);
8177     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
8178     if(SUCCEEDED(hr))
8179     {
8180         IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
8181         for(i = 0; i < 16; i++) {
8182             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILREF, i);
8183             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8184
8185             painter[0].diffuse = (i * 16); /* Creates shades of blue */
8186             painter[1].diffuse = (i * 16);
8187             painter[2].diffuse = (i * 16);
8188             painter[3].diffuse = (i * 16);
8189             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, painter, sizeof(painter[0]));
8190             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
8191         }
8192         hr = IDirect3DDevice9_EndScene(device);
8193         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
8194     }
8195
8196     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8197     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
8198
8199     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
8200     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8201
8202     color = getPixelColor(device, 160, 420);
8203     ok(color == 0x00000030, "CCW triangle, twoside FALSE, cull cw, replace, has color 0x%08x, expected 0x00000030\n", color);
8204     color = getPixelColor(device, 160, 300);
8205     ok(color == 0x00000080, "CW triangle, twoside FALSE, cull cw, culled, has color 0x%08x, expected 0x00000080\n", color);
8206
8207     color = getPixelColor(device, 480, 420);
8208     ok(color == 0x00000090, "CCW triangle, twoside TRUE, cull off, incr, has color 0x%08x, expected 0x00000090\n", color);
8209     color = getPixelColor(device, 480, 300);
8210     ok(color == 0x00000030, "CW triangle, twoside TRUE, cull off, replace, has color 0x%08x, expected 0x00000030\n", color);
8211
8212     color = getPixelColor(device, 160, 180);
8213     ok(color == 0x00000080, "CCW triangle, twoside TRUE, cull ccw, culled, has color 0x%08x, expected 0x00000080\n", color);
8214     color = getPixelColor(device, 160, 60);
8215     ok(color == 0x00000030, "CW triangle, twoside TRUE, cull ccw, replace, has color 0x%08x, expected 0x00000030\n", color);
8216
8217     color = getPixelColor(device, 480, 180);
8218     ok(color == 0x00000090, "CCW triangle, twoside TRUE, cull cw, incr, has color 0x%08x, expected 0x00000090\n", color);
8219     color = getPixelColor(device, 480, 60);
8220     ok(color == 0x00000080, "CW triangle, twoside TRUE, cull cw, culled, has color 0x%08x, expected 0x00000080\n", color);
8221 }
8222
8223 static void vpos_register_test(IDirect3DDevice9 *device)
8224 {
8225     HRESULT hr;
8226     DWORD color;
8227     const DWORD shader_code[] = {
8228     0xffff0300,                                                             /* ps_3_0                     */
8229     0x0200001f, 0x80000000, 0x90031000,                                     /* dcl vPos.xy                */
8230     0x03000002, 0x80030000, 0x90541000, 0xa1fe0000,                         /* sub r0.xy, vPos.xy, c0.zw  */
8231     0x02000001, 0x800f0001, 0xa0e40000,                                     /* mov r1, c0                 */
8232     0x02000001, 0x80080002, 0xa0550000,                                     /* mov r2.a, c0.y             */
8233     0x02000001, 0x80010002, 0xa0550000,                                     /* mov r2.r, c0.y             */
8234     0x04000058, 0x80020002, 0x80000000, 0x80000001, 0x80550001,             /* cmp r2.g, r0.x, r1.x, r1.y */
8235     0x04000058, 0x80040002, 0x80550000, 0x80000001, 0x80550001,             /* cmp r2.b, r0.y, r1.x, r1.y */
8236     0x02000001, 0x800f0800, 0x80e40002,                                     /* mov oC0, r2                */
8237     0x0000ffff                                                              /* end                        */
8238     };
8239     const DWORD shader_frac_code[] = {
8240     0xffff0300,                                                             /* ps_3_0                     */
8241     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0 */
8242     0x0200001f, 0x80000000, 0x90031000,                                     /* dcl vPos.xy                */
8243     0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                 */
8244     0x02000013, 0x80030000, 0x90541000,                                     /* frc r0.xy, vPos.xy         */
8245     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                */
8246     0x0000ffff                                                              /* end                        */
8247     };
8248     IDirect3DPixelShader9 *shader, *shader_frac;
8249     IDirect3DSurface9 *surface = NULL, *backbuffer;
8250     const float quad[] = {
8251         -1.0,   -1.0,   0.1,    0.0,    0.0,
8252          1.0,   -1.0,   0.1,    1.0,    0.0,
8253         -1.0,    1.0,   0.1,    0.0,    1.0,
8254          1.0,    1.0,   0.1,    1.0,    1.0,
8255     };
8256     D3DLOCKED_RECT lr;
8257     float constant[4] = {1.0, 0.0, 320, 240};
8258     DWORD *pos;
8259
8260     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
8261     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8262     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
8263     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed hr=%08x\n", hr);
8264     hr = IDirect3DDevice9_CreatePixelShader(device, shader_frac_code, &shader_frac);
8265     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed hr=%08x\n", hr);
8266     hr = IDirect3DDevice9_SetPixelShader(device, shader);
8267     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
8268     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8269     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
8270     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
8271     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed hr=%08x\n", hr);
8272
8273     hr = IDirect3DDevice9_BeginScene(device);
8274     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8275     if(SUCCEEDED(hr)) {
8276         hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, constant, 1);
8277         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF failed hr=%08x\n", hr);
8278         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
8279         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8280         hr = IDirect3DDevice9_EndScene(device);
8281         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8282     }
8283
8284     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8285     /* This has to be pixel exact */
8286     color = getPixelColor(device, 319, 239);
8287     ok(color == 0x00000000, "vPos: Pixel 319,239 has color 0x%08x, expected 0x00000000\n", color);
8288     color = getPixelColor(device, 320, 239);
8289     ok(color == 0x0000ff00, "vPos: Pixel 320,239 has color 0x%08x, expected 0x0000ff00\n", color);
8290     color = getPixelColor(device, 319, 240);
8291     ok(color == 0x000000ff, "vPos: Pixel 319,240 has color 0x%08x, expected 0x000000ff\n", color);
8292     color = getPixelColor(device, 320, 240);
8293     ok(color == 0x0000ffff, "vPos: Pixel 320,240 has color 0x%08x, expected 0x0000ffff\n", color);
8294
8295     hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, D3DFMT_X8R8G8B8, 0, 0, TRUE,
8296                                              &surface, NULL);
8297     ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed hr=%08x\n", hr);
8298     hr = IDirect3DDevice9_BeginScene(device);
8299     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8300     if(SUCCEEDED(hr)) {
8301         constant[2] = 16; constant[3] = 16;
8302         hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, constant, 1);
8303         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF failed hr=%08x\n", hr);
8304         hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
8305         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8306         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
8307         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8308         hr = IDirect3DDevice9_EndScene(device);
8309         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8310     }
8311     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, D3DLOCK_READONLY);
8312     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr=%08x\n", hr);
8313
8314     pos = (DWORD *) (((BYTE *) lr.pBits) + 14 * lr.Pitch + 14 * sizeof(DWORD));
8315     color = *pos & 0x00ffffff;
8316     ok(color == 0x00000000, "Pixel 14/14 has color 0x%08x, expected 0x00000000\n", color);
8317     pos = (DWORD *) (((BYTE *) lr.pBits) + 14 * lr.Pitch + 18 * sizeof(DWORD));
8318     color = *pos & 0x00ffffff;
8319     ok(color == 0x0000ff00, "Pixel 14/18 has color 0x%08x, expected 0x0000ff00\n", color);
8320     pos = (DWORD *) (((BYTE *) lr.pBits) + 18 * lr.Pitch + 14 * sizeof(DWORD));
8321     color = *pos & 0x00ffffff;
8322     ok(color == 0x000000ff, "Pixel 18/14 has color 0x%08x, expected 0x000000ff\n", color);
8323     pos = (DWORD *) (((BYTE *) lr.pBits) + 18 * lr.Pitch + 18 * sizeof(DWORD));
8324     color = *pos & 0x00ffffff;
8325     ok(color == 0x0000ffff, "Pixel 18/18 has color 0x%08x, expected 0x0000ffff\n", color);
8326
8327     hr = IDirect3DSurface9_UnlockRect(surface);
8328     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr=%08x\n", hr);
8329
8330     /* Test the fraction value of vPos. This is tested with the offscreen target and not the backbuffer to
8331      * have full control over the multisampling setting inside this test
8332      */
8333     hr = IDirect3DDevice9_SetPixelShader(device, shader_frac);
8334     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
8335     hr = IDirect3DDevice9_BeginScene(device);
8336     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8337     if(SUCCEEDED(hr)) {
8338         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
8339         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8340         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
8341         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8342         hr = IDirect3DDevice9_EndScene(device);
8343         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8344     }
8345     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
8346     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8347
8348     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, D3DLOCK_READONLY);
8349     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr=%08x\n", hr);
8350
8351     pos = (DWORD *) (((BYTE *) lr.pBits) + 14 * lr.Pitch + 14 * sizeof(DWORD));
8352     color = *pos & 0x00ffffff;
8353     ok(color == 0x00000000, "vPos fraction test has color 0x%08x, expected 0x00000000\n", color);
8354
8355     hr = IDirect3DSurface9_UnlockRect(surface);
8356     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr=%08x\n", hr);
8357
8358     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
8359     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
8360     IDirect3DPixelShader9_Release(shader);
8361     IDirect3DPixelShader9_Release(shader_frac);
8362     if(surface) IDirect3DSurface9_Release(surface);
8363     IDirect3DSurface9_Release(backbuffer);
8364 }
8365
8366 static void pointsize_test(IDirect3DDevice9 *device)
8367 {
8368     HRESULT hr;
8369     D3DCAPS9 caps;
8370     D3DMATRIX matrix;
8371     D3DMATRIX identity;
8372     float ptsize, ptsize_orig, ptsizemax_orig, ptsizemin_orig;
8373     DWORD color;
8374
8375     const float vertices[] = {
8376         64,     64,     0.1,
8377         128,    64,     0.1,
8378         192,    64,     0.1,
8379         256,    64,     0.1,
8380         320,    64,     0.1,
8381         384,    64,     0.1,
8382         448,    64,     0.1,
8383         512,    64,     0.1,
8384         576,    64,     0.1,
8385     };
8386
8387     /* 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 */
8388     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;
8389     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;
8390     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;
8391     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;
8392
8393     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;
8394     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;
8395     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;
8396     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;
8397
8398     memset(&caps, 0, sizeof(caps));
8399     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8400     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%08x\n", hr);
8401     if(caps.MaxPointSize < 32.0) {
8402         skip("MaxPointSize < 32.0, skipping(MaxPointsize = %f)\n", caps.MaxPointSize);
8403         return;
8404     }
8405
8406     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 0.0, 0);
8407     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8408     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, &matrix);
8409     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed, hr=%08x\n", hr);
8410     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8411     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
8412     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSIZE, (DWORD *) &ptsize_orig);
8413     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed hr=%08x\n", hr);
8414
8415     hr = IDirect3DDevice9_BeginScene(device);
8416     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8417     if(SUCCEEDED(hr)) {
8418         ptsize = 16.0;
8419         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8420         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8421         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[0], sizeof(float) * 3);
8422         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8423
8424         ptsize = 32.0;
8425         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8426         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8427         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[3], sizeof(float) * 3);
8428         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8429
8430         ptsize = 31.5;
8431         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8432         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8433         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[6], sizeof(float) * 3);
8434         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8435
8436         if(caps.MaxPointSize >= 64.0) {
8437             ptsize = 64.0;
8438             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8439             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8440             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[9], sizeof(float) * 3);
8441             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8442
8443             ptsize = 63.75;
8444             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8445             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8446             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[15], sizeof(float) * 3);
8447             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8448         }
8449
8450         ptsize = 1.0;
8451         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8452         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8453         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[12], sizeof(float) * 3);
8454         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8455
8456         hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSIZE_MAX, (DWORD *) (&ptsizemax_orig));
8457         ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed, hr=%08x\n", hr);
8458         hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSIZE_MAX, (DWORD *) (&ptsizemin_orig));
8459         ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed, hr=%08x\n", hr);
8460
8461         /* What happens if point scaling is disabled, and POINTSIZE_MAX < POINTSIZE? */
8462         ptsize = 16.0;
8463         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8464         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8465         ptsize = 1.0;
8466         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MAX, *((DWORD *) (&ptsize)));
8467         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8468         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[18], sizeof(float) * 3);
8469         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8470
8471         /* What happens if POINTSIZE_MAX < POINTSIZE_MIN?
8472          * ptsize = 4.0, ptsize_max = 1.0, ptsize_min = 16.0
8473          */
8474         ptsize = 4.0;
8475         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8476         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8477         ptsize = 16.0;
8478         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MIN, *((DWORD *) (&ptsize)));
8479         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8480         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[21], sizeof(float) * 3);
8481         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8482
8483         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MAX, *((DWORD *) (&ptsizemax_orig)));
8484         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8485
8486         /* pointsize < pointsize_min < pointsize_max?
8487          * pointsize = 1.0, pointsize_min = 16.0, pointsize_max = default(usually 64.0)
8488          */
8489         ptsize = 1.0;
8490         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8491         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8492         ptsize = 16.0;
8493         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MIN, *((DWORD *) (&ptsize)));
8494         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8495         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[24], sizeof(float) * 3);
8496         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8497
8498         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MIN, *((DWORD *) (&ptsizemin_orig)));
8499         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8500
8501         hr = IDirect3DDevice9_EndScene(device);
8502         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8503     }
8504     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8505     color = getPixelColor(device, 64-9, 64-9);
8506     ok(color == 0x000000ff, "pSize: Pixel (64-9),(64-9) has color 0x%08x, expected 0x000000ff\n", color);
8507     color = getPixelColor(device, 64-8, 64-8);
8508     todo_wine ok(color == 0x00ffffff, "pSize: Pixel (64-8),(64-8) has color 0x%08x, expected 0x00ffffff\n", color);
8509     color = getPixelColor(device, 64-7, 64-7);
8510     ok(color == 0x00ffffff, "pSize: Pixel (64-7),(64-7) has color 0x%08x, expected 0x00ffffff\n", color);
8511     color = getPixelColor(device, 64+7, 64+7);
8512     ok(color == 0x00ffffff, "pSize: Pixel (64+7),(64+7) has color 0x%08x, expected 0x00ffffff\n", color);
8513     color = getPixelColor(device, 64+8, 64+8);
8514     ok(color == 0x000000ff, "pSize: Pixel (64+8),(64+8) has color 0x%08x, expected 0x000000ff\n", color);
8515     color = getPixelColor(device, 64+9, 64+9);
8516     ok(color == 0x000000ff, "pSize: Pixel (64+9),(64+9) has color 0x%08x, expected 0x000000ff\n", color);
8517
8518     color = getPixelColor(device, 128-17, 64-17);
8519     ok(color == 0x000000ff, "pSize: Pixel (128-17),(64-17) has color 0x%08x, expected 0x000000ff\n", color);
8520     color = getPixelColor(device, 128-16, 64-16);
8521     todo_wine ok(color == 0x00ffffff, "pSize: Pixel (128-16),(64-16) has color 0x%08x, expected 0x00ffffff\n", color);
8522     color = getPixelColor(device, 128-15, 64-15);
8523     ok(color == 0x00ffffff, "pSize: Pixel (128-15),(64-15) has color 0x%08x, expected 0x00ffffff\n", color);
8524     color = getPixelColor(device, 128+15, 64+15);
8525     ok(color == 0x00ffffff, "pSize: Pixel (128+15),(64+15) has color 0x%08x, expected 0x00ffffff\n", color);
8526     color = getPixelColor(device, 128+16, 64+16);
8527     ok(color == 0x000000ff, "pSize: Pixel (128+16),(64+16) has color 0x%08x, expected 0x000000ff\n", color);
8528     color = getPixelColor(device, 128+17, 64+17);
8529     ok(color == 0x000000ff, "pSize: Pixel (128+17),(64+17) has color 0x%08x, expected 0x000000ff\n", color);
8530
8531     color = getPixelColor(device, 192-17, 64-17);
8532     ok(color == 0x000000ff, "pSize: Pixel (192-17),(64-17) has color 0x%08x, expected 0x000000ff\n", color);
8533     color = getPixelColor(device, 192-16, 64-16);
8534     ok(color == 0x000000ff, "pSize: Pixel (192-16),(64-16) has color 0x%08x, expected 0x000000ff\n", color);
8535     color = getPixelColor(device, 192-15, 64-15);
8536     ok(color == 0x00ffffff, "pSize: Pixel (192-15),(64-15) has color 0x%08x, expected 0x00ffffff\n", color);
8537     color = getPixelColor(device, 192+15, 64+15);
8538     ok(color == 0x00ffffff, "pSize: Pixel (192+15),(64+15) has color 0x%08x, expected 0x00ffffff\n", color);
8539     color = getPixelColor(device, 192+16, 64+16);
8540     ok(color == 0x000000ff, "pSize: Pixel (192+16),(64+16) has color 0x%08x, expected 0x000000ff\n", color);
8541     color = getPixelColor(device, 192+17, 64+17);
8542     ok(color == 0x000000ff, "pSize: Pixel (192+17),(64+17) has color 0x%08x, expected 0x000000ff\n", color);
8543
8544     if(caps.MaxPointSize >= 64.0) {
8545         color = getPixelColor(device, 256-33, 64-33);
8546         ok(color == 0x000000ff, "pSize: Pixel (256-33),(64-33) has color 0x%08x, expected 0x000000ff\n", color);
8547         color = getPixelColor(device, 256-32, 64-32);
8548         todo_wine ok(color == 0x00ffffff, "pSize: Pixel (256-32),(64-32) has color 0x%08x, expected 0x00ffffff\n", color);
8549         color = getPixelColor(device, 256-31, 64-31);
8550         ok(color == 0x00ffffff, "pSize: Pixel (256-31),(64-31) has color 0x%08x, expected 0x00ffffff\n", color);
8551         color = getPixelColor(device, 256+31, 64+31);
8552         ok(color == 0x00ffffff, "pSize: Pixel (256+31),(64+31) has color 0x%08x, expected 0x00ffffff\n", color);
8553         color = getPixelColor(device, 256+32, 64+32);
8554         ok(color == 0x000000ff, "pSize: Pixel (256+32),(64+32) has color 0x%08x, expected 0x000000ff\n", color);
8555         color = getPixelColor(device, 256+33, 64+33);
8556         ok(color == 0x000000ff, "pSize: Pixel (256+33),(64+33) has color 0x%08x, expected 0x000000ff\n", color);
8557
8558         color = getPixelColor(device, 384-33, 64-33);
8559         ok(color == 0x000000ff, "pSize: Pixel (384-33),(64-33) has color 0x%08x, expected 0x000000ff\n", color);
8560         color = getPixelColor(device, 384-32, 64-32);
8561         ok(color == 0x000000ff, "pSize: Pixel (384-32),(64-32) has color 0x%08x, expected 0x000000ff\n", color);
8562         color = getPixelColor(device, 384-31, 64-31);
8563         ok(color == 0x00ffffff, "pSize: Pixel (384-31),(64-31) has color 0x%08x, expected 0x00ffffff\n", color);
8564         color = getPixelColor(device, 384+31, 64+31);
8565         ok(color == 0x00ffffff, "pSize: Pixel (384+31),(64+31) has color 0x%08x, expected 0x00ffffff\n", color);
8566         color = getPixelColor(device, 384+32, 64+32);
8567         ok(color == 0x000000ff, "pSize: Pixel (384+32),(64+32) has color 0x%08x, expected 0x000000ff\n", color);
8568         color = getPixelColor(device, 384+33, 64+33);
8569         ok(color == 0x000000ff, "pSize: Pixel (384+33),(64+33) has color 0x%08x, expected 0x000000ff\n", color);
8570     }
8571
8572     color = getPixelColor(device, 320-1, 64-1);
8573     ok(color == 0x000000ff, "pSize: Pixel (320-1),(64-1) has color 0x%08x, expected 0x000000ff\n", color);
8574     color = getPixelColor(device, 320-0, 64-0);
8575     ok(color == 0x00ffffff, "pSize: Pixel (320-0),(64-0) has color 0x%08x, expected 0x00ffffff\n", color);
8576     color = getPixelColor(device, 320+1, 64+1);
8577     ok(color == 0x000000ff, "pSize: Pixel (320+1),(64+1) has color 0x%08x, expected 0x000000ff\n", color);
8578
8579     /* ptsize = 16, ptsize_max = 1 --> point has size 1 */
8580     color = getPixelColor(device, 448-4, 64-4);
8581     ok(color == 0x000000ff, "pSize: Pixel (448-4),(64-4) has color 0x%08x, expected 0x00ffffff\n", color);
8582     color = getPixelColor(device, 448+4, 64+4);
8583     ok(color == 0x000000ff, "pSize: Pixel (448+4),(64+4) has color 0x%08x, expected 0x00ffffff\n", color);
8584
8585     /* ptsize = 4, ptsize_max = 1, ptsize_min = 16 --> point has size 1 */
8586     color = getPixelColor(device, 512-4, 64-4);
8587     ok(color == 0x000000ff, "pSize: Pixel (448-4),(64-4) has color 0x%08x, expected 0x00ffffff\n", color);
8588     color = getPixelColor(device, 512+4, 64+4);
8589     ok(color == 0x000000ff, "pSize: Pixel (448+4),(64+4) has color 0x%08x, expected 0x00ffffff\n", color);
8590
8591     /* ptsize = 1, ptsize_max = default(64), ptsize_min = 16 --> point has size 16
8592      * Don't be overly picky - just show that the point is bigger than 1 pixel
8593      */
8594     color = getPixelColor(device, 576-4, 64-4);
8595     ok(color == 0x00ffffff, "pSize: Pixel (448-4),(64-4) has color 0x%08x, expected 0x00ffffff\n", color);
8596     color = getPixelColor(device, 576+4, 64+4);
8597     ok(color == 0x00ffffff, "pSize: Pixel (448+4),(64+4) has color 0x%08x, expected 0x00ffffff\n", color);
8598
8599     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize_orig)));
8600     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed hr=%08x\n", hr);
8601     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, &identity);
8602     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed, hr=%08x\n", hr);
8603 }
8604
8605 static void multiple_rendertargets_test(IDirect3DDevice9 *device)
8606 {
8607     HRESULT hr;
8608     IDirect3DPixelShader9 *ps;
8609     IDirect3DTexture9 *tex1, *tex2;
8610     IDirect3DSurface9 *surf1, *surf2, *backbuf;
8611     D3DCAPS9 caps;
8612     DWORD color;
8613     DWORD shader_code[] = {
8614     0xffff0300,                                                             /* ps_3_0             */
8615     0x05000051, 0xa00f0000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c0, 0, 1, 0, 0 */
8616     0x05000051, 0xa00f0001, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, /* def c1, 0, 0, 1, 0 */
8617     0x02000001, 0x800f0800, 0xa0e40000,                                     /* mov oC0, c0        */
8618     0x02000001, 0x800f0801, 0xa0e40001,                                     /* mov oC1, c1        */
8619     0x0000ffff                                                              /* END                */
8620     };
8621     float quad[] = {
8622        -1.0,   -1.0,    0.1,
8623         1.0,   -1.0,    0.1,
8624        -1.0,    1.0,    0.1,
8625         1.0,    1.0,    0.1,
8626     };
8627     float texquad[] = {
8628        -1.0,   -1.0,    0.1,    0.0,    0.0,
8629         0.0,   -1.0,    0.1,    1.0,    0.0,
8630        -1.0,    1.0,    0.1,    0.0,    1.0,
8631         0.0,    1.0,    0.1,    1.0,    1.0,
8632
8633         0.0,   -1.0,    0.1,    0.0,    0.0,
8634         1.0,   -1.0,    0.1,    1.0,    0.0,
8635         0.0,    1.0,    0.1,    0.0,    1.0,
8636         1.0,    1.0,    0.1,    1.0,    1.0,
8637     };
8638
8639     memset(&caps, 0, sizeof(caps));
8640     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8641     ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed, hr=%08x\n", hr);
8642     if(caps.NumSimultaneousRTs < 2) {
8643         skip("Only 1 simultaneous render target supported, skipping MRT test\n");
8644         return;
8645     }
8646
8647     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0, 0);
8648     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8649
8650     hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &tex1, NULL);
8651     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
8652     hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &tex2, NULL);
8653     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
8654     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &ps);
8655     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed, hr=%08x\n", hr);
8656
8657     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuf);
8658     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderTarget failed, hr=%08x\n", hr);
8659     hr = IDirect3DTexture9_GetSurfaceLevel(tex1, 0, &surf1);
8660     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed, hr=%08x\n", hr);
8661     hr = IDirect3DTexture9_GetSurfaceLevel(tex2, 0, &surf2);
8662     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed, hr=%08x\n", hr);
8663
8664     hr = IDirect3DDevice9_SetPixelShader(device, ps);
8665     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed, hr=%08x\n", hr);
8666     hr = IDirect3DDevice9_SetRenderTarget(device, 0, surf1);
8667     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8668     hr = IDirect3DDevice9_SetRenderTarget(device, 1, surf2);
8669     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8670     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8671     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr=%08x\n", hr);
8672
8673     hr = IDirect3DDevice9_BeginScene(device);
8674     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed, hr=%08x\n", hr);
8675     if(SUCCEEDED(hr)) {
8676         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
8677         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8678
8679         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
8680         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed, hr=%08x\n", hr);
8681         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuf);
8682         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8683         hr = IDirect3DDevice9_SetRenderTarget(device, 1, NULL);
8684         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8685         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
8686         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr=%08x\n", hr);
8687
8688         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex1);
8689         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
8690         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &texquad[0], 5 * sizeof(float));
8691         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8692
8693         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex2);
8694         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
8695         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &texquad[20], 5 * sizeof(float));
8696         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8697
8698         hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
8699         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
8700
8701         hr = IDirect3DDevice9_EndScene(device);
8702         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%08x\n", hr);
8703     }
8704
8705     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8706     color = getPixelColor(device, 160, 240);
8707     ok(color == 0x0000ff00, "Texture 1(output color 1) has color 0x%08x, expected 0x0000ff00\n", color);
8708     color = getPixelColor(device, 480, 240);
8709     ok(color == 0x000000ff, "Texture 2(output color 2) has color 0x%08x, expected 0x000000ff\n", color);
8710
8711     IDirect3DPixelShader9_Release(ps);
8712     IDirect3DTexture9_Release(tex1);
8713     IDirect3DTexture9_Release(tex2);
8714     IDirect3DSurface9_Release(surf1);
8715     IDirect3DSurface9_Release(surf2);
8716     IDirect3DSurface9_Release(backbuf);
8717 }
8718
8719 struct formats {
8720     const char *fmtName;
8721     D3DFORMAT textureFormat;
8722     DWORD resultColorBlending;
8723     DWORD resultColorNoBlending;
8724 };
8725
8726 const struct formats test_formats[] = {
8727   { "D3DFMT_G16R16", D3DFMT_G16R16, 0x001818ff, 0x002010ff},
8728   { "D3DFMT_R16F", D3DFMT_R16F, 0x0018ffff, 0x0020ffff },
8729   { "D3DFMT_G16R16F", D3DFMT_G16R16F, 0x001818ff, 0x002010ff },
8730   { "D3DFMT_A16B16G16R16F", D3DFMT_A16B16G16R16F, 0x00181800, 0x00201000 },
8731   { "D3DFMT_R32F", D3DFMT_R32F, 0x0018ffff, 0x0020ffff },
8732   { "D3DFMT_G32R32F", D3DFMT_G32R32F, 0x001818ff, 0x002010ff },
8733   { "D3DFMT_A32B32G32R32F", D3DFMT_A32B32G32R32F, 0x00181800, 0x00201000 },
8734   { NULL, 0 }
8735 };
8736
8737 static void pixelshader_blending_test(IDirect3DDevice9 *device)
8738 {
8739     HRESULT hr;
8740     IDirect3DTexture9 *offscreenTexture = NULL;
8741     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
8742     IDirect3D9 *d3d = NULL;
8743     DWORD color;
8744     DWORD r0, g0, b0, r1, g1, b1;
8745     int fmt_index;
8746
8747     static const float quad[][5] = {
8748         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
8749         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
8750         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
8751         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
8752     };
8753
8754     /* Quad with R=0x10, G=0x20 */
8755     static const struct vertex quad1[] = {
8756         {-1.0f, -1.0f, 0.1f, 0x80102000},
8757         {-1.0f,  1.0f, 0.1f, 0x80102000},
8758         { 1.0f, -1.0f, 0.1f, 0x80102000},
8759         { 1.0f,  1.0f, 0.1f, 0x80102000},
8760     };
8761
8762     /* Quad with R=0x20, G=0x10 */
8763     static const struct vertex quad2[] = {
8764         {-1.0f, -1.0f, 0.1f, 0x80201000},
8765         {-1.0f,  1.0f, 0.1f, 0x80201000},
8766         { 1.0f, -1.0f, 0.1f, 0x80201000},
8767         { 1.0f,  1.0f, 0.1f, 0x80201000},
8768     };
8769
8770     IDirect3DDevice9_GetDirect3D(device, &d3d);
8771
8772     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
8773     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
8774     if(!backbuffer) {
8775         goto out;
8776     }
8777
8778     for(fmt_index=0; test_formats[fmt_index].textureFormat != 0; fmt_index++)
8779     {
8780         D3DFORMAT fmt = test_formats[fmt_index].textureFormat;
8781         if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, fmt) != D3D_OK) {
8782            skip("%s textures not supported\n", test_formats[fmt_index].fmtName);
8783            continue;
8784         }
8785
8786         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
8787         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
8788
8789         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, fmt, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
8790         ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %08x\n", hr);
8791         if(!offscreenTexture) {
8792             continue;
8793         }
8794
8795         hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
8796         ok(hr == D3D_OK, "Can't get offscreen surface, hr = %08x\n", hr);
8797         if(!offscreen) {
8798             continue;
8799         }
8800
8801         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
8802         ok(hr == D3D_OK, "SetFVF failed, hr = %08x\n", hr);
8803
8804         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
8805         ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8806         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
8807         ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8808         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
8809         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
8810         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
8811         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
8812         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
8813         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8814
8815         /* Below we will draw two quads with different colors and try to blend them together.
8816          * The result color is compared with the expected outcome.
8817          */
8818         if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
8819             hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
8820             ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
8821             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 0.0, 0);
8822             ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
8823
8824             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
8825             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8826
8827             /* Draw a quad using color 0x0010200 */
8828             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_ONE);
8829             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8830             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_ZERO);
8831             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8832             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
8833             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
8834
8835             /* Draw a quad using color 0x0020100 */
8836             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
8837             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8838             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
8839             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8840             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
8841             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
8842
8843             /* We don't want to blend the result on the backbuffer */
8844             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
8845             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8846
8847             /* Prepare rendering the 'blended' texture quad to the backbuffer */
8848             hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
8849             ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
8850             hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
8851             ok(hr == D3D_OK, "SetTexture failed, %08x\n", hr);
8852
8853             hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
8854             ok(hr == D3D_OK, "SetFVF failed, hr = %08x\n", hr);
8855
8856             /* This time with the texture */
8857             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
8858             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %08x\n", hr);
8859
8860             IDirect3DDevice9_EndScene(device);
8861         }
8862         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8863
8864
8865         if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, fmt) == D3D_OK) {
8866             /* Compare the color of the center quad with our expectation */
8867             color = getPixelColor(device, 320, 240);
8868             r0 = (color & 0x00ff0000) >> 16;
8869             g0 = (color & 0x0000ff00) >>  8;
8870             b0 = (color & 0x000000ff) >>  0;
8871
8872             r1 = (test_formats[fmt_index].resultColorBlending & 0x00ff0000) >> 16;
8873             g1 = (test_formats[fmt_index].resultColorBlending & 0x0000ff00) >>  8;
8874             b1 = (test_formats[fmt_index].resultColorBlending & 0x000000ff) >>  0;
8875
8876             ok(r0 >= max(r1, 1) - 1 && r0 <= r1 + 1 &&
8877                g0 >= max(g1, 1) - 1 && g0 <= g1 + 1 &&
8878                b0 >= max(b1, 1) - 1 && b0 <= b1 + 1,
8879                "Offscreen failed for %s: Got color %#08x, expected %#08x.\n", test_formats[fmt_index].fmtName, color, test_formats[fmt_index].resultColorBlending);
8880         } else {
8881             /* No pixel shader blending is supported so expected garbage.The type of 'garbage' depends on the driver version and OS.
8882              * E.g. on G16R16 ati reports (on old r9600 drivers) 0x00ffffff and on modern ones 0x002010ff which is also what Nvidia
8883              * reports. On Vista Nvidia seems to report 0x00ffffff on Geforce7 cards. */
8884             color = getPixelColor(device, 320, 240);
8885             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);
8886         }
8887
8888         IDirect3DDevice9_SetTexture(device, 0, NULL);
8889         if(offscreenTexture) {
8890             IDirect3DTexture9_Release(offscreenTexture);
8891         }
8892         if(offscreen) {
8893             IDirect3DSurface9_Release(offscreen);
8894         }
8895     }
8896
8897 out:
8898     /* restore things */
8899     if(backbuffer) {
8900         IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
8901         IDirect3DSurface9_Release(backbuffer);
8902     }
8903 }
8904
8905 static void tssargtemp_test(IDirect3DDevice9 *device)
8906 {
8907     HRESULT hr;
8908     DWORD color;
8909     static const struct vertex quad[] = {
8910         {-1.0,     -1.0,    0.1,    0x00ff0000},
8911         { 1.0,     -1.0,    0.1,    0x00ff0000},
8912         {-1.0,      1.0,    0.1,    0x00ff0000},
8913         { 1.0,      1.0,    0.1,    0x00ff0000}
8914     };
8915     D3DCAPS9 caps;
8916
8917     memset(&caps, 0, sizeof(caps));
8918     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8919     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
8920     if(!(caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP)) {
8921         skip("D3DPMISCCAPS_TSSARGTEMP not supported\n");
8922         return;
8923     }
8924
8925     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
8926     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
8927
8928     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
8929     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8930     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
8931     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8932
8933     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
8934     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8935     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
8936     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8937     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_RESULTARG, D3DTA_TEMP);
8938     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8939
8940     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_ADD);
8941     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8942     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLORARG1, D3DTA_CURRENT);
8943     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8944     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLORARG2, D3DTA_TEMP);
8945     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8946
8947     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_COLOROP, D3DTOP_DISABLE);
8948     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8949
8950     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0x0000ff00);
8951     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8952     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
8953     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %08x\n", hr);
8954
8955     hr = IDirect3DDevice9_BeginScene(device);
8956     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed, hr = %08x\n", hr);
8957     if(SUCCEEDED(hr)) {
8958
8959         hr = IDirect3DDevice9_EndScene(device);
8960         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr = %08x\n", hr);
8961         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
8962         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed with %08x\n", hr);
8963     }
8964     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8965     color = getPixelColor(device, 320, 240);
8966     ok(color == 0x00FFFF00, "TSSARGTEMP test returned color 0x%08x, expected 0x00FFFF00\n", color);
8967
8968     /* Set stage 1 back to default */
8969     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_RESULTARG, D3DTA_CURRENT);
8970     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8971     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
8972     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8973     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
8974     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8975     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
8976     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8977     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_COLOROP, D3DTOP_DISABLE);
8978     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
8979 }
8980
8981 struct testdata
8982 {
8983     DWORD idxVertex; /* number of instances in the first stream */
8984     DWORD idxColor; /* number of instances in the second stream */
8985     DWORD idxInstance; /* should be 1 ?? */
8986     DWORD color1; /* color 1 instance */
8987     DWORD color2; /* color 2 instance */
8988     DWORD color3; /* color 3 instance */
8989     DWORD color4; /* color 4 instance */
8990     WORD strVertex; /* specify which stream to use 0-2*/
8991     WORD strColor;
8992     WORD strInstance;
8993 };
8994
8995 static const struct testdata testcases[]=
8996 {
8997     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  0 */
8998     {3, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0, 1, 2}, /*  1 */
8999     {2, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0, 1, 2}, /*  2 */
9000     {1, 4, 1, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0, 1, 2}, /*  3 */
9001     {0, 4, 1, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0, 1, 2}, /*  4 */
9002     {4, 3, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  5 */
9003     {4, 2, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  6 */
9004     {4, 1, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  7 */
9005     {4, 0, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  8 */
9006     {3, 3, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0, 1, 2}, /*  9 */
9007     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 1, 0, 2}, /* 10 */
9008     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 2, 1}, /* 11 */
9009     {4, 4, 1, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 2, 3, 1}, /* 12 */
9010     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 2, 0, 1}, /* 13 */
9011     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 1, 2, 3}, /* 14 */
9012 /*
9013     This case is handled in a stand alone test, SetStreamSourceFreq(0,(D3DSTREAMSOURCE_INSTANCEDATA | 1))  has to return D3DERR_INVALIDCALL!
9014     {4, 4, 1, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 2, 1, 0, D3DERR_INVALIDCALL},
9015 */
9016 };
9017
9018 /* Drawing Indexed Geometry with instances*/
9019 static void stream_test(IDirect3DDevice9 *device)
9020 {
9021     IDirect3DVertexBuffer9 *vb = NULL;
9022     IDirect3DVertexBuffer9 *vb2 = NULL;
9023     IDirect3DVertexBuffer9 *vb3 = NULL;
9024     IDirect3DIndexBuffer9 *ib = NULL;
9025     IDirect3DVertexDeclaration9 *pDecl = NULL;
9026     IDirect3DVertexShader9 *shader = NULL;
9027     HRESULT hr;
9028     BYTE *data;
9029     DWORD color;
9030     DWORD ind;
9031     unsigned i;
9032
9033     const DWORD shader_code[] =
9034     {
9035         0xfffe0101,                                     /* vs_1_1 */
9036         0x0000001f, 0x80000000, 0x900f0000,             /* dcl_position v0 */
9037         0x0000001f, 0x8000000a, 0x900f0001,             /* dcl_color0 v1 */
9038         0x0000001f, 0x80000005, 0x900f0002,             /* dcl_texcoord v2 */
9039         0x00000001, 0x800f0000, 0x90e40000,             /* mov r0, v0 */
9040         0x00000002, 0xc00f0000, 0x80e40000, 0x90e40002, /* add oPos, r0, v2 */
9041         0x00000001, 0xd00f0000, 0x90e40001,             /* mov oD0, v1 */
9042         0x0000ffff
9043     };
9044
9045     const float quad[][3] =
9046     {
9047         {-0.5f, -0.5f,  1.1f}, /*0 */
9048         {-0.5f,  0.5f,  1.1f}, /*1 */
9049         { 0.5f, -0.5f,  1.1f}, /*2 */
9050         { 0.5f,  0.5f,  1.1f}, /*3 */
9051     };
9052
9053     const float vertcolor[][4] =
9054     {
9055         {1.0f, 0.0f, 0.0f, 1.0f}, /*0 */
9056         {1.0f, 0.0f, 0.0f, 1.0f}, /*1 */
9057         {1.0f, 0.0f, 0.0f, 1.0f}, /*2 */
9058         {1.0f, 0.0f, 0.0f, 1.0f}, /*3 */
9059     };
9060
9061     /* 4 position for 4 instances */
9062     const float instancepos[][3] =
9063     {
9064         {-0.6f,-0.6f, 0.0f},
9065         { 0.6f,-0.6f, 0.0f},
9066         { 0.6f, 0.6f, 0.0f},
9067         {-0.6f, 0.6f, 0.0f},
9068     };
9069
9070     short indices[] = {0, 1, 2, 1, 2, 3};
9071
9072     D3DVERTEXELEMENT9 decl[] =
9073     {
9074         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9075         {1, 0,  D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
9076         {2, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
9077         D3DDECL_END()
9078     };
9079
9080     /* set the default value because it isn't done in wine? */
9081     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 1);
9082     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9083
9084     /* check for D3DSTREAMSOURCE_INDEXEDDATA at stream0 */
9085     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 0, (D3DSTREAMSOURCE_INSTANCEDATA | 1));
9086     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9087
9088     /* check wrong cases */
9089     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 0);
9090     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9091     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9092     ok(hr == D3D_OK && ind == 1, "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9093     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 2);
9094     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9095     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9096     ok(hr == D3D_OK && ind == 2, "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9097     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, (D3DSTREAMSOURCE_INDEXEDDATA | 0));
9098     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9099     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9100     ok(hr == D3D_OK && ind == (D3DSTREAMSOURCE_INDEXEDDATA | 0), "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9101     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, (D3DSTREAMSOURCE_INSTANCEDATA | 0));
9102     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9103     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9104     ok(hr == D3D_OK && ind == (0 | D3DSTREAMSOURCE_INSTANCEDATA), "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9105     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA | 0));
9106     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9107     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9108     ok(hr == D3D_OK && ind == (0 | D3DSTREAMSOURCE_INSTANCEDATA), "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9109
9110     /* set the default value back */
9111     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 1);
9112     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9113
9114     /* create all VertexBuffers*/
9115     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0, D3DPOOL_MANAGED, &vb, NULL);
9116     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
9117     if(!vb) {
9118         skip("Failed to create a vertex buffer\n");
9119         return;
9120     }
9121     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(vertcolor), 0, 0, D3DPOOL_MANAGED, &vb2, NULL);
9122     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
9123     if(!vb2) {
9124         skip("Failed to create a vertex buffer\n");
9125         goto out;
9126     }
9127     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(instancepos), 0, 0, D3DPOOL_MANAGED, &vb3, NULL);
9128     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
9129     if(!vb3) {
9130         skip("Failed to create a vertex buffer\n");
9131         goto out;
9132     }
9133
9134     /* create IndexBuffer*/
9135     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, NULL);
9136     ok(hr == D3D_OK, "IDirect3DDevice9_CreateIndexBuffer failed with %08x\n", hr);
9137     if(!ib) {
9138         skip("Failed to create a index buffer\n");
9139         goto out;
9140     }
9141
9142     /* copy all Buffers (Vertex + Index)*/
9143     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), (void **) &data, 0);
9144     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
9145     memcpy(data, quad, sizeof(quad));
9146     hr = IDirect3DVertexBuffer9_Unlock(vb);
9147     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
9148     hr = IDirect3DVertexBuffer9_Lock(vb2, 0, sizeof(vertcolor), (void **) &data, 0);
9149     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
9150     memcpy(data, vertcolor, sizeof(vertcolor));
9151     hr = IDirect3DVertexBuffer9_Unlock(vb2);
9152     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
9153     hr = IDirect3DVertexBuffer9_Lock(vb3, 0, sizeof(instancepos), (void **) &data, 0);
9154     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
9155     memcpy(data, instancepos, sizeof(instancepos));
9156     hr = IDirect3DVertexBuffer9_Unlock(vb3);
9157     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
9158     hr = IDirect3DIndexBuffer9_Lock(ib, 0, sizeof(indices), (void **) &data, 0);
9159     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Lock failed with %08x\n", hr);
9160     memcpy(data, indices, sizeof(indices));
9161     hr = IDirect3DIndexBuffer9_Unlock(ib);
9162     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
9163
9164     /* create VertexShader */
9165     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
9166     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexShader failed hr=%08x\n", hr);
9167     if(!shader) {
9168         skip("Failed to create a vetex shader\n");
9169         goto out;
9170     }
9171
9172     hr = IDirect3DDevice9_SetVertexShader(device, shader);
9173     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
9174
9175     hr = IDirect3DDevice9_SetIndices(device, ib);
9176     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
9177
9178     /* run all tests */
9179     for( i = 0; i < sizeof(testcases)/sizeof(testcases[0]); ++i)
9180     {
9181         struct testdata act = testcases[i];
9182         decl[0].Stream = act.strVertex;
9183         decl[1].Stream = act.strColor;
9184         decl[2].Stream = act.strInstance;
9185         /* create VertexDeclarations */
9186         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl, &pDecl);
9187         ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed hr=%08x (case %i)\n", hr, i);
9188
9189         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
9190         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x (case %i)\n", hr, i);
9191
9192         hr = IDirect3DDevice9_BeginScene(device);
9193         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x (case %i)\n", hr, i);
9194         if(SUCCEEDED(hr))
9195         {
9196             hr = IDirect3DDevice9_SetVertexDeclaration(device, pDecl);
9197             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x (case %i)\n", hr, i);
9198
9199             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strVertex, (D3DSTREAMSOURCE_INDEXEDDATA | act.idxVertex));
9200             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9201             hr = IDirect3DDevice9_SetStreamSource(device, act.strVertex, vb, 0, sizeof(quad[0]));
9202             ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x (case %i)\n", hr, i);
9203
9204             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strColor, (D3DSTREAMSOURCE_INDEXEDDATA | act.idxColor));
9205             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9206             hr = IDirect3DDevice9_SetStreamSource(device, act.strColor, vb2, 0, sizeof(vertcolor[0]));
9207             ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x (case %i)\n", hr, i);
9208
9209             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strInstance, (D3DSTREAMSOURCE_INSTANCEDATA | act.idxInstance));
9210             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9211             hr = IDirect3DDevice9_SetStreamSource(device, act.strInstance, vb3, 0, sizeof(instancepos[0]));
9212             ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x (case %i)\n", hr, i);
9213
9214             /* don't know if this is right (1*3 and 4*1)*/
9215             hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 0, 1 * 3 , 0, 4*1);
9216             ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitive failed with %08x (case %i)\n", hr, i);
9217             hr = IDirect3DDevice9_EndScene(device);
9218             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x (case %i)\n", hr, i);
9219
9220             /* set all StreamSource && StreamSourceFreq back to default */
9221             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strVertex, 1);
9222             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9223             hr = IDirect3DDevice9_SetStreamSource(device, act.strVertex, NULL, 0, 0);
9224             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9225             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.idxColor, 1);
9226             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9227             hr = IDirect3DDevice9_SetStreamSource(device, act.idxColor, NULL, 0, 0);
9228             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9229             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.idxInstance, 1);
9230             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9231             hr = IDirect3DDevice9_SetStreamSource(device, act.idxInstance, NULL, 0, 0);
9232             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9233         }
9234
9235         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9236         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x (case %i)\n", hr, i);
9237
9238         hr = IDirect3DVertexDeclaration9_Release(pDecl);
9239         ok(hr == D3D_OK, "IDirect3DVertexDeclaration9_Release failed with %08x (case %i)\n", hr, i);
9240
9241         color = getPixelColor(device, 160, 360);
9242         ok(color == act.color1, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color1, i);
9243         color = getPixelColor(device, 480, 360);
9244         ok(color == act.color2, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color2, i);
9245         color = getPixelColor(device, 480, 120);
9246         ok(color == act.color3, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color3, i);
9247         color = getPixelColor(device, 160, 120);
9248         ok(color == act.color4, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color4, i);
9249     }
9250
9251     hr = IDirect3DDevice9_SetIndices(device, NULL);
9252     ok(hr == D3D_OK, "IDirect3DDevice9_SetIndices failed with %08x\n", hr);
9253
9254 out:
9255     if(vb) IDirect3DVertexBuffer9_Release(vb);
9256     if(vb2)IDirect3DVertexBuffer9_Release(vb2);
9257     if(vb3)IDirect3DVertexBuffer9_Release(vb3);
9258     if(ib)IDirect3DIndexBuffer9_Release(ib);
9259     if(shader)IDirect3DVertexShader9_Release(shader);
9260 }
9261
9262 static void np2_stretch_rect_test(IDirect3DDevice9 *device) {
9263     IDirect3DSurface9 *src = NULL, *dst = NULL, *backbuffer = NULL;
9264     IDirect3DTexture9 *dsttex = NULL;
9265     HRESULT hr;
9266     DWORD color;
9267     D3DRECT r1 = {0,  0,  50,  50 };
9268     D3DRECT r2 = {50, 0,  100, 50 };
9269     D3DRECT r3 = {50, 50, 100, 100};
9270     D3DRECT r4 = {0,  50,  50, 100};
9271     const float quad[] = {
9272         -1.0,   -1.0,   0.1,    0.0,    0.0,
9273          1.0,   -1.0,   0.1,    1.0,    0.0,
9274         -1.0,    1.0,   0.1,    0.0,    1.0,
9275          1.0,    1.0,   0.1,    1.0,    1.0,
9276     };
9277
9278     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
9279     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
9280
9281     hr = IDirect3DDevice9_CreateRenderTarget(device, 100, 100, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &src, NULL );
9282     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
9283     hr = IDirect3DDevice9_CreateTexture(device, 25, 25, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &dsttex, NULL);
9284     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
9285
9286     if(!src || !dsttex) {
9287         skip("One or more test resources could not be created\n");
9288         goto cleanup;
9289     }
9290
9291     hr = IDirect3DTexture9_GetSurfaceLevel(dsttex, 0, &dst);
9292     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
9293
9294     hr = IDirect3DDevice9_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
9295     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9296
9297     /* Clear the StretchRect destination for debugging */
9298     hr = IDirect3DDevice9_SetRenderTarget(device, 0, dst);
9299     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
9300     hr = IDirect3DDevice9_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
9301     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9302
9303     hr = IDirect3DDevice9_SetRenderTarget(device, 0, src);
9304     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
9305
9306     hr = IDirect3DDevice9_Clear(device, 1, &r1, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
9307     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9308     hr = IDirect3DDevice9_Clear(device, 1, &r2, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
9309     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9310     hr = IDirect3DDevice9_Clear(device, 1, &r3, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
9311     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9312     hr = IDirect3DDevice9_Clear(device, 1, &r4, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
9313     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9314
9315     /* Stretchrect before setting the render target back to the backbuffer. This will make Wine use
9316      * the target -> texture GL blit path
9317      */
9318     hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst, NULL, D3DTEXF_POINT);
9319     ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
9320     IDirect3DSurface9_Release(dst);
9321
9322     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
9323     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
9324
9325     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) dsttex);
9326     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9327     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
9328     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
9329     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9330     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9331     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9332     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9333
9334     hr = IDirect3DDevice9_BeginScene(device);
9335     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
9336     if(SUCCEEDED(hr)) {
9337         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
9338         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
9339         hr = IDirect3DDevice9_EndScene(device);
9340         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
9341     }
9342
9343     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9344     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
9345     color = getPixelColor(device, 160, 360);
9346     ok(color == 0x00ff0000, "stretchrect: Pixel 160,360 has color 0x%08x, expected 0x00ff0000\n", color);
9347     color = getPixelColor(device, 480, 360);
9348     ok(color == 0x0000ff00, "stretchrect: Pixel 480,360 has color 0x%08x, expected 0x0000ff00\n", color);
9349     color = getPixelColor(device, 480, 120);
9350     ok(color == 0x000000ff, "stretchrect: Pixel 480,120 has color 0x%08x, expected 0x000000ff\n", color);
9351     color = getPixelColor(device, 160, 120);
9352     ok(color == 0x00000000, "stretchrect: Pixel 160,120 has color 0x%08x, expected 0x00000000\n", color);
9353
9354     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
9355     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9356     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
9357     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9358
9359 cleanup:
9360     if(src) IDirect3DSurface9_Release(src);
9361     if(backbuffer) IDirect3DSurface9_Release(backbuffer);
9362     if(dsttex) IDirect3DTexture9_Release(dsttex);
9363 }
9364
9365 static void texop_test(IDirect3DDevice9 *device)
9366 {
9367     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
9368     IDirect3DTexture9 *texture = NULL;
9369     D3DLOCKED_RECT locked_rect;
9370     D3DCOLOR color;
9371     D3DCAPS9 caps;
9372     HRESULT hr;
9373     unsigned i;
9374
9375     static const struct {
9376         float x, y, z;
9377         float s, t;
9378         D3DCOLOR diffuse;
9379     } quad[] = {
9380         {-1.0f, -1.0f, 0.1f, -1.0f, -1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)},
9381         {-1.0f,  1.0f, 0.1f, -1.0f,  1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)},
9382         { 1.0f, -1.0f, 0.1f,  1.0f, -1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)},
9383         { 1.0f,  1.0f, 0.1f,  1.0f,  1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)}
9384     };
9385
9386     static const D3DVERTEXELEMENT9 decl_elements[] = {
9387         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9388         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
9389         {0, 20, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
9390         D3DDECL_END()
9391     };
9392
9393     static const struct {
9394         D3DTEXTUREOP op;
9395         const char *name;
9396         DWORD caps_flag;
9397         D3DCOLOR result;
9398     } test_data[] = {
9399         {D3DTOP_SELECTARG1,                "SELECTARG1",                D3DTEXOPCAPS_SELECTARG1,                D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
9400         {D3DTOP_SELECTARG2,                "SELECTARG2",                D3DTEXOPCAPS_SELECTARG2,                D3DCOLOR_ARGB(0x00, 0x33, 0x33, 0x33)},
9401         {D3DTOP_MODULATE,                  "MODULATE",                  D3DTEXOPCAPS_MODULATE,                  D3DCOLOR_ARGB(0x00, 0x00, 0x33, 0x00)},
9402         {D3DTOP_MODULATE2X,                "MODULATE2X",                D3DTEXOPCAPS_MODULATE2X,                D3DCOLOR_ARGB(0x00, 0x00, 0x66, 0x00)},
9403         {D3DTOP_MODULATE4X,                "MODULATE4X",                D3DTEXOPCAPS_MODULATE4X,                D3DCOLOR_ARGB(0x00, 0x00, 0xcc, 0x00)},
9404         {D3DTOP_ADD,                       "ADD",                       D3DTEXOPCAPS_ADD,                       D3DCOLOR_ARGB(0x00, 0x33, 0xff, 0x33)},
9405         {D3DTOP_ADDSIGNED,                 "ADDSIGNED",                 D3DTEXOPCAPS_ADDSIGNED,                 D3DCOLOR_ARGB(0x00, 0x00, 0xb2, 0x00)},
9406         {D3DTOP_ADDSIGNED2X,               "ADDSIGNED2X",               D3DTEXOPCAPS_ADDSIGNED2X,               D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
9407         {D3DTOP_SUBTRACT,                  "SUBTRACT",                  D3DTEXOPCAPS_SUBTRACT,                  D3DCOLOR_ARGB(0x00, 0x00, 0xcc, 0x00)},
9408         {D3DTOP_ADDSMOOTH,                 "ADDSMOOTH",                 D3DTEXOPCAPS_ADDSMOOTH,                 D3DCOLOR_ARGB(0x00, 0x33, 0xff, 0x33)},
9409         {D3DTOP_BLENDDIFFUSEALPHA,         "BLENDDIFFUSEALPHA",         D3DTEXOPCAPS_BLENDDIFFUSEALPHA,         D3DCOLOR_ARGB(0x00, 0x22, 0x77, 0x22)},
9410         {D3DTOP_BLENDTEXTUREALPHA,         "BLENDTEXTUREALPHA",         D3DTEXOPCAPS_BLENDTEXTUREALPHA,         D3DCOLOR_ARGB(0x00, 0x14, 0xad, 0x14)},
9411         {D3DTOP_BLENDFACTORALPHA,          "BLENDFACTORALPHA",          D3DTEXOPCAPS_BLENDFACTORALPHA,          D3DCOLOR_ARGB(0x00, 0x07, 0xe4, 0x07)},
9412         {D3DTOP_BLENDTEXTUREALPHAPM,       "BLENDTEXTUREALPHAPM",       D3DTEXOPCAPS_BLENDTEXTUREALPHAPM,       D3DCOLOR_ARGB(0x00, 0x14, 0xff, 0x14)},
9413         {D3DTOP_BLENDCURRENTALPHA,         "BLENDCURRENTALPHA",         D3DTEXOPCAPS_BLENDCURRENTALPHA,         D3DCOLOR_ARGB(0x00, 0x22, 0x77, 0x22)},
9414         {D3DTOP_MODULATEALPHA_ADDCOLOR,    "MODULATEALPHA_ADDCOLOR",    D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR,    D3DCOLOR_ARGB(0x00, 0x1f, 0xff, 0x1f)},
9415         {D3DTOP_MODULATECOLOR_ADDALPHA,    "MODULATECOLOR_ADDALPHA",    D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA,    D3DCOLOR_ARGB(0x00, 0x99, 0xcc, 0x99)},
9416         {D3DTOP_MODULATEINVALPHA_ADDCOLOR, "MODULATEINVALPHA_ADDCOLOR", D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR, D3DCOLOR_ARGB(0x00, 0x14, 0xff, 0x14)},
9417         {D3DTOP_MODULATEINVCOLOR_ADDALPHA, "MODULATEINVCOLOR_ADDALPHA", D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA, D3DCOLOR_ARGB(0x00, 0xcc, 0x99, 0xcc)},
9418         /* BUMPENVMAP & BUMPENVMAPLUMINANCE have their own tests */
9419         {D3DTOP_DOTPRODUCT3,               "DOTPRODUCT2",               D3DTEXOPCAPS_DOTPRODUCT3,               D3DCOLOR_ARGB(0x00, 0x99, 0x99, 0x99)},
9420         {D3DTOP_MULTIPLYADD,               "MULTIPLYADD",               D3DTEXOPCAPS_MULTIPLYADD,               D3DCOLOR_ARGB(0x00, 0xff, 0x33, 0x00)},
9421         {D3DTOP_LERP,                      "LERP",                      D3DTEXOPCAPS_LERP,                      D3DCOLOR_ARGB(0x00, 0x00, 0x33, 0x33)},
9422     };
9423
9424     memset(&caps, 0, sizeof(caps));
9425     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9426     ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x\n", hr);
9427
9428     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
9429     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed with 0x%08x\n", hr);
9430     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
9431     ok(SUCCEEDED(hr), "SetVertexDeclaration failed with 0x%08x\n", hr);
9432
9433     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
9434     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed with 0x%08x\n", hr);
9435     hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
9436     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
9437     *((DWORD *)locked_rect.pBits) = D3DCOLOR_ARGB(0x99, 0x00, 0xff, 0x00);
9438     hr = IDirect3DTexture9_UnlockRect(texture, 0);
9439     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
9440     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
9441     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
9442
9443     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG0, D3DTA_DIFFUSE);
9444     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9445     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9446     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9447     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9448     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9449
9450     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
9451     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9452
9453     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
9454     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9455     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0xdd333333);
9456     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9457     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA);
9458     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9459
9460     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
9461     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9462
9463     for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
9464     {
9465         if (!(caps.TextureOpCaps & test_data[i].caps_flag))
9466         {
9467             skip("tex operation %s not supported\n", test_data[i].name);
9468             continue;
9469         }
9470
9471         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, test_data[i].op);
9472         ok(SUCCEEDED(hr), "SetTextureStageState (%s) failed with 0x%08x\n", test_data[i].name, hr);
9473
9474         hr = IDirect3DDevice9_BeginScene(device);
9475         ok(SUCCEEDED(hr), "BeginScene failed with 0x%08x\n", hr);
9476
9477         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
9478         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9479
9480         hr = IDirect3DDevice9_EndScene(device);
9481         ok(SUCCEEDED(hr), "EndScene failed with 0x%08x\n", hr);
9482
9483         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9484         ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
9485
9486         color = getPixelColor(device, 320, 240);
9487         ok(color_match(color, test_data[i].result, 3), "Operation %s returned color 0x%08x, expected 0x%08x\n",
9488                 test_data[i].name, color, test_data[i].result);
9489     }
9490
9491     if (texture) IDirect3DTexture9_Release(texture);
9492     if (vertex_declaration) IDirect3DVertexDeclaration9_Release(vertex_declaration);
9493 }
9494
9495 static void yuv_color_test(IDirect3DDevice9 *device) {
9496     HRESULT hr;
9497     IDirect3DSurface9 *surface = NULL, *target = NULL;
9498     unsigned int fmt, i;
9499     D3DFORMAT format;
9500     const char *fmt_string;
9501     D3DLOCKED_RECT lr;
9502     IDirect3D9 *d3d;
9503     HRESULT color;
9504     DWORD ref_color_left, ref_color_right;
9505
9506     struct {
9507         DWORD in;           /* The input color */
9508         DWORD uyvy_left;    /* "in" interpreted as uyvy and transformed to RGB, pixel 1/1*/
9509         DWORD uyvy_right;   /* "in" interpreted as uyvy and transformed to RGB, pixel 2/1*/
9510         DWORD yuy2_left;    /* "in" interpreted as yuy2 and transformed to RGB, pixel 1/1 */
9511         DWORD yuy2_right;   /* "in" interpreted as yuy2 and transformed to RGB, pixel 2/1 */
9512     } test_data[] = {
9513     /* Originally I wanted to avoid being evil, and set Y1 = Y2 to avoid triggering troubles in shader converters,
9514      * but the main difference between YUY2 and UYVY is the swapped ordering of the chroma and luminance
9515      * values. However, handling the two Y's properly could have a big impact on image quality, so be picky about
9516      * that
9517      */
9518       { 0x00000000, 0x00008700, 0x00008700, 0x00008700, 0x00008700 },
9519       { 0xff000000, 0x00008700, 0x004bff1c, 0x00b30000, 0x00b30000 },
9520       { 0x00ff0000, 0x00b30000, 0x00b30000, 0x00008700, 0x004bff1c },
9521       { 0x0000ff00, 0x004bff1c, 0x00008700, 0x000030e1, 0x000030e1 },
9522       { 0x000000ff, 0x000030e1, 0x000030e1, 0x004bff1c, 0x00008700 },
9523       { 0xffff0000, 0x00b30000, 0x00ffd01c, 0x00b30000, 0x00ffd01c },
9524       { 0xff00ff00, 0x004bff1c, 0x004bff1c, 0x00b300e1, 0x00b300e1 },
9525       { 0xff0000ff, 0x000030e1, 0x004bffff, 0x00ffd01c, 0x00b30000 },
9526       { 0x00ffff00, 0x00ffd01c, 0x00b30000, 0x000030e1, 0x004bffff },
9527       { 0x00ff00ff, 0x00b300e1, 0x00b300e1, 0x004bff1c, 0x004bff1c },
9528       { 0x0000ffff, 0x004bffff, 0x000030e1, 0x004bffff, 0x000030e1 },
9529       { 0xffffff00, 0x00ffd01c, 0x00ffd01c, 0x00b300e1, 0x00ff79ff },
9530       { 0xffff00ff, 0x00b300e1, 0x00ff79ff, 0x00ffd01c, 0x00ffd01c },
9531       { 0xffffffff, 0x00ff79ff, 0x00ff79ff, 0x00ff79ff, 0x00ff79ff },
9532
9533       { 0x4cff4c54, 0x00ff0000, 0x00ff0000, 0x000b8b00, 0x00b6ffa3 },
9534       { 0x00800080, 0x00000000, 0x00000000, 0x0000ff00, 0x0000ff00 },
9535       { 0xFF80FF80, 0x00ffffff, 0x00ffffff, 0x00ff00ff, 0x00ff00ff },
9536       { 0x1c6b1cff, 0x000000fd, 0x000000fd, 0x006dff45, 0x0000d500 },
9537     };
9538
9539     hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
9540     ok(hr == D3D_OK, "IDirect3DDevice9_GetDirect3D failed, hr = %08x\n", hr);
9541     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &target);
9542     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderTarget failed, hr = %08x\n", hr);
9543
9544     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX0);
9545     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %08x\n", hr);
9546
9547     for(fmt = 0; fmt < 2; fmt++) {
9548         if(fmt == 0) {
9549             format = D3DFMT_UYVY;
9550             fmt_string = "D3DFMT_UYVY";
9551         } else {
9552             format = D3DFMT_YUY2;
9553             fmt_string = "D3DFMT_YUY2";
9554         }
9555
9556         /* Some(all?) Windows drivers do not support YUV 3D textures, only 2D surfaces in StretchRect. Thus use
9557                        * StretchRect to draw the YUV surface onto the screen instead of drawPrimitive
9558                        */
9559         if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
9560                                         D3DRTYPE_SURFACE, format) != D3D_OK) {
9561             skip("%s is not supported\n", fmt_string);
9562             continue;
9563         }
9564
9565         /* A pixel is effectively 16 bit large, but two pixels are stored together, so the minimum size is 2x1 */
9566         hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2, 1, format, D3DPOOL_DEFAULT, &surface, NULL);
9567         ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed, hr = %08x\n", hr);
9568
9569         for(i = 0; i < (sizeof(test_data)/sizeof(test_data[0])); i++) {
9570             if(fmt == 0) {
9571                 ref_color_left = test_data[i].uyvy_left;
9572                 ref_color_right = test_data[i].uyvy_right;
9573             } else {
9574                 ref_color_left = test_data[i].yuy2_left;
9575                 ref_color_right = test_data[i].yuy2_right;
9576             }
9577
9578             memset(&lr, 0, sizeof(lr));
9579             hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
9580             ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr = %08x\n", hr);
9581             *((DWORD *) lr.pBits) = test_data[i].in;
9582             hr = IDirect3DSurface9_UnlockRect(surface);
9583             ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr = %08x\n", hr);
9584
9585             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
9586             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9587             hr = IDirect3DDevice9_StretchRect(device, surface, NULL, target, NULL, D3DTEXF_POINT);
9588             ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with 0x%08x\n", hr);
9589             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9590             ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
9591
9592             /* Native D3D can't resist filtering the YUY surface, even though we asked it not to do so above. To
9593              * prevent running into precision problems, read a far left and far right pixel. In the future we may
9594              * want to add tests for the filtered pixels as well.
9595              *
9596              * Unfortunately different implementations(Windows-NV and Mac-ATI tested) interpret some colors vastly
9597              * differently, so we need a max diff of 16
9598              */
9599             color = getPixelColor(device, 40, 240);
9600             ok(color_match(color, ref_color_left, 16),
9601                "Input 0x%08x: Got color 0x%08x for pixel 1/1, expected 0x%08x, format %s\n",
9602                test_data[i].in, color, ref_color_left, fmt_string);
9603             color = getPixelColor(device, 600, 240);
9604             ok(color_match(color, ref_color_right, 16),
9605                "Input 0x%08x: Got color 0x%08x for pixel 2/1, expected 0x%08x, format %s\n",
9606                test_data[i].in, color, ref_color_left, fmt_string);
9607         }
9608         IDirect3DSurface9_Release(surface);
9609     }
9610     IDirect3DSurface9_Release(target);
9611     IDirect3D9_Release(d3d);
9612 }
9613
9614 static void texop_range_test(IDirect3DDevice9 *device)
9615 {
9616     static const struct {
9617         float x, y, z;
9618         D3DCOLOR diffuse;
9619     } quad[] = {
9620         {-1.0f, -1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)},
9621         {-1.0f,  1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)},
9622         { 1.0f, -1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)},
9623         { 1.0f,  1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)}
9624     };
9625     HRESULT hr;
9626     IDirect3DTexture9 *texture;
9627     D3DLOCKED_RECT locked_rect;
9628     D3DCAPS9 caps;
9629     DWORD color;
9630
9631     /* We need ADD and SUBTRACT operations */
9632     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9633     ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x\n", hr);
9634     if (!(caps.TextureOpCaps & D3DTEXOPCAPS_ADD)) {
9635         skip("D3DTOP_ADD is not supported, skipping value range test\n");
9636     }
9637     if (!(caps.TextureOpCaps & D3DTEXOPCAPS_SUBTRACT)) {
9638         skip("D3DTEXOPCAPS_SUBTRACT is not supported, skipping value range test\n");
9639     }
9640
9641     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
9642     ok(SUCCEEDED(hr), "SetFVF failed with 0x%08x\n", hr);
9643     /* Stage 1: result = diffuse(=1.0) + diffuse
9644      * stage 2: result = result - tfactor(= 0.5)
9645      */
9646     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0x80808080);
9647     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9648     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
9649     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9650     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
9651     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9652     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
9653     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9654     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_CURRENT);
9655     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9656     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9657     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9658     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SUBTRACT);
9659     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9660
9661     hr = IDirect3DDevice9_BeginScene(device);
9662     ok(SUCCEEDED(hr), "BeginScene failed with 0x%08x\n", hr);
9663     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
9664     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9665     hr = IDirect3DDevice9_EndScene(device);
9666     ok(SUCCEEDED(hr), "EndScene failed with 0x%08x\n", hr);
9667     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9668     ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
9669
9670     color = getPixelColor(device, 320, 240);
9671     ok(color_match(color, 0x00808080, 1), "texop Range > 1.0 returned 0x%08x, expected 0x00808080\n",
9672        color);
9673
9674     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
9675     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed with 0x%08x\n", hr);
9676     hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
9677     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
9678     *((DWORD *)locked_rect.pBits) = D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00);
9679     hr = IDirect3DTexture9_UnlockRect(texture, 0);
9680     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
9681     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
9682     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
9683
9684     /* Stage 1: result = texture(=0.0) - tfactor(= 0.5)
9685      * stage 2: result = result + diffuse(1.0)
9686      */
9687     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0x80808080);
9688     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9689     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9690     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9691     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9692     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9693     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SUBTRACT);
9694     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9695     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_CURRENT);
9696     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9697     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
9698     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9699     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
9700     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9701
9702     hr = IDirect3DDevice9_BeginScene(device);
9703     ok(SUCCEEDED(hr), "BeginScene failed with 0x%08x\n", hr);
9704     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
9705     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9706     hr = IDirect3DDevice9_EndScene(device);
9707     ok(SUCCEEDED(hr), "EndScene failed with 0x%08x\n", hr);
9708     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9709     ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
9710
9711     color = getPixelColor(device, 320, 240);
9712     ok(color_match(color, 0x00ffffff, 1), "texop Range < 0.0 returned 0x%08x, expected 0x00ffffff\n",
9713        color);
9714
9715     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
9716     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9717     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
9718     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9719     hr = IDirect3DDevice9_SetTexture(device, 1, NULL);
9720     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
9721     IDirect3DTexture9_Release(texture);
9722 }
9723
9724 static void alphareplicate_test(IDirect3DDevice9 *device) {
9725     struct vertex quad[] = {
9726         { -1.0,    -1.0,    0.1,    0x80ff00ff },
9727         {  1.0,    -1.0,    0.1,    0x80ff00ff },
9728         { -1.0,     1.0,    0.1,    0x80ff00ff },
9729         {  1.0,     1.0,    0.1,    0x80ff00ff },
9730     };
9731     HRESULT hr;
9732     DWORD color;
9733
9734     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
9735     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9736
9737     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
9738     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
9739
9740     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9741     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9742     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE | D3DTA_ALPHAREPLICATE);
9743     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9744
9745     hr = IDirect3DDevice9_BeginScene(device);
9746     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
9747     if(SUCCEEDED(hr)) {
9748         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
9749         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9750         hr = IDirect3DDevice9_EndScene(device);
9751         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
9752     }
9753
9754     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9755     ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
9756
9757     color = getPixelColor(device, 320, 240);
9758     ok(color_match(color, 0x00808080, 1), "alphareplicate test 0x%08x, expected 0x00808080\n",
9759        color);
9760
9761     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
9762     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9763
9764 }
9765
9766 static void dp3_alpha_test(IDirect3DDevice9 *device) {
9767     HRESULT hr;
9768     D3DCAPS9 caps;
9769     DWORD color;
9770     struct vertex quad[] = {
9771         { -1.0,    -1.0,    0.1,    0x408080c0 },
9772         {  1.0,    -1.0,    0.1,    0x408080c0 },
9773         { -1.0,     1.0,    0.1,    0x408080c0 },
9774         {  1.0,     1.0,    0.1,    0x408080c0 },
9775     };
9776
9777     memset(&caps, 0, sizeof(caps));
9778     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9779     ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x\n", hr);
9780     if (!(caps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3)) {
9781         skip("D3DTOP_DOTPRODUCT3 not supported\n");
9782         return;
9783     }
9784
9785     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
9786     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9787
9788     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
9789     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
9790
9791     /* dp3_x4 r0, diffuse_bias, tfactor_bias
9792      * mov r0.a, diffuse.a
9793      * mov r0, r0.a
9794      *
9795      * It turns out that the 2nd line is ignored, and the dp3 result written into r0.a instead
9796      * 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
9797      * (0.0 * 0.5 + 0.0 * 0.5 + 0.25 * 0.5) * 4 = 0.125 * 4 = 0.5, with a bunch of inprecision.
9798      */
9799     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);
9800     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9801     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
9802     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9803     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9804     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9805     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
9806     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9807     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
9808     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9809     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9810     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9811     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_CURRENT | D3DTA_ALPHAREPLICATE);
9812     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9813     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
9814     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9815     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0xffffffff);
9816     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9817
9818     hr = IDirect3DDevice9_BeginScene(device);
9819     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
9820     if(SUCCEEDED(hr)) {
9821         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
9822         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9823         hr = IDirect3DDevice9_EndScene(device);
9824         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
9825     }
9826
9827     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9828     ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
9829
9830     color = getPixelColor(device, 320, 240);
9831     ok(color_match(color, 0x00808080, 4), "dp3 alpha test 0x%08x, expected 0x00808080\n",
9832        color);
9833
9834     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
9835     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9836     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
9837     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9838     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
9839     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
9840 }
9841
9842 static void zwriteenable_test(IDirect3DDevice9 *device) {
9843     HRESULT hr;
9844     DWORD color;
9845     struct vertex quad1[] = {
9846         { -1.0,  -1.0,  0.1,    0x00ff0000},
9847         { -1.0,   1.0,  0.1,    0x00ff0000},
9848         {  1.0,  -1.0,  0.1,    0x00ff0000},
9849         {  1.0,   1.0,  0.1,    0x00ff0000},
9850     };
9851     struct vertex quad2[] = {
9852         { -1.0,  -1.0,  0.9,    0x0000ff00},
9853         { -1.0,   1.0,  0.9,    0x0000ff00},
9854         {  1.0,  -1.0,  0.9,    0x0000ff00},
9855         {  1.0,   1.0,  0.9,    0x0000ff00},
9856     };
9857
9858     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
9859     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9860
9861     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
9862     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
9863     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
9864     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9865     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
9866     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9867     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
9868     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9869
9870     hr = IDirect3DDevice9_BeginScene(device);
9871     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
9872     if(SUCCEEDED(hr)) {
9873         /* The Z buffer is filled with 1.0. Draw a red quad with z = 0.1, zenable = D3DZB_FALSE, zwriteenable = TRUE.
9874          * The red color is written because the z test is disabled. The question is whether the z = 0.1 values
9875          * are written into the Z buffer. After the draw, set zenable = TRUE and draw a green quad at z = 0.9.
9876          * If the values are written, the z test will fail(0.9 > 0.1) and the red color remains. If the values
9877          * are not written, the z test succeeds(0.9 < 1.0) and the green color is written. It turns out that
9878          * the screen is green, so zenable = D3DZB_FALSE and zwriteenable  = TRUE does NOT write to the z buffer.
9879          */
9880         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
9881         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9882         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
9883         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9884         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
9885         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9886
9887         hr = IDirect3DDevice9_EndScene(device);
9888         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
9889     }
9890
9891     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9892     ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
9893     color = getPixelColor(device, 320, 240);
9894     ok(color_match(color, 0x0000ff00, 1), "zwriteenable test returned 0x%08x, expected 0x0000ff00\n",
9895        color);
9896
9897     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
9898     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9899 }
9900
9901 static void alphatest_test(IDirect3DDevice9 *device) {
9902 #define ALPHATEST_PASSED 0x0000ff00
9903 #define ALPHATEST_FAILED 0x00ff0000
9904     struct {
9905         D3DCMPFUNC  func;
9906         DWORD       color_less;
9907         DWORD       color_equal;
9908         DWORD       color_greater;
9909     } testdata[] = {
9910         {   D3DCMP_NEVER,           ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED },
9911         {   D3DCMP_LESS,            ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED },
9912         {   D3DCMP_EQUAL,           ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED },
9913         {   D3DCMP_LESSEQUAL,       ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_FAILED },
9914         {   D3DCMP_GREATER,         ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_PASSED },
9915         {   D3DCMP_NOTEQUAL,        ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED },
9916         {   D3DCMP_GREATEREQUAL,    ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED },
9917         {   D3DCMP_ALWAYS,          ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED },
9918     };
9919     unsigned int i, j;
9920     HRESULT hr;
9921     DWORD color;
9922     struct vertex quad[] = {
9923         {   -1.0,    -1.0,   0.1,    ALPHATEST_PASSED | 0x80000000  },
9924         {    1.0,    -1.0,   0.1,    ALPHATEST_PASSED | 0x80000000  },
9925         {   -1.0,     1.0,   0.1,    ALPHATEST_PASSED | 0x80000000  },
9926         {    1.0,     1.0,   0.1,    ALPHATEST_PASSED | 0x80000000  },
9927     };
9928     D3DCAPS9 caps;
9929
9930     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, TRUE);
9931     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9932     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
9933     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
9934
9935     for(j = 0; j < 2; j++) {
9936         if(j == 1) {
9937             /* Try a pixel shader instead of fixed function. The wined3d code may emulate
9938              * the alpha test either for performance reasons(floating point RTs) or to work
9939              * around driver bugs(Geforce 7x00 cards on MacOS). There may be a different
9940              * codepath for ffp and shader in this case, and the test should cover both
9941              */
9942             IDirect3DPixelShader9 *ps;
9943             DWORD shader_code[] = {
9944                 0xffff0101,                                 /* ps_1_1           */
9945                 0x00000001, 0x800f0000, 0x90e40000,         /* mov r0, v0       */
9946                 0x0000ffff                                  /* end              */
9947             };
9948             memset(&caps, 0, sizeof(caps));
9949             IDirect3DDevice9_GetDeviceCaps(device, &caps);
9950             ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with 0x%08x\n", hr);
9951             if(caps.PixelShaderVersion < D3DPS_VERSION(1, 1)) {
9952                 break;
9953             }
9954
9955             hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &ps);
9956             ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed with 0x%08x\n", hr);
9957             IDirect3DDevice9_SetPixelShader(device, ps);
9958             ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with 0x%08x\n", hr);
9959             IDirect3DPixelShader9_Release(ps);
9960         }
9961
9962         for(i = 0; i < (sizeof(testdata)/sizeof(testdata[0])); i++) {
9963             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAFUNC, testdata[i].func);
9964             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9965
9966             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0, 0);
9967             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9968             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAREF, 0x90);
9969             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9970             hr = IDirect3DDevice9_BeginScene(device);
9971             ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
9972             if(SUCCEEDED(hr)) {
9973                 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
9974                 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9975                 hr = IDirect3DDevice9_EndScene(device);
9976                 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with 0x%08x\n", hr);
9977             }
9978             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9979             ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
9980             color = getPixelColor(device, 320, 240);
9981             ok(color_match(color, testdata[i].color_less, 1), "Alphatest failed. Got color 0x%08x, expected 0x%08x. alpha < ref, func %u\n",
9982             color, testdata[i].color_less, testdata[i].func);
9983
9984             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0, 0);
9985             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9986             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAREF, 0x80);
9987             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
9988             hr = IDirect3DDevice9_BeginScene(device);
9989             ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
9990             if(SUCCEEDED(hr)) {
9991                 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
9992                 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9993                 hr = IDirect3DDevice9_EndScene(device);
9994                 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with 0x%08x\n", hr);
9995             }
9996             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9997             ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
9998             color = getPixelColor(device, 320, 240);
9999             ok(color_match(color, testdata[i].color_equal, 1), "Alphatest failed. Got color 0x%08x, expected 0x%08x. alpha == ref, func %u\n",
10000             color, testdata[i].color_equal, testdata[i].func);
10001
10002             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0, 0);
10003             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10004             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAREF, 0x70);
10005             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10006             hr = IDirect3DDevice9_BeginScene(device);
10007             ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
10008             if(SUCCEEDED(hr)) {
10009                 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
10010                 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10011                 hr = IDirect3DDevice9_EndScene(device);
10012                 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with 0x%08x\n", hr);
10013             }
10014             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10015             ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
10016             color = getPixelColor(device, 320, 240);
10017             ok(color_match(color, testdata[i].color_greater, 1), "Alphatest failed. Got color 0x%08x, expected 0x%08x. alpha > ref, func %u\n",
10018             color, testdata[i].color_greater, testdata[i].func);
10019         }
10020     }
10021
10022     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, FALSE);
10023     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10024     IDirect3DDevice9_SetPixelShader(device, NULL);
10025     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with 0x%08x\n", hr);
10026 }
10027
10028 START_TEST(visual)
10029 {
10030     IDirect3DDevice9 *device_ptr;
10031     D3DCAPS9 caps;
10032     HRESULT hr;
10033     DWORD color;
10034
10035     d3d9_handle = LoadLibraryA("d3d9.dll");
10036     if (!d3d9_handle)
10037     {
10038         skip("Could not load d3d9.dll\n");
10039         return;
10040     }
10041
10042     device_ptr = init_d3d9();
10043     if (!device_ptr)
10044     {
10045         skip("Creating the device failed\n");
10046         return;
10047     }
10048
10049     IDirect3DDevice9_GetDeviceCaps(device_ptr, &caps);
10050
10051     /* Check for the reliability of the returned data */
10052     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
10053     if(FAILED(hr))
10054     {
10055         skip("Clear failed, can't assure correctness of the test results, skipping\n");
10056         goto cleanup;
10057     }
10058     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
10059
10060     color = getPixelColor(device_ptr, 1, 1);
10061     if(color !=0x00ff0000)
10062     {
10063         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
10064         goto cleanup;
10065     }
10066
10067     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xff00ddee, 0.0, 0);
10068     if(FAILED(hr))
10069     {
10070         skip("Clear failed, can't assure correctness of the test results, skipping\n");
10071         goto cleanup;
10072     }
10073     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
10074
10075     color = getPixelColor(device_ptr, 639, 479);
10076     if(color != 0x0000ddee)
10077     {
10078         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
10079         goto cleanup;
10080     }
10081
10082     /* Now execute the real tests */
10083     stretchrect_test(device_ptr);
10084     lighting_test(device_ptr);
10085     clear_test(device_ptr);
10086     fog_test(device_ptr);
10087     if(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
10088     {
10089         test_cube_wrap(device_ptr);
10090     } else {
10091         skip("No cube texture support\n");
10092     }
10093     z_range_test(device_ptr);
10094     if(caps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)
10095     {
10096         maxmip_test(device_ptr);
10097     }
10098     else
10099     {
10100         skip("No mipmap support\n");
10101     }
10102     offscreen_test(device_ptr);
10103     alpha_test(device_ptr);
10104     shademode_test(device_ptr);
10105     srgbtexture_test(device_ptr);
10106     release_buffer_test(device_ptr);
10107     float_texture_test(device_ptr);
10108     g16r16_texture_test(device_ptr);
10109     pixelshader_blending_test(device_ptr);
10110     texture_transform_flags_test(device_ptr);
10111     autogen_mipmap_test(device_ptr);
10112     fixed_function_decl_test(device_ptr);
10113     conditional_np2_repeat_test(device_ptr);
10114     fixed_function_bumpmap_test(device_ptr);
10115     if(caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) {
10116         stencil_cull_test(device_ptr);
10117     } else {
10118         skip("No two sided stencil support\n");
10119     }
10120     pointsize_test(device_ptr);
10121     tssargtemp_test(device_ptr);
10122     np2_stretch_rect_test(device_ptr);
10123     yuv_color_test(device_ptr);
10124     zwriteenable_test(device_ptr);
10125     alphatest_test(device_ptr);
10126
10127     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1))
10128     {
10129         test_constant_clamp_vs(device_ptr);
10130         test_compare_instructions(device_ptr);
10131     }
10132     else skip("No vs_1_1 support\n");
10133
10134     if (caps.VertexShaderVersion >= D3DVS_VERSION(2, 0))
10135     {
10136         test_mova(device_ptr);
10137         if (caps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) {
10138             test_vshader_input(device_ptr);
10139             test_vshader_float16(device_ptr);
10140             stream_test(device_ptr);
10141         } else {
10142             skip("No vs_3_0 support\n");
10143         }
10144     }
10145     else skip("No vs_2_0 support\n");
10146
10147     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1) && caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
10148     {
10149         fog_with_shader_test(device_ptr);
10150         fog_srgbwrite_test(device_ptr);
10151     }
10152     else skip("No vs_1_1 and ps_1_1 support\n");
10153
10154     if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
10155     {
10156         texbem_test(device_ptr);
10157         texdepth_test(device_ptr);
10158         texkill_test(device_ptr);
10159         x8l8v8u8_test(device_ptr);
10160         if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 4)) {
10161             constant_clamp_ps_test(device_ptr);
10162             cnd_test(device_ptr);
10163             if (caps.PixelShaderVersion >= D3DPS_VERSION(2, 0)) {
10164                 dp2add_ps_test(device_ptr);
10165                 if (caps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) {
10166                     nested_loop_test(device_ptr);
10167                     fixed_function_varying_test(device_ptr);
10168                     vFace_register_test(device_ptr);
10169                     vpos_register_test(device_ptr);
10170                     multiple_rendertargets_test(device_ptr);
10171                     if(caps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) {
10172                         vshader_version_varying_test(device_ptr);
10173                         pshader_version_varying_test(device_ptr);
10174                     } else {
10175                         skip("No vs_3_0 support\n");
10176                     }
10177                 } else {
10178                     skip("No ps_3_0 support\n");
10179                 }
10180             } else {
10181                 skip("No ps_2_0 support\n");
10182             }
10183         }
10184     }
10185     else skip("No ps_1_1 support\n");
10186
10187     texop_test(device_ptr);
10188     texop_range_test(device_ptr);
10189     alphareplicate_test(device_ptr);
10190     dp3_alpha_test(device_ptr);
10191
10192 cleanup:
10193     if(device_ptr) {
10194         ULONG ref;
10195
10196         D3DPRESENT_PARAMETERS present_parameters;
10197         IDirect3DSwapChain9 *swapchain;
10198         IDirect3DDevice9_GetSwapChain(device_ptr, 0, &swapchain);
10199         IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters);
10200         IDirect3DSwapChain9_Release(swapchain);
10201         ref = IDirect3DDevice9_Release(device_ptr);
10202         DestroyWindow(present_parameters.hDeviceWindow);
10203         ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
10204     }
10205 }