dinput: Fix printing NULL strings.
[wine] / dlls / d3d9 / tests / visual.c
1 /*
2  * Copyright 2005, 2007-2008 Henri Verbeet
3  * Copyright (C) 2007-2008 Stefan Dösinger(for CodeWeavers)
4  * Copyright (C) 2008 Jason Green(for TransGaming)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 /* This test framework allows limited testing of rendering results. Things are rendered, shown on
22  * the framebuffer, read back from there and compared to expected colors.
23  *
24  * However, neither d3d nor opengl is guaranteed to be pixel exact, and thus the capability of this test
25  * is rather limited. As a general guideline for adding tests, do not rely on corner pixels. Draw a big enough
26  * area which shows specific behavior(like a quad on the whole screen), and try to get resulting colors with
27  * all bits set or unset in all channels(like pure red, green, blue, white, black). Hopefully everything that
28  * causes visible results in games can be tested in a way that does not depend on pixel exactness
29  */
30
31 #define COBJMACROS
32 #include <d3d9.h>
33 #include "wine/test.h"
34
35 static HMODULE d3d9_handle = 0;
36
37 static HWND create_window(void)
38 {
39     WNDCLASS wc = {0};
40     HWND ret;
41     wc.lpfnWndProc = DefWindowProc;
42     wc.lpszClassName = "d3d9_test_wc";
43     RegisterClass(&wc);
44
45     ret = CreateWindow("d3d9_test_wc", "d3d9_test",
46                         WS_SYSMENU | WS_POPUP , 0, 0, 640, 480, 0, 0, 0, 0);
47     ShowWindow(ret, SW_SHOW);
48     return ret;
49 }
50
51 static BOOL color_match(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
52 {
53     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
54     c1 >>= 8; c2 >>= 8;
55     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
56     c1 >>= 8; c2 >>= 8;
57     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
58     c1 >>= 8; c2 >>= 8;
59     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
60     return TRUE;
61 }
62
63 /* Locks a given surface and returns the color at (x,y).  It's the caller's
64  * responsibility to only pass in lockable surfaces and valid x,y coordinates */
65 static DWORD getPixelColorFromSurface(IDirect3DSurface9 *surface, UINT x, UINT y)
66 {
67     DWORD color;
68     HRESULT hr;
69     D3DSURFACE_DESC desc;
70     RECT rectToLock = {x, y, x+1, y+1};
71     D3DLOCKED_RECT lockedRect;
72
73     hr = IDirect3DSurface9_GetDesc(surface, &desc);
74     if(FAILED(hr))  /* This is not a test */
75     {
76         trace("Can't get the surface description, hr=%08x\n", hr);
77         return 0xdeadbeef;
78     }
79
80     hr = IDirect3DSurface9_LockRect(surface, &lockedRect, &rectToLock, D3DLOCK_READONLY);
81     if(FAILED(hr))  /* This is not a test */
82     {
83         trace("Can't lock the surface, hr=%08x\n", hr);
84         return 0xdeadbeef;
85     }
86     switch(desc.Format) {
87         case D3DFMT_A8R8G8B8:
88         {
89             color = ((DWORD *) lockedRect.pBits)[0] & 0xffffffff;
90             break;
91         }
92         default:
93             trace("Error: unknown surface format: %d\n", desc.Format);
94             color = 0xdeadbeef;
95             break;
96     }
97     hr = IDirect3DSurface9_UnlockRect(surface);
98     if(FAILED(hr))
99     {
100         trace("Can't unlock the surface, hr=%08x\n", hr);
101     }
102     return color;
103 }
104
105 static DWORD getPixelColor(IDirect3DDevice9 *device, UINT x, UINT y)
106 {
107     DWORD ret;
108     IDirect3DSurface9 *surf = NULL, *target = NULL;
109     HRESULT hr;
110     D3DLOCKED_RECT lockedRect;
111     RECT rectToLock = {x, y, x+1, y+1};
112
113     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 640, 480,
114             D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL);
115     if (FAILED(hr) || !surf)
116     {
117         trace("Can't create an offscreen plain surface to read the render target data, hr=%08x\n", hr);
118         return 0xdeadbeef;
119     }
120
121     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &target);
122     if(FAILED(hr))
123     {
124         trace("Can't get the render target, hr=%08x\n", hr);
125         ret = 0xdeadbeed;
126         goto out;
127     }
128
129     hr = IDirect3DDevice9_GetRenderTargetData(device, target, surf);
130     if (FAILED(hr))
131     {
132         trace("Can't read the render target data, hr=%08x\n", hr);
133         ret = 0xdeadbeec;
134         goto out;
135     }
136
137     hr = IDirect3DSurface9_LockRect(surf, &lockedRect, &rectToLock, D3DLOCK_READONLY);
138     if(FAILED(hr))
139     {
140         trace("Can't lock the offscreen surface, hr=%08x\n", hr);
141         ret = 0xdeadbeeb;
142         goto out;
143     }
144
145     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
146      * really important for these tests
147      */
148     ret = ((DWORD *) lockedRect.pBits)[0] & 0x00ffffff;
149     hr = IDirect3DSurface9_UnlockRect(surf);
150     if(FAILED(hr))
151     {
152         trace("Can't unlock the offscreen surface, hr=%08x\n", hr);
153     }
154
155 out:
156     if(target) IDirect3DSurface9_Release(target);
157     if(surf) IDirect3DSurface9_Release(surf);
158     return ret;
159 }
160
161 static IDirect3DDevice9 *init_d3d9(void)
162 {
163     IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion) = 0;
164     IDirect3D9 *d3d9_ptr = 0;
165     IDirect3DDevice9 *device_ptr = 0;
166     D3DPRESENT_PARAMETERS present_parameters;
167     HRESULT hr;
168     D3DADAPTER_IDENTIFIER9 identifier;
169
170     d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
171     ok(d3d9_create != NULL, "Failed to get address of Direct3DCreate9\n");
172     if (!d3d9_create) return NULL;
173
174     d3d9_ptr = d3d9_create(D3D_SDK_VERSION);
175     if (!d3d9_ptr)
176     {
177         skip("could not create D3D9\n");
178         return NULL;
179     }
180
181     ZeroMemory(&present_parameters, sizeof(present_parameters));
182     present_parameters.Windowed = TRUE;
183     present_parameters.hDeviceWindow = create_window();
184     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
185     present_parameters.BackBufferWidth = 640;
186     present_parameters.BackBufferHeight = 480;
187     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
188     present_parameters.EnableAutoDepthStencil = TRUE;
189     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
190
191     memset(&identifier, 0, sizeof(identifier));
192     hr = IDirect3D9_GetAdapterIdentifier(d3d9_ptr, 0, 0, &identifier);
193     ok(hr == D3D_OK, "Failed to get adapter identifier description\n");
194     trace("Driver string: \"%s\"\n", identifier.Driver);
195     trace("Description string: \"%s\"\n", identifier.Description);
196     ok(identifier.Description[0] != '\0', "Empty driver description\n");
197     trace("Device name string: \"%s\"\n", identifier.DeviceName);
198     ok(identifier.DeviceName[0]  != '\0', "Empty device name\n");
199     trace("Driver version %d.%d.%d.%d\n",
200           HIWORD(U(identifier.DriverVersion).HighPart), LOWORD(U(identifier.DriverVersion).HighPart),
201           HIWORD(U(identifier.DriverVersion).LowPart), LOWORD(U(identifier.DriverVersion).LowPart));
202
203     hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
204             present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
205     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE || hr == D3DERR_INVALIDCALL,
206             "Failed to create a device, hr %#x.\n", hr);
207
208     return device_ptr;
209 }
210
211 struct vertex
212 {
213     float x, y, z;
214     DWORD diffuse;
215 };
216
217 struct tvertex
218 {
219     float x, y, z, rhw;
220     DWORD diffuse;
221 };
222
223 struct nvertex
224 {
225     float x, y, z;
226     float nx, ny, nz;
227     DWORD diffuse;
228 };
229
230 static void lighting_test(IDirect3DDevice9 *device)
231 {
232     HRESULT hr;
233     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
234     DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
235     DWORD color;
236     D3DMATERIAL9 material, old_material;
237     DWORD cop, carg;
238     DWORD old_colorwrite;
239
240     float mat[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
241                       0.0f, 1.0f, 0.0f, 0.0f,
242                       0.0f, 0.0f, 1.0f, 0.0f,
243                       0.0f, 0.0f, 0.0f, 1.0f };
244
245     struct vertex unlitquad[] =
246     {
247         {-1.0f, -1.0f,   0.1f,                          0xffff0000},
248         {-1.0f,  0.0f,   0.1f,                          0xffff0000},
249         { 0.0f,  0.0f,   0.1f,                          0xffff0000},
250         { 0.0f, -1.0f,   0.1f,                          0xffff0000},
251     };
252     struct vertex litquad[] =
253     {
254         {-1.0f,  0.0f,   0.1f,                          0xff00ff00},
255         {-1.0f,  1.0f,   0.1f,                          0xff00ff00},
256         { 0.0f,  1.0f,   0.1f,                          0xff00ff00},
257         { 0.0f,  0.0f,   0.1f,                          0xff00ff00},
258     };
259     struct nvertex unlitnquad[] =
260     {
261         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
262         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
263         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
264         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
265     };
266     struct nvertex litnquad[] =
267     {
268         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
269         { 0.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
270         { 1.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
271         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
272     };
273     WORD Indices[] = {0, 1, 2, 2, 3, 0};
274
275     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
276     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
277
278     /* Setup some states that may cause issues */
279     hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(0), (D3DMATRIX *) mat);
280     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %08x\n", hr);
281     hr = IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, (D3DMATRIX *)mat);
282     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %08x\n", hr);
283     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, (D3DMATRIX *) mat);
284     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %08x\n", hr);
285     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
286     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
287     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
288     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
289     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
290     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
291     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
292     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
293     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, FALSE);
294     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
295     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
296     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
297     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, FALSE);
298     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
299     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
300     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
301     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_COLORWRITEENABLE, &old_colorwrite);
302     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
303     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
304     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
305
306     hr = IDirect3DDevice9_SetFVF(device, 0);
307     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
308
309     hr = IDirect3DDevice9_SetFVF(device, fvf);
310     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
311
312     hr = IDirect3DDevice9_BeginScene(device);
313     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
314     if(hr == D3D_OK)
315     {
316         /* No lights are defined... That means, lit vertices should be entirely black */
317         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
318         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
319         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
320                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitquad, sizeof(unlitquad[0]));
321         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
322
323         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
324         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
325         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
326                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litquad, sizeof(litquad[0]));
327         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
328
329         hr = IDirect3DDevice9_SetFVF(device, nfvf);
330         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
331
332         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
333         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
334         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
335                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitnquad, sizeof(unlitnquad[0]));
336         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
337
338         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
339         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
340         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
341                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litnquad, sizeof(litnquad[0]));
342         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
343
344         IDirect3DDevice9_EndScene(device);
345         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
346     }
347
348     color = getPixelColor(device, 160, 360); /* Lower left quad - unlit without normals */
349     ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x, expected 0x00ff0000.\n", color);
350     color = getPixelColor(device, 160, 120); /* Upper left quad - lit without normals */
351     ok(color == 0x00000000, "Lit quad without normals has color 0x%08x, expected 0x00000000.\n", color);
352     color = getPixelColor(device, 480, 360); /* Lower left quad - unlit with normals */
353     ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x, expected 0x000000ff.\n", color);
354     color = getPixelColor(device, 480, 120); /* Upper left quad - lit with normals */
355     ok(color == 0x00000000, "Lit quad with normals has color 0x%08x, expected 0x00000000.\n", color);
356
357     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
358
359     hr = IDirect3DDevice9_GetMaterial(device, &old_material);
360     ok(hr == D3D_OK, "IDirect3DDevice9_GetMaterial returned %08x\n", hr);
361     memset(&material, 0, sizeof(material));
362     material.Diffuse.r = 0.0;
363     material.Diffuse.g = 0.0;
364     material.Diffuse.b = 0.0;
365     material.Diffuse.a = 1.0;
366     material.Ambient.r = 0.0;
367     material.Ambient.g = 0.0;
368     material.Ambient.b = 0.0;
369     material.Ambient.a = 0.0;
370     material.Specular.r = 0.0;
371     material.Specular.g = 0.0;
372     material.Specular.b = 0.0;
373     material.Specular.a = 0.0;
374     material.Emissive.r = 0.0;
375     material.Emissive.g = 0.0;
376     material.Emissive.b = 0.0;
377     material.Emissive.a = 0.0;
378     material.Power = 0.0;
379     IDirect3DDevice9_SetMaterial(device, &material);
380     ok(hr == D3D_OK, "IDirect3DDevice9_SetMaterial returned %08x\n", hr);
381
382     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL);
383     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
384     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
385     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
386
387     hr = IDirect3DDevice9_GetTextureStageState(device, 0, D3DTSS_COLOROP, &cop);
388     ok(hr == D3D_OK, "IDirect3DDevice9_GetTextureStageState returned %08x\n", hr);
389     hr = IDirect3DDevice9_GetTextureStageState(device, 0, D3DTSS_COLORARG1, &carg);
390     ok(hr == D3D_OK, "IDirect3DDevice9_GetTextureStageState returned %08x\n", hr);
391     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
392     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
393     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE | D3DTA_ALPHAREPLICATE);
394     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
395
396     hr = IDirect3DDevice9_BeginScene(device);
397     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
398     if(SUCCEEDED(hr)) {
399         struct vertex lighting_test[] = {
400             {-1.0,   -1.0,   0.1,    0x8000ff00},
401             { 1.0,   -1.0,   0.1,    0x80000000},
402             {-1.0,    1.0,   0.1,    0x8000ff00},
403             { 1.0,    1.0,   0.1,    0x80000000}
404         };
405         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
406         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr=%08x\n", hr);
407         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, lighting_test, sizeof(lighting_test[0]));
408         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
409
410         hr = IDirect3DDevice9_EndScene(device);
411         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
412     }
413
414     color = getPixelColor(device, 320, 240);
415     ok(color == 0x00ffffff, "Lit vertex alpha test returned color %08x, expected 0x00ffffff\n", color);
416     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
417
418     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, cop);
419     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
420     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
421     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
422     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);
423     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
424     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
425     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
426     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, old_colorwrite);
427     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
428     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, carg);
429     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState returned %08x\n", hr);
430     hr = IDirect3DDevice9_SetMaterial(device, &old_material);
431     ok(hr == D3D_OK, "IDirect3DDevice9_SetMaterial returned %08x\n", hr);
432 }
433
434 static void clear_test(IDirect3DDevice9 *device)
435 {
436     /* Tests the correctness of clearing parameters */
437     HRESULT hr;
438     D3DRECT rect[2];
439     D3DRECT rect_negneg;
440     DWORD color;
441     D3DVIEWPORT9 old_vp, vp;
442     RECT scissor;
443     DWORD oldColorWrite;
444     BOOL invalid_clear_failed = FALSE;
445
446     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
447     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
448
449     /* Positive x, negative y */
450     rect[0].x1 = 0;
451     rect[0].y1 = 480;
452     rect[0].x2 = 320;
453     rect[0].y2 = 240;
454
455     /* Positive x, positive y */
456     rect[1].x1 = 0;
457     rect[1].y1 = 0;
458     rect[1].x2 = 320;
459     rect[1].y2 = 240;
460     /* Clear 2 rectangles with one call. The refrast returns an error in this case, every real driver tested so far
461      * returns D3D_OK, but ignores the rectangle silently
462      */
463     hr = IDirect3DDevice9_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
464     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
465     if(hr == D3DERR_INVALIDCALL) invalid_clear_failed = TRUE;
466
467     /* negative x, negative y */
468     rect_negneg.x1 = 640;
469     rect_negneg.y1 = 240;
470     rect_negneg.x2 = 320;
471     rect_negneg.y2 = 0;
472     hr = IDirect3DDevice9_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
473     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %08x\n", hr);
474     if(hr == D3DERR_INVALIDCALL) invalid_clear_failed = TRUE;
475
476     color = getPixelColor(device, 160, 360); /* lower left quad */
477     ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
478     color = getPixelColor(device, 160, 120); /* upper left quad */
479     if(invalid_clear_failed) {
480         /* If the negative rectangle was refused, the other rectangles in the list shouldn't be cleared either */
481         ok(color == 0x00ffffff, "Clear rectangle 1(pos, pos) has color %08x\n", color);
482     } else {
483         /* If the negative rectangle was dropped silently, the correct ones are cleared */
484         ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
485     }
486     color = getPixelColor(device, 480, 360); /* lower right quad  */
487     ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
488     color = getPixelColor(device, 480, 120); /* upper right quad */
489     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
490
491     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
492
493     /* Hack to work around a nvidia windows driver bug. The clear below is supposed to
494      * clear the red quad in the top left part of the render target. For some reason it
495      * doesn't work if the clear color is 0xffffffff on some versions of the Nvidia Windows
496      * driver(tested on 8.17.12.5896, Win7). A clear with a different color works around
497      * this bug and fixes the clear with the white color. Even 0xfeffffff works, but let's
498      * pick some obvious value
499      */
500     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xdeadbabe, 0.0, 0);
501     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
502
503     /* Test how the viewport affects clears */
504     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
505     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
506     hr = IDirect3DDevice9_GetViewport(device, &old_vp);
507     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
508
509     vp.X = 160;
510     vp.Y = 120;
511     vp.Width = 160;
512     vp.Height = 120;
513     vp.MinZ = 0.0;
514     vp.MaxZ = 1.0;
515     hr = IDirect3DDevice9_SetViewport(device, &vp);
516     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
517     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
518     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
519
520     vp.X = 320;
521     vp.Y = 240;
522     vp.Width = 320;
523     vp.Height = 240;
524     vp.MinZ = 0.0;
525     vp.MaxZ = 1.0;
526     hr = IDirect3DDevice9_SetViewport(device, &vp);
527     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
528     rect[0].x1 = 160;
529     rect[0].y1 = 120;
530     rect[0].x2 = 480;
531     rect[0].y2 = 360;
532     hr = IDirect3DDevice9_Clear(device, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
533     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
534
535     hr = IDirect3DDevice9_SetViewport(device, &old_vp);
536     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
537
538     color = getPixelColor(device, 158, 118);
539     ok(color == 0x00ffffff, "(158,118) has color %08x\n", color);
540     color = getPixelColor(device, 162, 118);
541     ok(color == 0x00ffffff, "(162,118) has color %08x\n", color);
542     color = getPixelColor(device, 158, 122);
543     ok(color == 0x00ffffff, "(158,122) has color %08x\n", color);
544     color = getPixelColor(device, 162, 122);
545     ok(color == 0x000000ff, "(162,122) has color %08x\n", color);
546
547     color = getPixelColor(device, 318, 238);
548     ok(color == 0x000000ff, "(318,238) has color %08x\n", color);
549     color = getPixelColor(device, 322, 238);
550     ok(color == 0x00ffffff, "(322,328) has color %08x\n", color);
551     color = getPixelColor(device, 318, 242);
552     ok(color == 0x00ffffff, "(318,242) has color %08x\n", color);
553     color = getPixelColor(device, 322, 242);
554     ok(color == 0x0000ff00, "(322,242) has color %08x\n", color);
555
556     color = getPixelColor(device, 478, 358);
557     ok(color == 0x0000ff00, "(478,358 has color %08x\n", color);
558     color = getPixelColor(device, 482, 358);
559     ok(color == 0x00ffffff, "(482,358) has color %08x\n", color);
560     color = getPixelColor(device, 478, 362);
561     ok(color == 0x00ffffff, "(478,362) has color %08x\n", color);
562     color = getPixelColor(device, 482, 362);
563     ok(color == 0x00ffffff, "(482,362) has color %08x\n", color);
564
565     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
566
567     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
568     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
569
570     scissor.left = 160;
571     scissor.right = 480;
572     scissor.top = 120;
573     scissor.bottom = 360;
574     hr = IDirect3DDevice9_SetScissorRect(device, &scissor);
575     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %08x\n", hr);
576     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, TRUE);
577     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %08x\n", hr);
578
579     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
580     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
581     hr = IDirect3DDevice9_Clear(device, 1, &rect[1], D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
582     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
583
584     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, FALSE);
585     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %08x\n", hr);
586
587     color = getPixelColor(device, 158, 118);
588     ok(color == 0x00ffffff, "Pixel 158/118 has color %08x\n", color);
589     color = getPixelColor(device, 162, 118);
590     ok(color == 0x00ffffff, "Pixel 162/118 has color %08x\n", color);
591     color = getPixelColor(device, 158, 122);
592     ok(color == 0x00ffffff, "Pixel 158/122 has color %08x\n", color);
593     color = getPixelColor(device, 162, 122);
594     ok(color == 0x00ff0000, "Pixel 162/122 has color %08x\n", color);
595
596     color = getPixelColor(device, 158, 358);
597     ok(color == 0x00ffffff, "Pixel 158/358 has color %08x\n", color);
598     color = getPixelColor(device, 162, 358);
599     ok(color == 0x0000ff00, "Pixel 162/358 has color %08x\n", color);
600     color = getPixelColor(device, 158, 358);
601     ok(color == 0x00ffffff, "Pixel 158/358 has color %08x\n", color);
602     color = getPixelColor(device, 162, 362);
603     ok(color == 0x00ffffff, "Pixel 162/362 has color %08x\n", color);
604
605     color = getPixelColor(device, 478, 118);
606     ok(color == 0x00ffffff, "Pixel 158/118 has color %08x\n", color);
607     color = getPixelColor(device, 478, 122);
608     ok(color == 0x0000ff00, "Pixel 162/118 has color %08x\n", color);
609     color = getPixelColor(device, 482, 122);
610     ok(color == 0x00ffffff, "Pixel 158/122 has color %08x\n", color);
611     color = getPixelColor(device, 482, 358);
612     ok(color == 0x00ffffff, "Pixel 162/122 has color %08x\n", color);
613
614     color = getPixelColor(device, 478, 358);
615     ok(color == 0x0000ff00, "Pixel 478/358 has color %08x\n", color);
616     color = getPixelColor(device, 478, 362);
617     ok(color == 0x00ffffff, "Pixel 478/118 has color %08x\n", color);
618     color = getPixelColor(device, 482, 358);
619     ok(color == 0x00ffffff, "Pixel 482/122 has color %08x\n", color);
620     color = getPixelColor(device, 482, 362);
621     ok(color == 0x00ffffff, "Pixel 482/122 has color %08x\n", color);
622
623     color = getPixelColor(device, 318, 238);
624     ok(color == 0x00ff0000, "Pixel 318/238 has color %08x\n", color);
625     color = getPixelColor(device, 318, 242);
626     ok(color == 0x0000ff00, "Pixel 318/242 has color %08x\n", color);
627     color = getPixelColor(device, 322, 238);
628     ok(color == 0x0000ff00, "Pixel 322/238 has color %08x\n", color);
629     color = getPixelColor(device, 322, 242);
630     ok(color == 0x0000ff00, "Pixel 322/242 has color %08x\n", color);
631
632     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
633
634     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_COLORWRITEENABLE, &oldColorWrite);
635     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %08x\n", hr);
636     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED);
637     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
638
639     /* Same nvidia windows driver trouble with white clears as earlier in the same test */
640     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xdeadbeef, 0.0, 0);
641     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
642
643     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
644     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
645
646     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, oldColorWrite);
647     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %08x\n", hr);
648
649     /* Colorwriteenable does not affect the clear */
650     color = getPixelColor(device, 320, 240);
651     ok(color == 0x00ffffff, "Color write protected clear returned color %08x\n", color);
652
653     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
654 }
655
656 static void color_fill_test(IDirect3DDevice9 *device)
657 {
658     HRESULT hr;
659     IDirect3DSurface9 *backbuffer = NULL;
660     IDirect3DSurface9 *rt_surface = NULL;
661     IDirect3DSurface9 *offscreen_surface = NULL;
662     DWORD fill_color, color;
663
664     /* Test ColorFill on a the backbuffer (should pass) */
665     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
666     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
667     if(backbuffer)
668     {
669         fill_color = 0x112233;
670         hr = IDirect3DDevice9_ColorFill(device, backbuffer, NULL, fill_color);
671         ok(SUCCEEDED(hr), "Color fill failed, hr %#x.\n", hr);
672
673         color = getPixelColor(device, 0, 0);
674         ok(color == fill_color, "Expected color %08x, got %08x\n", fill_color, color);
675
676         IDirect3DSurface9_Release(backbuffer);
677     }
678
679     /* Test ColorFill on a render target surface (should pass) */
680     hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &rt_surface, NULL );
681     ok(hr == D3D_OK, "Unable to create render target surface, hr = %08x\n", hr);
682     if(rt_surface)
683     {
684         fill_color = 0x445566;
685         hr = IDirect3DDevice9_ColorFill(device, rt_surface, NULL, fill_color);
686         ok(SUCCEEDED(hr), "Color fill failed, hr %#x.\n", hr);
687
688         color = getPixelColorFromSurface(rt_surface, 0, 0);
689         ok(color == fill_color, "Expected color %08x, got %08x\n", fill_color, color);
690
691         IDirect3DSurface9_Release(rt_surface);
692     }
693
694     /* Test ColorFill on a offscreen plain surface in D3DPOOL_DEFAULT (should pass) */
695     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
696             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &offscreen_surface, NULL);
697     ok(hr == D3D_OK, "Unable to create offscreen plain surface, hr = %08x\n", hr);
698     if(offscreen_surface)
699     {
700         fill_color = 0x778899;
701         hr = IDirect3DDevice9_ColorFill(device, offscreen_surface, NULL, fill_color);
702         ok(SUCCEEDED(hr), "Color fill failed, hr %#x.\n", hr);
703
704         color = getPixelColorFromSurface(offscreen_surface, 0, 0);
705         ok(color == fill_color, "Expected color %08x, got %08x\n", fill_color, color);
706
707         IDirect3DSurface9_Release(offscreen_surface);
708     }
709
710     /* Try ColorFill on a offscreen surface in sysmem (should fail) */
711     offscreen_surface = NULL;
712     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
713             D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &offscreen_surface, NULL);
714     ok(hr == D3D_OK, "Unable to create offscreen plain surface, hr = %08x\n", hr);
715     if(offscreen_surface)
716     {
717         hr = IDirect3DDevice9_ColorFill(device, offscreen_surface, NULL, 0);
718         ok(hr == D3DERR_INVALIDCALL, "ColorFill on offscreen sysmem surface failed with hr = %08x\n", hr);
719
720         IDirect3DSurface9_Release(offscreen_surface);
721     }
722 }
723
724 typedef struct {
725     float in[4];
726     DWORD out;
727 } test_data_t;
728
729 /*
730  *  c7      mova    ARGB            mov     ARGB
731  * -2.4     -2      0x00ffff00      -3      0x00ff0000
732  * -1.6     -2      0x00ffff00      -2      0x00ffff00
733  * -0.4      0      0x0000ffff      -1      0x0000ff00
734  *  0.4      0      0x0000ffff       0      0x0000ffff
735  *  1.6      2      0x00ff00ff       1      0x000000ff
736  *  2.4      2      0x00ff00ff       2      0x00ff00ff
737  */
738 static void test_mova(IDirect3DDevice9 *device)
739 {
740     static const DWORD mova_test[] = {
741         0xfffe0200,                                                             /* vs_2_0                       */
742         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
743         0x05000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0   */
744         0x05000051, 0xa00f0001, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, /* def c1, 1.0, 1.0, 0.0, 1.0   */
745         0x05000051, 0xa00f0002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, /* def c2, 0.0, 1.0, 0.0, 1.0   */
746         0x05000051, 0xa00f0003, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 0.0, 1.0, 1.0, 1.0   */
747         0x05000051, 0xa00f0004, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c4, 0.0, 0.0, 1.0, 1.0   */
748         0x05000051, 0xa00f0005, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, /* def c5, 1.0, 0.0, 1.0, 1.0   */
749         0x05000051, 0xa00f0006, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c6, 1.0, 1.0, 1.0, 1.0   */
750         0x0200002e, 0xb0010000, 0xa0000007,                                     /* mova a0.x, c7.x              */
751         0x03000001, 0xd00f0000, 0xa0e42003, 0xb0000000,                         /* mov oD0, c[a0.x + 3]         */
752         0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
753         0x0000ffff                                                              /* END                          */
754     };
755     static const DWORD mov_test[] = {
756         0xfffe0101,                                                             /* vs_1_1                       */
757         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
758         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0   */
759         0x00000051, 0xa00f0001, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, /* def c1, 1.0, 1.0, 0.0, 1.0   */
760         0x00000051, 0xa00f0002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, /* def c2, 0.0, 1.0, 0.0, 1.0   */
761         0x00000051, 0xa00f0003, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 0.0, 1.0, 1.0, 1.0   */
762         0x00000051, 0xa00f0004, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c4, 0.0, 0.0, 1.0, 1.0   */
763         0x00000051, 0xa00f0005, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, /* def c5, 1.0, 0.0, 1.0, 1.0   */
764         0x00000051, 0xa00f0006, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c6, 1.0, 1.0, 1.0, 1.0   */
765         0x00000001, 0xb0010000, 0xa0000007,                                     /* mov a0.x, c7.x               */
766         0x00000001, 0xd00f0000, 0xa0e42003,                                     /* mov oD0, c[a0.x + 3]         */
767         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
768         0x0000ffff                                                              /* END                          */
769     };
770
771     static const test_data_t test_data[2][6] = {
772         {
773             {{-2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff0000},
774             {{-1.6f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
775             {{-0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ff00},
776             {{ 0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
777             {{ 1.6f, 0.0f, 0.0f, 0.0f}, 0x000000ff},
778             {{ 2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff}
779         },
780         {
781             {{-2.4f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
782             {{-1.6f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
783             {{-0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
784             {{ 0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
785             {{ 1.6f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff},
786             {{ 2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff}
787         }
788     };
789
790     static const float quad[][3] = {
791         {-1.0f, -1.0f, 0.0f},
792         {-1.0f,  1.0f, 0.0f},
793         { 1.0f, -1.0f, 0.0f},
794         { 1.0f,  1.0f, 0.0f},
795     };
796
797     static const D3DVERTEXELEMENT9 decl_elements[] = {
798         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
799         D3DDECL_END()
800     };
801
802     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
803     IDirect3DVertexShader9 *mova_shader = NULL;
804     IDirect3DVertexShader9 *mov_shader = NULL;
805     HRESULT hr;
806     UINT i, j;
807
808     hr = IDirect3DDevice9_CreateVertexShader(device, mova_test, &mova_shader);
809     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
810     hr = IDirect3DDevice9_CreateVertexShader(device, mov_test, &mov_shader);
811     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
812     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
813     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
814     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
815     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
816
817     hr = IDirect3DDevice9_SetVertexShader(device, mov_shader);
818     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
819     for(j = 0; j < 2; ++j)
820     {
821         for (i = 0; i < (sizeof(test_data[0]) / sizeof(test_data_t)); ++i)
822         {
823             DWORD color;
824
825             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 7, test_data[j][i].in, 1);
826             ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
827
828             hr = IDirect3DDevice9_BeginScene(device);
829             ok(SUCCEEDED(hr), "BeginScene failed (%08x)\n", hr);
830
831             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], 3 * sizeof(float));
832             ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
833
834             hr = IDirect3DDevice9_EndScene(device);
835             ok(SUCCEEDED(hr), "EndScene failed (%08x)\n", hr);
836
837             color = getPixelColor(device, 320, 240);
838             ok(color == test_data[j][i].out, "Expected color %08x, got %08x (for input %f, instruction %s)\n",
839                test_data[j][i].out, color, test_data[j][i].in[0], j == 0 ? "mov" : "mova");
840
841             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
842             ok(SUCCEEDED(hr), "Present failed (%08x)\n", hr);
843
844             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
845             ok(SUCCEEDED(hr), "Clear failed (%08x)\n", hr);
846         }
847         hr = IDirect3DDevice9_SetVertexShader(device, mova_shader);
848         ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
849     }
850
851     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
852     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
853
854     IDirect3DVertexDeclaration9_Release(vertex_declaration);
855     IDirect3DVertexShader9_Release(mova_shader);
856     IDirect3DVertexShader9_Release(mov_shader);
857 }
858
859 struct sVertex {
860     float x, y, z;
861     DWORD diffuse;
862     DWORD specular;
863 };
864
865 struct sVertexT {
866     float x, y, z, rhw;
867     DWORD diffuse;
868     DWORD specular;
869 };
870
871 static void fog_test(IDirect3DDevice9 *device)
872 {
873     HRESULT hr;
874     D3DCOLOR color;
875     float start = 0.0f, end = 1.0f;
876     D3DCAPS9 caps;
877     int i;
878
879     /* Gets full z based fog with linear fog, no fog with specular color */
880     struct sVertex untransformed_1[] = {
881         {-1,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
882         {-1,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
883         { 0,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
884         { 0,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
885     };
886     /* Ok, I am too lazy to deal with transform matrices */
887     struct sVertex untransformed_2[] = {
888         {-1,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
889         {-1,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
890         { 0,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
891         { 0,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
892     };
893     /* Untransformed ones. Give them a different diffuse color to make the test look
894      * nicer. It also makes making sure that they are drawn correctly easier.
895      */
896     struct sVertexT transformed_1[] = {
897         {320,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
898         {640,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
899         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
900         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
901     };
902     struct sVertexT transformed_2[] = {
903         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
904         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
905         {640,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
906         {320,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
907     };
908     struct vertex rev_fog_quads[] = {
909        {-1.0,   -1.0,   0.1,    0x000000ff},
910        {-1.0,    0.0,   0.1,    0x000000ff},
911        { 0.0,    0.0,   0.1,    0x000000ff},
912        { 0.0,   -1.0,   0.1,    0x000000ff},
913
914        { 0.0,   -1.0,   0.9,    0x000000ff},
915        { 0.0,    0.0,   0.9,    0x000000ff},
916        { 1.0,    0.0,   0.9,    0x000000ff},
917        { 1.0,   -1.0,   0.9,    0x000000ff},
918
919        { 0.0,    0.0,   0.4,    0x000000ff},
920        { 0.0,    1.0,   0.4,    0x000000ff},
921        { 1.0,    1.0,   0.4,    0x000000ff},
922        { 1.0,    0.0,   0.4,    0x000000ff},
923
924        {-1.0,    0.0,   0.7,    0x000000ff},
925        {-1.0,    1.0,   0.7,    0x000000ff},
926        { 0.0,    1.0,   0.7,    0x000000ff},
927        { 0.0,    0.0,   0.7,    0x000000ff},
928     };
929     WORD Indices[] = {0, 1, 2, 2, 3, 0};
930
931     const float ident_mat[16] =
932     {
933         1.0f, 0.0f, 0.0f, 0.0f,
934         0.0f, 1.0f, 0.0f, 0.0f,
935         0.0f, 0.0f, 1.0f, 0.0f,
936         0.0f, 0.0f, 0.0f, 1.0f
937     };
938     const float world_mat1[16] =
939     {
940         1.0f, 0.0f,  0.0f, 0.0f,
941         0.0f, 1.0f,  0.0f, 0.0f,
942         0.0f, 0.0f,  1.0f, 0.0f,
943         0.0f, 0.0f, -0.5f, 1.0f
944     };
945     const float world_mat2[16] =
946     {
947         1.0f, 0.0f, 0.0f, 0.0f,
948         0.0f, 1.0f, 0.0f, 0.0f,
949         0.0f, 0.0f, 1.0f, 0.0f,
950         0.0f, 0.0f, 1.0f, 1.0f
951     };
952     const float proj_mat[16] =
953     {
954         1.0f, 0.0f,  0.0f, 0.0f,
955         0.0f, 1.0f,  0.0f, 0.0f,
956         0.0f, 0.0f,  1.0f, 0.0f,
957         0.0f, 0.0f, -1.0f, 1.0f
958     };
959
960     const struct sVertex far_quad1[] =
961     {
962         {-1.0f, -1.0f, 0.5f, 0xffff0000, 0xff000000},
963         {-1.0f,  0.0f, 0.5f, 0xffff0000, 0xff000000},
964         { 0.0f,  0.0f, 0.5f, 0xffff0000, 0xff000000},
965         { 0.0f, -1.0f, 0.5f, 0xffff0000, 0xff000000},
966     };
967     const struct sVertex far_quad2[] =
968     {
969         {-1.0f, 0.0f, 1.5f, 0xffff0000, 0xff000000},
970         {-1.0f, 1.0f, 1.5f, 0xffff0000, 0xff000000},
971         { 0.0f, 1.0f, 1.5f, 0xffff0000, 0xff000000},
972         { 0.0f, 0.0f, 1.5f, 0xffff0000, 0xff000000},
973     };
974
975     memset(&caps, 0, sizeof(caps));
976     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
977     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %08x\n", hr);
978     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
979     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
980
981     /* Setup initial states: No lighting, fog on, fog color */
982     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
983     ok(hr == D3D_OK, "Turning off lighting returned %08x\n", hr);
984     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
985     ok(hr == D3D_OK, "Turning on fog calculations returned %08x\n", hr);
986     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
987     ok(hr == D3D_OK, "Setting fog color returned %#08x\n", hr);
988
989     /* First test: Both table fog and vertex fog off */
990     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
991     ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
992     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
993     ok(hr == D3D_OK, "Turning off vertex fog returned %08x\n", hr);
994
995     /* Start = 0, end = 1. Should be default, but set them */
996     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
997     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
998     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
999     ok(hr == D3D_OK, "Setting fog end returned %08x\n", hr);
1000
1001     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
1002     {
1003         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
1004         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
1005         /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
1006         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
1007                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, untransformed_1,
1008                                                      sizeof(untransformed_1[0]));
1009         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
1010
1011         /* That makes it use the Z value */
1012         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
1013         ok(hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR returned %#08x\n", hr);
1014         /* Untransformed, vertex fog != none (or table fog != none):
1015          * Use the Z value as input into the equation
1016          */
1017         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
1018                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, untransformed_2,
1019                                                      sizeof(untransformed_2[0]));
1020         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
1021
1022         /* transformed verts */
1023         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
1024         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
1025         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
1026         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
1027                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
1028                                                      sizeof(transformed_1[0]));
1029         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
1030
1031         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
1032         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
1033         /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
1034          * equation
1035          */
1036         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
1037                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_2,
1038                                                      sizeof(transformed_2[0]));
1039         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
1040
1041         hr = IDirect3DDevice9_EndScene(device);
1042         ok(hr == D3D_OK, "EndScene returned %08x\n", hr);
1043     }
1044     else
1045     {
1046         ok(FALSE, "BeginScene failed\n");
1047     }
1048
1049     color = getPixelColor(device, 160, 360);
1050     ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color);
1051     color = getPixelColor(device, 160, 120);
1052     ok(color_match(color, 0x0000ff00, 1), "Untransformed vertex with linear vertex fog has color %08x\n", color);
1053     color = getPixelColor(device, 480, 120);
1054     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
1055     if(caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
1056     {
1057         color = getPixelColor(device, 480, 360);
1058         ok(color_match(color, 0x0000ff00, 1), "Transformed vertex with linear table fog has color %08x\n", color);
1059     }
1060     else
1061     {
1062         /* Without fog table support the vertex fog is still applied, even though table fog is turned on.
1063          * The settings above result in no fogging with vertex fog
1064          */
1065         color = getPixelColor(device, 480, 120);
1066         ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
1067         trace("Info: Table fog not supported by this device\n");
1068     }
1069     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1070
1071     /* Now test the special case fogstart == fogend */
1072     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
1073     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
1074
1075     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
1076     {
1077         start = 512;
1078         end = 512;
1079         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
1080         ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
1081         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
1082         ok(hr == D3D_OK, "Setting fog end returned %08x\n", hr);
1083
1084         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
1085         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
1086         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
1087         ok( hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR returned %08x\n", hr);
1088         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
1089         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
1090
1091         /* Untransformed vertex, z coord = 0.1, fogstart = 512, fogend = 512. Would result in
1092          * a completely fog-free primitive because start > zcoord, but because start == end, the primitive
1093          * is fully covered by fog. The same happens to the 2nd untransformed quad with z = 1.0.
1094          * The third transformed quad remains unfogged because the fogcoords are read from the specular
1095          * color and has fixed fogstart and fogend.
1096          */
1097         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
1098                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, untransformed_1,
1099                 sizeof(untransformed_1[0]));
1100         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
1101         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
1102                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, untransformed_2,
1103                 sizeof(untransformed_2[0]));
1104         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
1105
1106         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
1107         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
1108         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
1109         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
1110                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
1111                 sizeof(transformed_1[0]));
1112         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %08x\n", hr);
1113
1114         hr = IDirect3DDevice9_EndScene(device);
1115         ok(hr == D3D_OK, "EndScene returned %08x\n", hr);
1116     }
1117     else
1118     {
1119         ok(FALSE, "BeginScene failed\n");
1120     }
1121     color = getPixelColor(device, 160, 360);
1122     ok(color_match(color, 0x0000ff00, 1), "Untransformed vertex with vertex fog and z = 0.1 has color %08x\n", color);
1123     color = getPixelColor(device, 160, 120);
1124     ok(color_match(color, 0x0000ff00, 1), "Untransformed vertex with vertex fog and z = 1.0 has color %08x\n", color);
1125     color = getPixelColor(device, 480, 120);
1126     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
1127     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1128
1129     /* Test "reversed" fog without shaders. With shaders this fails on a few Windows D3D implementations,
1130      * but without shaders it seems to work everywhere
1131      */
1132     end = 0.2;
1133     start = 0.8;
1134     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
1135     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
1136     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
1137     ok(hr == D3D_OK, "Setting fog end returned %08x\n", hr);
1138     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1139     ok( hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
1140
1141     /* Test reversed fog without shaders. ATI cards have problems with reversed fog and shaders, so
1142      * it doesn't seem very important for games. ATI cards also have problems with reversed table fog,
1143      * so skip this for now
1144      */
1145     for(i = 0; i < 1 /*2 - Table fog test disabled, fails on ATI */; i++) {
1146         const char *mode = (i ? "table" : "vertex");
1147         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
1148         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
1149         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, i == 0 ? D3DFOG_LINEAR : D3DFOG_NONE);
1150         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1151         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, i == 0 ? D3DFOG_NONE : D3DFOG_LINEAR);
1152         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1153         hr = IDirect3DDevice9_BeginScene(device);
1154         ok( hr == D3D_OK, "IDirect3DDDevice9_BeginScene returned %08x\n", hr);
1155         if(SUCCEEDED(hr)) {
1156             WORD Indices2[] = { 0,  1,  2,  2,  3, 0,
1157                                 4,  5,  6,  6,  7, 4,
1158                                 8,  9, 10, 10, 11, 8,
1159                             12, 13, 14, 14, 15, 12};
1160
1161             hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */,
1162                     16 /* NumVerts */, 8 /*PrimCount */, Indices2, D3DFMT_INDEX16, rev_fog_quads,
1163                     sizeof(rev_fog_quads[0]));
1164             ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
1165
1166             hr = IDirect3DDevice9_EndScene(device);
1167             ok( hr == D3D_OK, "IDirect3DDDevice9_EndScene returned %08x\n", hr);
1168         }
1169         color = getPixelColor(device, 160, 360);
1170         ok(color_match(color, 0x0000ff00, 1),
1171                 "Reversed %s fog: z=0.1 has color 0x%08x, expected 0x0000ff00 or 0x0000fe00\n", mode, color);
1172
1173         color = getPixelColor(device, 160, 120);
1174         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x2b, 0xd4), 2),
1175                 "Reversed %s fog: z=0.7 has color 0x%08x\n", mode, color);
1176
1177         color = getPixelColor(device, 480, 120);
1178         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xaa, 0x55), 2),
1179                 "Reversed %s fog: z=0.4 has color 0x%08x\n", mode, color);
1180
1181         color = getPixelColor(device, 480, 360);
1182         ok(color == 0x000000ff, "Reversed %s fog: z=0.9 has color 0x%08x, expected 0x000000ff\n", mode, color);
1183
1184         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1185
1186         if(!(caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)) {
1187             skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping reversed table fog test\n");
1188             break;
1189         }
1190     }
1191
1192     if (caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
1193     {
1194         /* A simple fog + non-identity world matrix test */
1195         hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(0), (const D3DMATRIX *)world_mat1);
1196         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %#08x\n", hr);
1197
1198         start = 0.0;
1199         end = 1.0;
1200         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *)&start));
1201         ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
1202         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *)&end));
1203         ok(hr == D3D_OK, "Setting fog end returned %08x\n", hr);
1204         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
1205         ok(hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %#08x\n", hr);
1206         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
1207         ok(hr == D3D_OK, "Turning off vertex fog returned %#08x\n", hr);
1208
1209         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1210         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %#08x\n", hr);
1211
1212         if (IDirect3DDevice9_BeginScene(device) == D3D_OK)
1213         {
1214             hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
1215             ok(hr == D3D_OK, "SetVertexShader returned %#08x\n", hr);
1216
1217             hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4,
1218                     2, Indices, D3DFMT_INDEX16, far_quad1, sizeof(far_quad1[0]));
1219             ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
1220
1221             hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4,
1222                     2, Indices, D3DFMT_INDEX16, far_quad2, sizeof(far_quad2[0]));
1223             ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
1224
1225             hr = IDirect3DDevice9_EndScene(device);
1226             ok(hr == D3D_OK, "EndScene returned %#08x\n", hr);
1227         }
1228         else
1229         {
1230             ok(FALSE, "BeginScene failed\n");
1231         }
1232
1233         color = getPixelColor(device, 160, 360);
1234         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00), 4),
1235                 "Unfogged quad has color %08x\n", color);
1236         color = getPixelColor(device, 160, 120);
1237         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 1),
1238                 "Fogged out quad has color %08x\n", color);
1239
1240         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1241
1242         /* Test fog behavior with an orthogonal (but non-identity) projection matrix */
1243         hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(0), (const D3DMATRIX *)world_mat2);
1244         ok(hr == D3D_OK, "SetTransform returned %#08x\n", hr);
1245         hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, (const D3DMATRIX *)proj_mat);
1246         ok(hr == D3D_OK, "SetTransform returned %#08x\n", hr);
1247
1248         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1249         ok(hr == D3D_OK, "Clear returned %#08x\n", hr);
1250
1251         if (IDirect3DDevice9_BeginScene(device) == D3D_OK)
1252         {
1253             hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
1254             ok(hr == D3D_OK, "SetVertexShader returned %#08x\n", hr);
1255
1256             hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4,
1257                     2, Indices, D3DFMT_INDEX16, untransformed_1, sizeof(untransformed_1[0]));
1258             ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
1259
1260             hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4,
1261                     2, Indices, D3DFMT_INDEX16, untransformed_2, sizeof(untransformed_2[0]));
1262             ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
1263
1264             hr = IDirect3DDevice9_EndScene(device);
1265             ok(hr == D3D_OK, "EndScene returned %#08x\n", hr);
1266         }
1267         else
1268         {
1269             ok(FALSE, "BeginScene failed\n");
1270         }
1271
1272         color = getPixelColor(device, 160, 360);
1273         todo_wine ok(color_match(color, 0x00e51900, 4), "Partially fogged quad has color %08x\n", color);
1274         color = getPixelColor(device, 160, 120);
1275         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 1),
1276                 "Fogged out quad has color %08x\n", color);
1277
1278         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1279
1280         hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(0), (const D3DMATRIX *)ident_mat);
1281         ok(hr == D3D_OK, "SetTransform returned %#08x\n", hr);
1282         hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, (const D3DMATRIX *)ident_mat);
1283         ok(hr == D3D_OK, "SetTransform returned %#08x\n", hr);
1284     }
1285     else
1286     {
1287         skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests\n");
1288     }
1289
1290     /* Test RANGEFOG vs FOGTABLEMODE */
1291     if ((caps.RasterCaps & (D3DPRASTERCAPS_FOGTABLE | D3DPRASTERCAPS_FOGRANGE)) ==
1292             (D3DPRASTERCAPS_FOGTABLE | D3DPRASTERCAPS_FOGRANGE))
1293     {
1294         struct sVertex untransformed_3[] =
1295         {
1296             {-1.0,-1.0,   0.4999f,      0xFFFF0000,     0xFF000000  },
1297             {-1.0, 1.0,   0.4999f,      0xFFFF0000,     0xFF000000  },
1298             { 1.0,-1.0,   0.4999f,      0xFFFF0000,     0xFF000000  },
1299             { 1.0, 1.0,   0.4999f,      0xFFFF0000,     0xFF000000  },
1300         };
1301
1302         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1303         ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed, hr %#x.\n", hr);
1304         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
1305         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetFVF failed, hr %#x.\n", hr);
1306
1307         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_RANGEFOGENABLE, TRUE);
1308         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
1309
1310         /* z=0.4999, set the fogstart to 0.5 and fogend slightly higher. If range fog
1311          * is not used, the fog coordinate will be equal to fogstart and the quad not
1312          * fogged. If range fog is used the fog coordinate will be slightly higher and
1313          * the fog coordinate will be > fogend, so we get a fully fogged quad. The fog
1314          * is calculated per vertex and interpolated, so even the center of the screen
1315          * where the difference doesn't matter will be fogged, but check the corners in
1316          * case a d3d/gl implementation decides to calculate the fog factor per fragment */
1317         start = 0.5f;
1318         end = 0.50001f;
1319         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
1320         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
1321         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
1322         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
1323
1324         /* Table fog: Range fog is not used */
1325         hr = IDirect3DDevice9_BeginScene(device);
1326         ok(SUCCEEDED(hr), "IDirect3DDevice9_BeginScene failed, hr %#x.\n", hr);
1327         if (SUCCEEDED(hr))
1328         {
1329             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
1330             ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
1331             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, untransformed_3, sizeof(*untransformed_3));
1332             ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitiveUP failed, hr %#x.\n", hr);
1333             hr = IDirect3DDevice9_EndScene(device);
1334             ok(SUCCEEDED(hr), "IDirect3DDevice9_EndScene failed, hr %#x.\n", hr);
1335         }
1336         color = getPixelColor(device, 10, 10);
1337         ok(color == 0x00ff0000, "Rangefog with table fog returned color 0x%08x\n", color);
1338         color = getPixelColor(device, 630, 10);
1339         ok(color == 0x00ff0000, "Rangefog with table fog returned color 0x%08x\n", color);
1340         color = getPixelColor(device, 10, 470);
1341         ok(color == 0x00ff0000, "Rangefog with table fog returned color 0x%08x\n", color);
1342         color = getPixelColor(device, 630, 470);
1343         ok(color == 0x00ff0000, "Rangefog with table fog returned color 0x%08x\n", color);
1344
1345         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1346         ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed, hr %#x.\n", hr);
1347
1348         /* Vertex fog: Rangefog is used */
1349         hr = IDirect3DDevice9_BeginScene(device);
1350         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP returned %#08x\n", hr);
1351         if (SUCCEEDED(hr))
1352         {
1353             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
1354             ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
1355             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
1356             ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
1357             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, untransformed_3, sizeof(*untransformed_3));
1358             ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitiveUP failed, hr %#x.\n", hr);
1359             hr = IDirect3DDevice9_EndScene(device);
1360             ok(SUCCEEDED(hr), "IDirect3DDevice9_EndScene failed, hr %#x.\n", hr);
1361         }
1362         color = getPixelColor(device, 10, 10);
1363         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 1),
1364                 "Rangefog with vertex fog returned color 0x%08x\n", color);
1365         color = getPixelColor(device, 630, 10);
1366         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 1),
1367                 "Rangefog with vertex fog returned color 0x%08x\n", color);
1368         color = getPixelColor(device, 10, 470);
1369         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 1),
1370                 "Rangefog with vertex fog returned color 0x%08x\n", color);
1371         color = getPixelColor(device, 630, 470);
1372         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 1),
1373                 "Rangefog with vertex fog returned color 0x%08x\n", color);
1374
1375         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1376         ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed, hr %#x.\n", hr);
1377
1378         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_RANGEFOGENABLE, FALSE);
1379         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
1380     }
1381     else
1382     {
1383         skip("Range fog or table fog not supported, skipping range fog tests\n");
1384     }
1385
1386     /* Turn off the fog master switch to avoid confusing other tests */
1387     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
1388     ok(hr == D3D_OK, "Turning off fog calculations returned %08x\n", hr);
1389     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
1390     ok( hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR returned %08x\n", hr);
1391     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
1392     ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
1393 }
1394
1395 /* This test verifies the behaviour of cube maps wrt. texture wrapping.
1396  * D3D cube map wrapping always behaves like GL_CLAMP_TO_EDGE,
1397  * regardless of the actual addressing mode set. The way this test works is
1398  * that we sample in one of the corners of the cubemap with filtering enabled,
1399  * and check the interpolated color. There are essentially two reasonable
1400  * things an implementation can do: Either pick one of the faces and
1401  * interpolate the edge texel with itself (i.e., clamp within the face), or
1402  * interpolate between the edge texels of the three involved faces. It should
1403  * never involve the border color or the other side (texcoord wrapping) of a
1404  * face in the interpolation. */
1405 static void test_cube_wrap(IDirect3DDevice9 *device)
1406 {
1407     static const float quad[][6] = {
1408         {-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1409         {-1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1410         { 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1411         { 1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1412     };
1413
1414     static const D3DVERTEXELEMENT9 decl_elements[] = {
1415         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1416         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1417         D3DDECL_END()
1418     };
1419
1420     static const struct {
1421         D3DTEXTUREADDRESS mode;
1422         const char *name;
1423     } address_modes[] = {
1424         {D3DTADDRESS_WRAP, "D3DTADDRESS_WRAP"},
1425         {D3DTADDRESS_MIRROR, "D3DTADDRESS_MIRROR"},
1426         {D3DTADDRESS_CLAMP, "D3DTADDRESS_CLAMP"},
1427         {D3DTADDRESS_BORDER, "D3DTADDRESS_BORDER"},
1428         {D3DTADDRESS_MIRRORONCE, "D3DTADDRESS_MIRRORONCE"},
1429     };
1430
1431     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1432     IDirect3DCubeTexture9 *texture = NULL;
1433     IDirect3DSurface9 *surface = NULL;
1434     IDirect3DSurface9 *face_surface;
1435     D3DLOCKED_RECT locked_rect;
1436     HRESULT hr;
1437     UINT x;
1438     INT y, face;
1439
1440     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1441     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1442     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1443     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1444
1445     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
1446             D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL);
1447     ok(SUCCEEDED(hr), "CreateOffscreenPlainSurface failed (0x%08x)\n", hr);
1448
1449     hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
1450             D3DPOOL_DEFAULT, &texture, NULL);
1451     ok(SUCCEEDED(hr), "CreateCubeTexture failed (0x%08x)\n", hr);
1452
1453     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
1454     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1455
1456     for (y = 0; y < 128; ++y)
1457     {
1458         DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1459         for (x = 0; x < 64; ++x)
1460         {
1461             *ptr++ = 0xff0000ff;
1462         }
1463         for (x = 64; x < 128; ++x)
1464         {
1465             *ptr++ = 0xffff0000;
1466         }
1467     }
1468
1469     hr = IDirect3DSurface9_UnlockRect(surface);
1470     ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
1471
1472     hr= IDirect3DCubeTexture9_GetCubeMapSurface(texture, 0, 0, &face_surface);
1473     ok(SUCCEEDED(hr), "GetCubeMapSurface failed (0x%08x)\n", hr);
1474
1475     hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, face_surface, NULL);
1476     ok(SUCCEEDED(hr), "UpdateSurface failed (0x%08x)\n", hr);
1477
1478     IDirect3DSurface9_Release(face_surface);
1479
1480     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
1481     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1482
1483     for (y = 0; y < 128; ++y)
1484     {
1485         DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1486         for (x = 0; x < 64; ++x)
1487         {
1488             *ptr++ = 0xffff0000;
1489         }
1490         for (x = 64; x < 128; ++x)
1491         {
1492             *ptr++ = 0xff0000ff;
1493         }
1494     }
1495
1496     hr = IDirect3DSurface9_UnlockRect(surface);
1497     ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
1498
1499     /* Create cube faces */
1500     for (face = 1; face < 6; ++face)
1501     {
1502         hr= IDirect3DCubeTexture9_GetCubeMapSurface(texture, face, 0, &face_surface);
1503         ok(SUCCEEDED(hr), "GetCubeMapSurface failed (0x%08x)\n", hr);
1504
1505         hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, face_surface, NULL);
1506         ok(SUCCEEDED(hr), "UpdateSurface failed (0x%08x)\n", hr);
1507
1508         IDirect3DSurface9_Release(face_surface);
1509     }
1510
1511     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
1512     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1513
1514     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
1515     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1516     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
1517     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1518     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_BORDERCOLOR, 0xff00ff00);
1519     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_BORDERCOLOR failed (0x%08x)\n", hr);
1520
1521     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1522     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1523
1524     for (x = 0; x < (sizeof(address_modes) / sizeof(*address_modes)); ++x)
1525     {
1526         DWORD color;
1527
1528         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, address_modes[x].mode);
1529         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU (%s) failed (0x%08x)\n", address_modes[x].name, hr);
1530         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, address_modes[x].mode);
1531         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV (%s) failed (0x%08x)\n", address_modes[x].name, hr);
1532
1533         hr = IDirect3DDevice9_BeginScene(device);
1534         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1535
1536         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1537         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
1538
1539         hr = IDirect3DDevice9_EndScene(device);
1540         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1541
1542         color = getPixelColor(device, 320, 240);
1543         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xff), 1),
1544                 "Got color 0x%08x for addressing mode %s, expected 0x000000ff.\n",
1545                 color, address_modes[x].name);
1546
1547         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1548         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1549
1550         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
1551         ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
1552     }
1553
1554     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1555     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1556
1557     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1558     IDirect3DCubeTexture9_Release(texture);
1559     IDirect3DSurface9_Release(surface);
1560 }
1561
1562 static void offscreen_test(IDirect3DDevice9 *device)
1563 {
1564     HRESULT hr;
1565     IDirect3DTexture9 *offscreenTexture = NULL;
1566     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
1567     DWORD color;
1568
1569     static const float quad[][5] = {
1570         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
1571         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
1572         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
1573         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
1574     };
1575
1576     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
1577     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
1578
1579     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
1580     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %08x\n", hr);
1581     if(!offscreenTexture) {
1582         trace("Failed to create an X8R8G8B8 offscreen texture, trying R5G6B5\n");
1583         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
1584         ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %08x\n", hr);
1585         if(!offscreenTexture) {
1586             skip("Cannot create an offscreen render target\n");
1587             goto out;
1588         }
1589     }
1590
1591     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1592     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
1593     if(!backbuffer) {
1594         goto out;
1595     }
1596
1597     hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
1598     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %08x\n", hr);
1599     if(!offscreen) {
1600         goto out;
1601     }
1602
1603     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
1604     ok(hr == D3D_OK, "SetFVF failed, hr = %08x\n", hr);
1605
1606     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
1607     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
1608     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
1609     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
1610     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
1611     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1612     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
1613     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1614     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1615     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
1616
1617     if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
1618         hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
1619         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
1620         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1621         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
1622
1623         /* Draw without textures - Should result in a white quad */
1624         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
1625         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %08x\n", hr);
1626
1627         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
1628         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
1629         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
1630         ok(hr == D3D_OK, "SetTexture failed, %08x\n", hr);
1631
1632         /* This time with the texture */
1633         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
1634         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %08x\n", hr);
1635
1636         IDirect3DDevice9_EndScene(device);
1637     }
1638
1639     /* Center quad - should be white */
1640     color = getPixelColor(device, 320, 240);
1641     ok(color == 0x00ffffff, "Offscreen failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1642     /* Some quad in the cleared part of the texture */
1643     color = getPixelColor(device, 170, 240);
1644     ok(color == 0x00ff00ff, "Offscreen failed: Got color 0x%08x, expected 0x00ff00ff.\n", color);
1645     /* Part of the originally cleared back buffer */
1646     color = getPixelColor(device, 10, 10);
1647     ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1648     if(0) {
1649         /* Lower left corner of the screen, where back buffer offscreen rendering draws the offscreen texture.
1650          * It should be red, but the offscreen texture may leave some junk there. Not tested yet. Depending on
1651          * the offscreen rendering mode this test would succeed or fail
1652          */
1653         color = getPixelColor(device, 10, 470);
1654         ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1655     }
1656
1657     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1658
1659 out:
1660     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1661     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture returned %#x.\n", hr);
1662
1663     /* restore things */
1664     if(backbuffer) {
1665         IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
1666         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderTarget returned %#x.\n", hr);
1667         IDirect3DSurface9_Release(backbuffer);
1668     }
1669     if(offscreenTexture) {
1670         IDirect3DTexture9_Release(offscreenTexture);
1671     }
1672     if(offscreen) {
1673         IDirect3DSurface9_Release(offscreen);
1674     }
1675 }
1676
1677 /* This test tests fog in combination with shaders.
1678  * What's tested: linear fog (vertex and table) with pixel shader
1679  *                linear table fog with non foggy vertex shader
1680  *                vertex fog with foggy vertex shader, non-linear
1681  *                fog with shader, non-linear fog with foggy shader,
1682  *                linear table fog with foggy shader
1683  */
1684 static void fog_with_shader_test(IDirect3DDevice9 *device)
1685 {
1686     HRESULT hr;
1687     DWORD color;
1688     union {
1689         float f;
1690         DWORD i;
1691     } start, end;
1692     unsigned int i, j;
1693
1694     /* basic vertex shader without fog computation ("non foggy") */
1695     static const DWORD vertex_shader_code1[] = {
1696         0xfffe0101,                                                             /* vs_1_1                       */
1697         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
1698         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                */
1699         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
1700         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                  */
1701         0x0000ffff
1702     };
1703     /* basic vertex shader with reversed fog computation ("foggy") */
1704     static const DWORD vertex_shader_code2[] = {
1705         0xfffe0101,                                                             /* vs_1_1                        */
1706         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0               */
1707         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                 */
1708         0x00000051, 0xa00f0000, 0xbfa00000, 0x00000000, 0xbf666666, 0x00000000, /* def c0, -1.25, 0.0, -0.9, 0.0 */
1709         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                  */
1710         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                   */
1711         0x00000002, 0x800f0000, 0x90aa0000, 0xa0aa0000,                         /* add r0, v0.z, c0.z            */
1712         0x00000005, 0xc00f0001, 0x80000000, 0xa0000000,                         /* mul oFog, r0.x, c0.x          */
1713         0x0000ffff
1714     };
1715     /* basic pixel shader */
1716     static const DWORD pixel_shader_code[] = {
1717         0xffff0101,                                                             /* ps_1_1     */
1718         0x00000001, 0x800f0000, 0x90e40000,                                     /* mov r0, vo */
1719         0x0000ffff
1720     };
1721
1722     static struct vertex quad[] = {
1723         {-1.0f, -1.0f,  0.0f,          0xFFFF0000  },
1724         {-1.0f,  1.0f,  0.0f,          0xFFFF0000  },
1725         { 1.0f, -1.0f,  0.0f,          0xFFFF0000  },
1726         { 1.0f,  1.0f,  0.0f,          0xFFFF0000  },
1727     };
1728
1729     static const D3DVERTEXELEMENT9 decl_elements[] = {
1730         {0,  0, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1731         {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
1732         D3DDECL_END()
1733     };
1734
1735     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1736     IDirect3DVertexShader9      *vertex_shader[3]   = {NULL, NULL, NULL};
1737     IDirect3DPixelShader9       *pixel_shader[2]    = {NULL, NULL};
1738
1739     /* This reference data was collected on a nVidia GeForce 7600GS driver version 84.19 DirectX version 9.0c on Windows XP */
1740     static const struct test_data_t {
1741         int vshader;
1742         int pshader;
1743         D3DFOGMODE vfog;
1744         D3DFOGMODE tfog;
1745         unsigned int color[11];
1746     } test_data[] = {
1747         /* only pixel shader: */
1748         {0, 1, D3DFOG_NONE, D3DFOG_LINEAR,
1749         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1750         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1751         {0, 1, D3DFOG_EXP, D3DFOG_LINEAR,
1752         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1753         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1754         {0, 1, D3DFOG_EXP2, D3DFOG_LINEAR,
1755         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1756         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1757         {0, 1, D3DFOG_LINEAR, D3DFOG_NONE,
1758         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1759         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1760         {0, 1, D3DFOG_LINEAR, D3DFOG_LINEAR,
1761         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1762         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1763
1764         /* vertex shader */
1765         {1, 0, D3DFOG_NONE, D3DFOG_NONE,
1766         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1767          0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1768         {1, 0, D3DFOG_NONE, D3DFOG_LINEAR,
1769         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1770         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1771         {1, 0, D3DFOG_EXP, D3DFOG_LINEAR,
1772         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1773         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1774
1775         {1, 0, D3DFOG_EXP2, D3DFOG_LINEAR,
1776         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1777         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1778         {1, 0, D3DFOG_LINEAR, D3DFOG_LINEAR,
1779         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1780         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1781
1782         /* vertex shader and pixel shader */
1783         /* The next 4 tests would read the fog coord output, but it isn't available.
1784          * The result is a fully fogged quad, no matter what the Z coord is. This is on
1785          * a geforce 7400, 97.52 driver, Windows Vista, but probably hardware dependent.
1786          * These tests should be disabled if some other hardware behaves differently
1787          */
1788         {1, 1, D3DFOG_NONE, D3DFOG_NONE,
1789         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1790         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1791         {1, 1, D3DFOG_LINEAR, D3DFOG_NONE,
1792         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1793         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1794         {1, 1, D3DFOG_EXP, D3DFOG_NONE,
1795         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1796         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1797         {1, 1, D3DFOG_EXP2, D3DFOG_NONE,
1798         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1799         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1800
1801         /* These use the Z coordinate with linear table fog */
1802         {1, 1, D3DFOG_NONE, D3DFOG_LINEAR,
1803         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1804         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1805         {1, 1, D3DFOG_EXP, D3DFOG_LINEAR,
1806         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1807         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1808         {1, 1, D3DFOG_EXP2, D3DFOG_LINEAR,
1809         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1810         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1811         {1, 1, D3DFOG_LINEAR, D3DFOG_LINEAR,
1812         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1813         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1814
1815         /* Non-linear table fog without fog coord */
1816         {1, 1, D3DFOG_NONE, D3DFOG_EXP,
1817         {0x00ff0000, 0x00e71800, 0x00d12e00, 0x00bd4200, 0x00ab5400, 0x009b6400,
1818         0x008d7200, 0x007f8000, 0x00738c00, 0x00689700, 0x005ea100}},
1819         {1, 1, D3DFOG_NONE, D3DFOG_EXP2,
1820         {0x00fd0200, 0x00f50200, 0x00f50a00, 0x00e91600, 0x00d92600, 0x00c73800,
1821         0x00b24d00, 0x009c6300, 0x00867900, 0x00728d00, 0x005ea100}},
1822
1823 #if 0  /* FIXME: these fail on GeForce 8500 */
1824         /* foggy vertex shader */
1825         {2, 0, D3DFOG_NONE, D3DFOG_NONE,
1826         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1827          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1828         {2, 0, D3DFOG_EXP, D3DFOG_NONE,
1829         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1830          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1831         {2, 0, D3DFOG_EXP2, D3DFOG_NONE,
1832         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1833          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1834         {2, 0, D3DFOG_LINEAR, D3DFOG_NONE,
1835         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1836          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1837 #endif
1838
1839         /* foggy vertex shader and pixel shader. First 4 tests with vertex fog,
1840          * all using the fixed fog-coord linear fog
1841          */
1842         {2, 1, D3DFOG_NONE, D3DFOG_NONE,
1843         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1844          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1845         {2, 1, D3DFOG_EXP, D3DFOG_NONE,
1846         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1847          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1848         {2, 1, D3DFOG_EXP2, D3DFOG_NONE,
1849         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1850          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1851         {2, 1, D3DFOG_LINEAR, D3DFOG_NONE,
1852         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1853          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1854
1855         /* These use table fog. Here the shader-provided fog coordinate is
1856          * ignored and the z coordinate used instead
1857          */
1858         {2, 1, D3DFOG_NONE, D3DFOG_EXP,
1859         {0x00ff0000, 0x00e71800, 0x00d12e00, 0x00bd4200, 0x00ab5400, 0x009b6400,
1860         0x008d7200, 0x007f8000, 0x00738c00, 0x00689700, 0x005ea100}},
1861         {2, 1, D3DFOG_NONE, D3DFOG_EXP2,
1862         {0x00fd0200, 0x00f50200, 0x00f50a00, 0x00e91600, 0x00d92600, 0x00c73800,
1863         0x00b24d00, 0x009c6300, 0x00867900, 0x00728d00, 0x005ea100}},
1864         {2, 1, D3DFOG_NONE, D3DFOG_LINEAR,
1865         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1866         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1867     };
1868
1869     /* NOTE: changing these values will not affect the tests with foggy vertex shader, as the values are hardcoded in the shader*/
1870     start.f=0.1f;
1871     end.f=0.9f;
1872
1873     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code1, &vertex_shader[1]);
1874     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1875     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code2, &vertex_shader[2]);
1876     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1877     hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader[1]);
1878     ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1879     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1880     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
1881
1882     /* Setup initial states: No lighting, fog on, fog color */
1883     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1884     ok(hr == D3D_OK, "Turning off lighting failed (%08x)\n", hr);
1885     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
1886     ok(hr == D3D_OK, "Turning on fog calculations failed (%08x)\n", hr);
1887     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
1888     ok(hr == D3D_OK, "Setting fog color failed (%08x)\n", hr);
1889     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1890     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1891
1892     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
1893     ok(hr == D3D_OK, "Turning off table fog failed (%08x)\n", hr);
1894     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
1895     ok(hr == D3D_OK, "Turning off vertex fog failed (%08x)\n", hr);
1896
1897     /* Use fogtart = 0.1 and end = 0.9 to test behavior outside the fog transition phase, too*/
1898     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, start.i);
1899     ok(hr == D3D_OK, "Setting fog start failed (%08x)\n", hr);
1900     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, end.i);
1901     ok(hr == D3D_OK, "Setting fog end failed (%08x)\n", hr);
1902
1903     for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++)
1904     {
1905         hr = IDirect3DDevice9_SetVertexShader(device, vertex_shader[test_data[i].vshader]);
1906         ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1907         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader[test_data[i].pshader]);
1908         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1909         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, test_data[i].vfog);
1910         ok( hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1911         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, test_data[i].tfog);
1912         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1913
1914         for(j=0; j < 11; j++)
1915         {
1916             /* Don't use the whole zrange to prevent rounding errors */
1917             quad[0].z = 0.001f + (float)j / 10.02f;
1918             quad[1].z = 0.001f + (float)j / 10.02f;
1919             quad[2].z = 0.001f + (float)j / 10.02f;
1920             quad[3].z = 0.001f + (float)j / 10.02f;
1921
1922             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1923             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
1924
1925             hr = IDirect3DDevice9_BeginScene(device);
1926             ok( hr == D3D_OK, "BeginScene returned failed (%08x)\n", hr);
1927
1928             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1929             ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1930
1931             hr = IDirect3DDevice9_EndScene(device);
1932             ok(hr == D3D_OK, "EndScene failed (%08x)\n", hr);
1933
1934             /* As the red and green component are the result of blending use 5% tolerance on the expected value */
1935             color = getPixelColor(device, 128, 240);
1936             ok(color_match(color, test_data[i].color[j], 13),
1937                 "fog vs%i ps%i fvm%i ftm%i %d: got color %08x, expected %08x +-5%%\n",
1938                 test_data[i].vshader, test_data[i].pshader, test_data[i].vfog, test_data[i].tfog, j, color, test_data[i].color[j]);
1939
1940             IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1941         }
1942     }
1943
1944     /* reset states */
1945     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
1946     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1947     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1948     ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1949     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1950     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1951     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
1952     ok(hr == D3D_OK, "Turning off fog calculations failed (%08x)\n", hr);
1953
1954     IDirect3DVertexShader9_Release(vertex_shader[1]);
1955     IDirect3DVertexShader9_Release(vertex_shader[2]);
1956     IDirect3DPixelShader9_Release(pixel_shader[1]);
1957     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1958 }
1959
1960 static void generate_bumpmap_textures(IDirect3DDevice9 *device) {
1961     unsigned int i, x, y;
1962     HRESULT hr;
1963     IDirect3DTexture9 *texture[2] = {NULL, NULL};
1964     D3DLOCKED_RECT locked_rect;
1965
1966     /* Generate the textures */
1967     for(i=0; i<2; i++)
1968     {
1969         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, i?D3DFMT_A8R8G8B8:D3DFMT_V8U8,
1970                                             D3DPOOL_MANAGED, &texture[i], NULL);
1971         ok(SUCCEEDED(hr), "CreateTexture failed (0x%08x)\n", hr);
1972
1973         hr = IDirect3DTexture9_LockRect(texture[i], 0, &locked_rect, NULL, 0);
1974         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1975         for (y = 0; y < 128; ++y)
1976         {
1977             if(i)
1978             { /* Set up black texture with 2x2 texel white spot in the middle */
1979                 DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1980                 for (x = 0; x < 128; ++x)
1981                 {
1982                     if(y>62 && y<66 && x>62 && x<66)
1983                         *ptr++ = 0xffffffff;
1984                     else
1985                         *ptr++ = 0xff000000;
1986                 }
1987             }
1988             else
1989             { /* Set up a displacement map which points away from the center parallel to the closest axis.
1990                * (if multiplied with bumpenvmat)
1991               */
1992                 WORD *ptr = (WORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1993                 for (x = 0; x < 128; ++x)
1994                 {
1995                     if(abs(x-64)>abs(y-64))
1996                     {
1997                         if(x < 64)
1998                             *ptr++ = 0xc000;
1999                         else
2000                             *ptr++ = 0x4000;
2001                     }
2002                     else
2003                     {
2004                         if(y < 64)
2005                             *ptr++ = 0x0040;
2006                         else
2007                             *ptr++ = 0x00c0;
2008                     }
2009                 }
2010             }
2011         }
2012         hr = IDirect3DTexture9_UnlockRect(texture[i], 0);
2013         ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
2014
2015         hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture[i]);
2016         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
2017
2018         /* Disable texture filtering */
2019         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MINFILTER, D3DTEXF_POINT);
2020         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
2021         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
2022         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
2023
2024         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
2025         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU failed (0x%08x)\n", hr);
2026         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
2027         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV failed (0x%08x)\n", hr);
2028     }
2029 }
2030
2031 /* test the behavior of the texbem instruction
2032  * with normal 2D and projective 2D textures
2033  */
2034 static void texbem_test(IDirect3DDevice9 *device)
2035 {
2036     HRESULT hr;
2037     DWORD color;
2038     int i;
2039
2040     static const DWORD pixel_shader_code[] = {
2041         0xffff0101,                         /* ps_1_1*/
2042         0x00000042, 0xb00f0000,             /* tex t0*/
2043         0x00000043, 0xb00f0001, 0xb0e40000, /* texbem t1, t0*/
2044         0x00000001, 0x800f0000, 0xb0e40001, /* mov r0, t1*/
2045         0x0000ffff
2046     };
2047     static const DWORD double_texbem_code[] =  {
2048         0xffff0103,                                         /* ps_1_3           */
2049         0x00000042, 0xb00f0000,                             /* tex t0           */
2050         0x00000043, 0xb00f0001, 0xb0e40000,                 /* texbem t1, t0    */
2051         0x00000042, 0xb00f0002,                             /* tex t2           */
2052         0x00000043, 0xb00f0003, 0xb0e40002,                 /* texbem t3, t2    */
2053         0x00000002, 0x800f0000, 0xb0e40001, 0xb0e40003,     /* add r0, t1, t3   */
2054         0x0000ffff                                          /* end              */
2055     };
2056
2057
2058     static const float quad[][7] = {
2059         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f},
2060         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f},
2061         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 1.0f, 0.0f},
2062         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 1.0f, 1.0f},
2063     };
2064     static const float quad_proj[][9] = {
2065         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f,   0.0f,   0.0f, 0.0f, 128.0f},
2066         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f,   0.0f, 128.0f, 0.0f, 128.0f},
2067         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 128.0f,   0.0f, 0.0f, 128.0f},
2068         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 128.0f, 128.0f, 0.0f, 128.0f},
2069     };
2070
2071     static const D3DVERTEXELEMENT9 decl_elements[][4] = { {
2072         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2073         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
2074         {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
2075         D3DDECL_END()
2076     },{
2077         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2078         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
2079         {0, 20, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
2080         D3DDECL_END()
2081     } };
2082
2083     /* use asymmetric matrix to test loading */
2084     float bumpenvmat[4] = {0.0,0.5,-0.5,0.0};
2085
2086     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
2087     IDirect3DPixelShader9       *pixel_shader       = NULL;
2088     IDirect3DTexture9           *texture            = NULL, *texture1, *texture2;
2089     D3DLOCKED_RECT locked_rect;
2090
2091     generate_bumpmap_textures(device);
2092
2093     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
2094     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
2095     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
2096     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
2097     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
2098
2099     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
2100     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
2101
2102     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
2103     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
2104
2105     for(i=0; i<2; i++)
2106     {
2107         if(i)
2108         {
2109             hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4|D3DTTFF_PROJECTED);
2110             ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
2111         }
2112
2113         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements[i], &vertex_declaration);
2114         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
2115         hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
2116         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
2117
2118         hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader);
2119         ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
2120         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader);
2121         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
2122
2123         hr = IDirect3DDevice9_BeginScene(device);
2124         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
2125
2126         if(!i)
2127             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
2128         else
2129             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad_proj[0], sizeof(quad_proj[0]));
2130         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
2131
2132         hr = IDirect3DDevice9_EndScene(device);
2133         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
2134
2135         color = getPixelColor(device, 320-32, 240);
2136         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2137         color = getPixelColor(device, 320+32, 240);
2138         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2139         color = getPixelColor(device, 320, 240-32);
2140         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2141         color = getPixelColor(device, 320, 240+32);
2142         ok(color_match(color, 0x00ffffff, 4), "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2143
2144         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2145         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2146
2147         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
2148         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
2149         IDirect3DPixelShader9_Release(pixel_shader);
2150
2151         hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2152         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
2153         IDirect3DVertexDeclaration9_Release(vertex_declaration);
2154     }
2155
2156     /* clean up */
2157     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
2158     ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
2159
2160     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
2161     ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
2162
2163     for(i=0; i<2; i++)
2164     {
2165         hr = IDirect3DDevice9_GetTexture(device, i, (IDirect3DBaseTexture9 **) &texture);
2166         ok(SUCCEEDED(hr), "IDirect3DDevice9_GetTexture failed (0x%08x)\n", hr);
2167         IDirect3DTexture9_Release(texture); /* For the GetTexture */
2168         hr = IDirect3DDevice9_SetTexture(device, i, NULL);
2169         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
2170         IDirect3DTexture9_Release(texture);
2171     }
2172
2173     /* Test double texbem */
2174     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_V8U8, D3DPOOL_MANAGED, &texture, NULL);
2175     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed (0x%08x)\n", hr);
2176     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_V8U8, D3DPOOL_MANAGED, &texture1, NULL);
2177     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed (0x%08x)\n", hr);
2178     hr = IDirect3DDevice9_CreateTexture(device, 8, 8, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture2, NULL);
2179     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed (0x%08x)\n", hr);
2180     hr = IDirect3DDevice9_CreatePixelShader(device, double_texbem_code, &pixel_shader);
2181     ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
2182
2183     hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
2184     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
2185     ((signed char *) locked_rect.pBits)[0] = (-1.0 / 8.0) * 127;
2186     ((signed char *) locked_rect.pBits)[1] = ( 1.0 / 8.0) * 127;
2187
2188     hr = IDirect3DTexture9_UnlockRect(texture, 0);
2189     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
2190
2191     hr = IDirect3DTexture9_LockRect(texture1, 0, &locked_rect, NULL, 0);
2192     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
2193     ((signed char *) locked_rect.pBits)[0] = (-2.0 / 8.0) * 127;
2194     ((signed char *) locked_rect.pBits)[1] = (-4.0 / 8.0) * 127;
2195     hr = IDirect3DTexture9_UnlockRect(texture1, 0);
2196     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
2197
2198     {
2199         /* Some data without any meaning, just to have an 8x8 array to see which element is picked */
2200 #define tex  0x00ff0000
2201 #define tex1 0x0000ff00
2202 #define origin 0x000000ff
2203         static const DWORD pixel_data[] = {
2204             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
2205             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
2206             0x000000ff, tex1      , 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
2207             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
2208             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, origin,     0x000000ff, tex       , 0x000000ff,
2209             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
2210             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
2211             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
2212         };
2213 #undef tex1
2214 #undef tex2
2215 #undef origin
2216
2217         hr = IDirect3DTexture9_LockRect(texture2, 0, &locked_rect, NULL, 0);
2218         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
2219         for(i = 0; i < 8; i++) {
2220             memcpy(((char *) locked_rect.pBits) + i * locked_rect.Pitch, pixel_data + 8 * i, 8 * sizeof(DWORD));
2221         }
2222         hr = IDirect3DTexture9_UnlockRect(texture2, 0);
2223         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
2224     }
2225
2226     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
2227     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2228     hr = IDirect3DDevice9_SetTexture(device, 1, (IDirect3DBaseTexture9 *) texture2);
2229     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2230     hr = IDirect3DDevice9_SetTexture(device, 2, (IDirect3DBaseTexture9 *) texture1);
2231     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2232     hr = IDirect3DDevice9_SetTexture(device, 3, (IDirect3DBaseTexture9 *) texture2);
2233     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2234     hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader);
2235     ok(SUCCEEDED(hr), "Direct3DDevice9_SetPixelShader failed (0x%08x)\n", hr);
2236     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX4);
2237     ok(SUCCEEDED(hr), "Direct3DDevice9_SetPixelShader failed (0x%08x)\n", hr);
2238
2239     bumpenvmat[0] =-1.0;  bumpenvmat[2] =  2.0;
2240     bumpenvmat[1] = 0.0;  bumpenvmat[3] =  0.0;
2241     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
2242     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2243     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
2244     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2245     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
2246     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2247     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
2248     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2249
2250     bumpenvmat[0] = 1.5; bumpenvmat[2] =  0.0;
2251     bumpenvmat[1] = 0.0; bumpenvmat[3] =  0.5;
2252     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
2253     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2254     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
2255     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2256     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
2257     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2258     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
2259     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState returned %#x.\n", hr);
2260
2261     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
2262     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2263     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
2264     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2265     hr = IDirect3DDevice9_SetSamplerState(device, 1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
2266     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2267     hr = IDirect3DDevice9_SetSamplerState(device, 1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
2268     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2269     hr = IDirect3DDevice9_SetSamplerState(device, 2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
2270     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2271     hr = IDirect3DDevice9_SetSamplerState(device, 2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
2272     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2273     hr = IDirect3DDevice9_SetSamplerState(device, 3, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
2274     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2275     hr = IDirect3DDevice9_SetSamplerState(device, 3, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
2276     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetSamplerState returned %#x.\n", hr);
2277
2278     hr = IDirect3DDevice9_BeginScene(device);
2279     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
2280     if(SUCCEEDED(hr)) {
2281         static const float double_quad[] = {
2282             -1.0,   -1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
2283              1.0,   -1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
2284             -1.0,    1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
2285              1.0,    1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
2286         };
2287
2288         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, double_quad, sizeof(float) * 11);
2289         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
2290         hr = IDirect3DDevice9_EndScene(device);
2291         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
2292     }
2293     color = getPixelColor(device, 320, 240);
2294     ok(color == 0x00ffff00, "double texbem failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
2295
2296     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
2297     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2298     hr = IDirect3DDevice9_SetTexture(device, 1, NULL);
2299     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2300     hr = IDirect3DDevice9_SetTexture(device, 2, NULL);
2301     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2302     hr = IDirect3DDevice9_SetTexture(device, 3, NULL);
2303     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
2304     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
2305     ok(SUCCEEDED(hr), "Direct3DDevice9_SetPixelShader failed (0x%08x)\n", hr);
2306
2307     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2308     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2309
2310     IDirect3DPixelShader9_Release(pixel_shader);
2311     IDirect3DTexture9_Release(texture);
2312     IDirect3DTexture9_Release(texture1);
2313     IDirect3DTexture9_Release(texture2);
2314 }
2315
2316 static void z_range_test(IDirect3DDevice9 *device)
2317 {
2318     const struct vertex quad[] =
2319     {
2320         {-1.0f,  0.0f,   1.1f,                          0xffff0000},
2321         {-1.0f,  1.0f,   1.1f,                          0xffff0000},
2322         { 1.0f,  0.0f,  -1.1f,                          0xffff0000},
2323         { 1.0f,  1.0f,  -1.1f,                          0xffff0000},
2324     };
2325     const struct vertex quad2[] =
2326     {
2327         {-1.0f,  0.0f,   1.1f,                          0xff0000ff},
2328         {-1.0f,  1.0f,   1.1f,                          0xff0000ff},
2329         { 1.0f,  0.0f,  -1.1f,                          0xff0000ff},
2330         { 1.0f,  1.0f,  -1.1f,                          0xff0000ff},
2331     };
2332
2333     const struct tvertex quad3[] =
2334     {
2335         {    0,   240,   1.1f,  1.0,                    0xffffff00},
2336         {    0,   480,   1.1f,  1.0,                    0xffffff00},
2337         {  640,   240,  -1.1f,  1.0,                    0xffffff00},
2338         {  640,   480,  -1.1f,  1.0,                    0xffffff00},
2339     };
2340     const struct tvertex quad4[] =
2341     {
2342         {    0,   240,   1.1f,  1.0,                    0xff00ff00},
2343         {    0,   480,   1.1f,  1.0,                    0xff00ff00},
2344         {  640,   240,  -1.1f,  1.0,                    0xff00ff00},
2345         {  640,   480,  -1.1f,  1.0,                    0xff00ff00},
2346     };
2347     HRESULT hr;
2348     DWORD color;
2349     IDirect3DVertexShader9 *shader;
2350     IDirect3DVertexDeclaration9 *decl;
2351     D3DCAPS9 caps;
2352     const DWORD shader_code[] = {
2353         0xfffe0101,                                     /* vs_1_1           */
2354         0x0000001f, 0x80000000, 0x900f0000,             /* dcl_position v0  */
2355         0x00000001, 0xc00f0000, 0x90e40000,             /* mov oPos, v0     */
2356         0x00000001, 0xd00f0000, 0xa0e40000,             /* mov oD0, c0      */
2357         0x0000ffff                                      /* end              */
2358     };
2359     static const D3DVERTEXELEMENT9 decl_elements[] = {
2360         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2361         D3DDECL_END()
2362     };
2363
2364     IDirect3DDevice9_GetDeviceCaps(device, &caps);
2365
2366     /* Does the Present clear the depth stencil? Clear the depth buffer with some value != 0,
2367      * then call Present. Then clear the color buffer to make sure it has some defined content
2368      * after the Present with D3DSWAPEFFECT_DISCARD. After that draw a plane that is somewhere cut
2369      * by the depth value.
2370      */
2371     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.75, 0);
2372     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
2373     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2374     ok(SUCCEEDED(hr), "IDirect3DDevice9_Present returned %#x.\n", hr);
2375     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4, 0);
2376     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
2377
2378     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, TRUE);
2379     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2380     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
2381     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2382     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
2383     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2384     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
2385     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2386     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
2387     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
2388
2389     hr = IDirect3DDevice9_BeginScene(device);
2390     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2391     if(hr == D3D_OK)
2392     {
2393         /* Test the untransformed vertex path */
2394         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
2395         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2396         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS);
2397         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2398         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad2, sizeof(quad2[0]));
2399         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2400
2401         /* Test the transformed vertex path */
2402         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2403         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
2404
2405         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad4, sizeof(quad4[0]));
2406         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2407         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
2408         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2409         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad3, sizeof(quad3[0]));
2410         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2411
2412         hr = IDirect3DDevice9_EndScene(device);
2413         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2414     }
2415
2416     /* Do not test the exact corner pixels, but go pretty close to them */
2417
2418     /* Clipped because z > 1.0 */
2419     color = getPixelColor(device, 28, 238);
2420     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2421     color = getPixelColor(device, 28, 241);
2422     if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_CLIPTLVERTS)
2423     {
2424         ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2425     }
2426     else
2427     {
2428         ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
2429     }
2430
2431     /* Not clipped, > z buffer clear value(0.75) */
2432     color = getPixelColor(device, 31, 238);
2433     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2434     color = getPixelColor(device, 31, 241);
2435     ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
2436     color = getPixelColor(device, 100, 238);
2437     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2438     color = getPixelColor(device, 100, 241);
2439     ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
2440
2441     /* Not clipped, < z buffer clear value */
2442     color = getPixelColor(device, 104, 238);
2443     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2444     color = getPixelColor(device, 104, 241);
2445     ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color);
2446     color = getPixelColor(device, 318, 238);
2447     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2448     color = getPixelColor(device, 318, 241);
2449     ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color);
2450
2451     /* Clipped because z < 0.0 */
2452     color = getPixelColor(device, 321, 238);
2453     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2454     color = getPixelColor(device, 321, 241);
2455     if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_CLIPTLVERTS)
2456     {
2457         ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2458     }
2459     else
2460     {
2461         ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2462     }
2463
2464     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2465     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2466
2467     /* Test the shader path */
2468     if (caps.VertexShaderVersion < D3DVS_VERSION(1, 1)) {
2469         skip("Vertex shaders not supported\n");
2470         goto out;
2471     }
2472     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
2473     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
2474     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
2475     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
2476
2477     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4, 0);
2478
2479     IDirect3DDevice9_SetVertexDeclaration(device, decl);
2480     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
2481     IDirect3DDevice9_SetVertexShader(device, shader);
2482     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
2483
2484     hr = IDirect3DDevice9_BeginScene(device);
2485     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2486     if(hr == D3D_OK)
2487     {
2488         float colorf[] = {1.0, 0.0, 0.0, 1.0};
2489         float colorf2[] = {0.0, 0.0, 1.0, 1.0};
2490         IDirect3DDevice9_SetVertexShaderConstantF(device, 0, colorf, 1);
2491         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
2492         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2493         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS);
2494         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2495         IDirect3DDevice9_SetVertexShaderConstantF(device, 0, colorf2, 1);
2496         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad2, sizeof(quad2[0]));
2497         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %08x\n", hr);
2498
2499         hr = IDirect3DDevice9_EndScene(device);
2500         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2501     }
2502
2503     IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2504     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
2505     IDirect3DDevice9_SetVertexShader(device, NULL);
2506     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
2507
2508     IDirect3DVertexDeclaration9_Release(decl);
2509     IDirect3DVertexShader9_Release(shader);
2510
2511     /* Z < 1.0 */
2512     color = getPixelColor(device, 28, 238);
2513     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2514
2515     /* 1.0 < z < 0.75 */
2516     color = getPixelColor(device, 31, 238);
2517     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2518     color = getPixelColor(device, 100, 238);
2519     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2520
2521     /* 0.75 < z < 0.0 */
2522     color = getPixelColor(device, 104, 238);
2523     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2524     color = getPixelColor(device, 318, 238);
2525     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2526
2527     /* 0.0 < z */
2528     color = getPixelColor(device, 321, 238);
2529     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2530
2531     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2532     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2533
2534     out:
2535     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
2536     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2537     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
2538     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2539     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
2540     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
2541 }
2542
2543 static void fill_surface(IDirect3DSurface9 *surface, DWORD color)
2544 {
2545     D3DSURFACE_DESC desc;
2546     D3DLOCKED_RECT l;
2547     HRESULT hr;
2548     unsigned int x, y;
2549     DWORD *mem;
2550
2551     memset(&desc, 0, sizeof(desc));
2552     memset(&l, 0, sizeof(l));
2553     hr = IDirect3DSurface9_GetDesc(surface, &desc);
2554     ok(hr == D3D_OK, "IDirect3DSurface9_GetDesc failed with %08x\n", hr);
2555     hr = IDirect3DSurface9_LockRect(surface, &l, NULL, 0);
2556     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed with %08x\n", hr);
2557     if(FAILED(hr)) return;
2558
2559     for(y = 0; y < desc.Height; y++)
2560     {
2561         mem = (DWORD *) ((BYTE *) l.pBits + y * l.Pitch);
2562         for(x = 0; x < l.Pitch / sizeof(DWORD); x++)
2563         {
2564             mem[x] = color;
2565         }
2566     }
2567     hr = IDirect3DSurface9_UnlockRect(surface);
2568     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed with %08x\n", hr);
2569 }
2570
2571 /* This tests a variety of possible StretchRect() situations */
2572 static void stretchrect_test(IDirect3DDevice9 *device)
2573 {
2574     HRESULT hr;
2575     IDirect3DTexture9 *tex_rt32 = NULL, *tex_rt64 = NULL, *tex_rt_dest64 = NULL, *tex_rt_dest640_480 = NULL;
2576     IDirect3DSurface9 *surf_tex_rt32 = NULL, *surf_tex_rt64 = NULL, *surf_tex_rt_dest64 = NULL, *surf_tex_rt_dest640_480 = NULL;
2577     IDirect3DTexture9 *tex32 = NULL, *tex64 = NULL, *tex_dest64 = NULL;
2578     IDirect3DSurface9 *surf_tex32 = NULL, *surf_tex64 = NULL, *surf_tex_dest64 = NULL;
2579     IDirect3DSurface9 *surf_rt32 = NULL, *surf_rt64 = NULL, *surf_rt_dest64 = NULL;
2580     IDirect3DSurface9 *surf_offscreen32 = NULL, *surf_offscreen64 = NULL, *surf_offscreen_dest64 = NULL;
2581     IDirect3DSurface9 *surf_temp32 = NULL, *surf_temp64 = NULL;
2582     IDirect3DSurface9 *orig_rt = NULL;
2583     IDirect3DSurface9 *backbuffer = NULL;
2584     DWORD color;
2585
2586     RECT src_rect64 = {0, 0, 64, 64};
2587     RECT src_rect64_flipy = {0, 64, 64, 0};
2588     RECT dst_rect64 = {0, 0, 64, 64};
2589     RECT dst_rect64_flipy = {0, 64, 64, 0};
2590
2591     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &orig_rt);
2592     ok(hr == D3D_OK, "Can't get render target, hr = %08x\n", hr);
2593     if(!orig_rt) {
2594         goto out;
2595     }
2596
2597     /* Create our temporary surfaces in system memory */
2598     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf_temp32, NULL);
2599     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2600     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf_temp64, NULL);
2601     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2602
2603     /* Create offscreen plain surfaces in D3DPOOL_DEFAULT */
2604     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_offscreen32, NULL);
2605     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2606     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_offscreen64, NULL);
2607     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2608     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_offscreen_dest64, NULL);
2609     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %08x\n", hr);
2610
2611     /* Create render target surfaces */
2612     hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &surf_rt32, NULL );
2613     ok(hr == D3D_OK, "Creating the render target surface failed with %08x\n", hr);
2614     hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &surf_rt64, NULL );
2615     ok(hr == D3D_OK, "Creating the render target surface failed with %08x\n", hr);
2616     hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &surf_rt_dest64, NULL );
2617     ok(hr == D3D_OK, "Creating the render target surface failed with %08x\n", hr);
2618     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
2619     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
2620
2621     /* Create render target textures */
2622     hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt32, NULL);
2623     ok(hr == D3D_OK, "Creating the render target texture failed with %08x\n", hr);
2624     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt64, NULL);
2625     ok(hr == D3D_OK, "Creating the render target texture failed with %08x\n", hr);
2626     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt_dest64, NULL);
2627     ok(hr == D3D_OK, "Creating the render target texture failed with %08x\n", hr);
2628     hr = IDirect3DDevice9_CreateTexture(device, 640, 480, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt_dest640_480, NULL);
2629     ok(hr == D3D_OK, "Creating the render target texture failed with %08x\n", hr);
2630     if (tex_rt32) {
2631         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt32, 0, &surf_tex_rt32);
2632         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2633     }
2634     if (tex_rt64) {
2635         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt64, 0, &surf_tex_rt64);
2636         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2637     }
2638     if (tex_rt_dest64) {
2639         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt_dest64, 0, &surf_tex_rt_dest64);
2640         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2641     }
2642     if (tex_rt_dest64) {
2643         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt_dest640_480, 0, &surf_tex_rt_dest640_480);
2644         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2645     }
2646
2647     /* Create regular textures in D3DPOOL_DEFAULT */
2648     hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex32, NULL);
2649     ok(hr == D3D_OK, "Creating the regular texture failed with %08x\n", hr);
2650     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex64, NULL);
2651     ok(hr == D3D_OK, "Creating the regular texture failed with %08x\n", hr);
2652     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_dest64, NULL);
2653     ok(hr == D3D_OK, "Creating the regular texture failed with %08x\n", hr);
2654     if (tex32) {
2655         hr = IDirect3DTexture9_GetSurfaceLevel(tex32, 0, &surf_tex32);
2656         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2657     }
2658     if (tex64) {
2659         hr = IDirect3DTexture9_GetSurfaceLevel(tex64, 0, &surf_tex64);
2660         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2661     }
2662     if (tex_dest64) {
2663         hr = IDirect3DTexture9_GetSurfaceLevel(tex_dest64, 0, &surf_tex_dest64);
2664         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
2665     }
2666
2667     /*********************************************************************
2668      * Tests for when the source parameter is an offscreen plain surface *
2669      *********************************************************************/
2670
2671     /* Fill the offscreen 64x64 surface with green */
2672     if (surf_offscreen64)
2673         fill_surface(surf_offscreen64, 0xff00ff00);
2674
2675     /* offscreenplain ==> offscreenplain, same size */
2676     if(surf_offscreen64 && surf_offscreen_dest64) {
2677         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_offscreen_dest64, NULL, 0);
2678         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2679
2680         if (hr == D3D_OK) {
2681             color = getPixelColorFromSurface(surf_offscreen_dest64, 32, 32);
2682             ok(color == 0xff00ff00, "StretchRect offscreen ==> offscreen same size failed: Got color 0x%08x, expected 0xff00ff00.\n", color);
2683         }
2684
2685         /* Blit without scaling */
2686         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64, surf_offscreen_dest64, &dst_rect64, 0);
2687         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2688
2689         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
2690         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64_flipy, surf_offscreen_dest64, &dst_rect64, 0);
2691         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2692
2693         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
2694         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64, surf_offscreen_dest64, &dst_rect64_flipy, 0);
2695         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2696     }
2697
2698     /* offscreenplain ==> rendertarget texture, same size */
2699     if(surf_offscreen64 && surf_tex_rt_dest64 && surf_temp64) {
2700         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_tex_rt_dest64, NULL, 0);
2701         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2702
2703         /* We can't lock rendertarget textures, so copy to our temp surface first */
2704         if (hr == D3D_OK) {
2705             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2706             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2707         }
2708
2709         if (hr == D3D_OK) {
2710             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2711             ok(color == 0xff00ff00, "StretchRect offscreen ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xff00ff00.\n", color);
2712         }
2713
2714         /* Blit without scaling */
2715         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64, surf_tex_rt_dest64, &dst_rect64, 0);
2716         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2717
2718         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
2719         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64_flipy, surf_tex_rt_dest64, &dst_rect64, 0);
2720         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2721
2722         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
2723         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64, surf_tex_rt_dest64, &dst_rect64_flipy, 0);
2724         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2725     }
2726
2727     /* offscreenplain ==> rendertarget surface, same size */
2728     if(surf_offscreen64 && surf_rt_dest64) {
2729         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_rt_dest64, NULL, 0);
2730         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2731
2732         if (hr == D3D_OK) {
2733             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2734             ok(color == 0xff00ff00, "StretchRect offscreen ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xff00ff00.\n", color);
2735         }
2736
2737         /* Blit without scaling */
2738         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64, surf_rt_dest64, &dst_rect64, 0);
2739         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2740
2741         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
2742         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64_flipy, surf_rt_dest64, &dst_rect64, 0);
2743         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2744
2745         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
2746         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, &src_rect64, surf_rt_dest64, &dst_rect64_flipy, 0);
2747         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2748     }
2749
2750     /* offscreenplain ==> texture, same size (should fail) */
2751     if(surf_offscreen64 && surf_tex_dest64) {
2752         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_tex_dest64, NULL, 0);
2753         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2754     }
2755
2756     /* Fill the smaller offscreen surface with red */
2757     fill_surface(surf_offscreen32, 0xffff0000);
2758
2759     /* offscreenplain ==> offscreenplain, scaling (should fail) */
2760     if(surf_offscreen32 && surf_offscreen64) {
2761         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_offscreen64, NULL, 0);
2762         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2763     }
2764
2765     /* offscreenplain ==> rendertarget texture, scaling */
2766     if(surf_offscreen32 && surf_tex_rt_dest64 && surf_temp64) {
2767         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_tex_rt_dest64, NULL, 0);
2768         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2769
2770         /* We can't lock rendertarget textures, so copy to our temp surface first */
2771         if (hr == D3D_OK) {
2772             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2773             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2774         }
2775
2776         if (hr == D3D_OK) {
2777             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2778             ok(color == 0xffff0000, "StretchRect offscreen ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2779         }
2780     }
2781
2782     /* offscreenplain ==> rendertarget surface, scaling */
2783     if(surf_offscreen32 && surf_rt_dest64) {
2784         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_rt_dest64, NULL, 0);
2785         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2786
2787         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2788         ok(color == 0xffff0000, "StretchRect offscreen ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2789     }
2790
2791     /* offscreenplain ==> texture, scaling (should fail) */
2792     if(surf_offscreen32 && surf_tex_dest64) {
2793         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_tex_dest64, NULL, 0);
2794         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2795     }
2796
2797     /************************************************************
2798      * Tests for when the source parameter is a regular texture *
2799      ************************************************************/
2800
2801     /* Fill the surface of the regular texture with blue */
2802     if (surf_tex64 && surf_temp64) {
2803         /* Can't fill the surf_tex directly because it's created in D3DPOOL_DEFAULT */
2804         fill_surface(surf_temp64, 0xff0000ff);
2805         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp64, NULL, surf_tex64, NULL);
2806         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
2807     }
2808
2809     /* texture ==> offscreenplain, same size */
2810     if(surf_tex64 && surf_offscreen64) {
2811         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_offscreen64, NULL, 0);
2812         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2813     }
2814
2815     /* texture ==> rendertarget texture, same size */
2816     if(surf_tex64 && surf_tex_rt_dest64 && surf_temp64) {
2817         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_tex_rt_dest64, NULL, 0);
2818         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2819
2820         /* We can't lock rendertarget textures, so copy to our temp surface first */
2821         if (hr == D3D_OK) {
2822             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2823             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2824         }
2825
2826         if (hr == D3D_OK) {
2827             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2828             ok(color == 0xff0000ff, "StretchRect texture ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xff0000ff.\n", color);
2829         }
2830
2831         /* Blit without scaling */
2832         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, &src_rect64, surf_tex_rt_dest64, &dst_rect64, 0);
2833         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2834
2835         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
2836         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, &src_rect64_flipy, surf_tex_rt_dest64, &dst_rect64, 0);
2837         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2838
2839         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
2840         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, &src_rect64, surf_tex_rt_dest64, &dst_rect64_flipy, 0);
2841         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2842     }
2843
2844     /* texture ==> rendertarget surface, same size */
2845     if(surf_tex64 && surf_rt_dest64) {
2846         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_rt_dest64, NULL, 0);
2847         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2848
2849         if (hr == D3D_OK) {
2850             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2851             ok(color == 0xff0000ff, "StretchRect texture ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xff0000ff.\n", color);
2852         }
2853
2854         /* Blit without scaling */
2855         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, &src_rect64, surf_rt_dest64, &dst_rect64, 0);
2856         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2857
2858         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
2859         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, &src_rect64_flipy, surf_rt_dest64, &dst_rect64, 0);
2860         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2861
2862         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
2863         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, &src_rect64, surf_rt_dest64, &dst_rect64_flipy, 0);
2864         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2865     }
2866
2867     /* texture ==> texture, same size (should fail) */
2868     if(surf_tex64 && surf_tex_dest64) {
2869         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_tex_dest64, NULL, 0);
2870         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2871     }
2872
2873     /* Fill the surface of the smaller regular texture with red */
2874     if (surf_tex32 && surf_temp32) {
2875         /* Can't fill the surf_tex directly because it's created in D3DPOOL_DEFAULT */
2876         fill_surface(surf_temp32, 0xffff0000);
2877         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp32, NULL, surf_tex32, NULL);
2878         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
2879     }
2880
2881     /* texture ==> offscreenplain, scaling (should fail) */
2882     if(surf_tex32 && surf_offscreen64) {
2883         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_offscreen64, NULL, 0);
2884         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2885     }
2886
2887     /* texture ==> rendertarget texture, scaling */
2888     if(surf_tex32 && surf_tex_rt_dest64 && surf_temp64) {
2889         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_tex_rt_dest64, NULL, 0);
2890         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2891
2892         /* We can't lock rendertarget textures, so copy to our temp surface first */
2893         if (hr == D3D_OK) {
2894             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2895             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2896         }
2897
2898         if (hr == D3D_OK) {
2899             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2900             ok(color == 0xffff0000, "StretchRect texture ==> rendertarget texture scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2901         }
2902     }
2903
2904     /* texture ==> rendertarget surface, scaling */
2905     if(surf_tex32 && surf_rt_dest64) {
2906         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_rt_dest64, NULL, 0);
2907         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2908
2909         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2910         ok(color == 0xffff0000, "StretchRect texture ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2911     }
2912
2913     /* texture ==> texture, scaling (should fail) */
2914     if(surf_tex32 && surf_tex_dest64) {
2915         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_tex_dest64, NULL, 0);
2916         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2917     }
2918
2919     /*****************************************************************
2920      * Tests for when the source parameter is a rendertarget texture *
2921      *****************************************************************/
2922
2923     /* Fill the surface of the rendertarget texture with white */
2924     if (surf_tex_rt64 && surf_temp64) {
2925         /* Can't fill the surf_tex_rt directly because it's created in D3DPOOL_DEFAULT */
2926         fill_surface(surf_temp64, 0xffffffff);
2927         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp64, NULL, surf_tex_rt64, NULL);
2928         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
2929     }
2930
2931     /* rendertarget texture ==> offscreenplain, same size */
2932     if(surf_tex_rt64 && surf_offscreen64) {
2933         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_offscreen64, NULL, 0);
2934         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2935     }
2936
2937     /* rendertarget texture ==> rendertarget texture, same size */
2938     if(surf_tex_rt64 && surf_tex_rt_dest64 && surf_temp64) {
2939         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_tex_rt_dest64, NULL, 0);
2940         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2941
2942         /* We can't lock rendertarget textures, so copy to our temp surface first */
2943         if (hr == D3D_OK) {
2944             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2945             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
2946         }
2947
2948         if (hr == D3D_OK) {
2949             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2950             ok(color == 0xffffffff, "StretchRect rendertarget texture ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xffffffff.\n", color);
2951         }
2952
2953         /* Blit without scaling */
2954         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, &src_rect64, surf_tex_rt_dest64, &dst_rect64, 0);
2955         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2956
2957         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
2958         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, &src_rect64_flipy, surf_tex_rt_dest64, &dst_rect64, 0);
2959         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2960
2961         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
2962         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, &src_rect64, surf_tex_rt_dest64, &dst_rect64_flipy, 0);
2963         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2964     }
2965
2966     /* rendertarget texture ==> rendertarget surface, same size */
2967     if(surf_tex_rt64 && surf_rt_dest64) {
2968         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_rt_dest64, NULL, 0);
2969         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2970
2971         if (hr == D3D_OK) {
2972             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2973             ok(color == 0xffffffff, "StretchRect rendertarget texture ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xffffffff.\n", color);
2974         }
2975
2976         /* Blit without scaling */
2977         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, &src_rect64, surf_rt_dest64, &dst_rect64, 0);
2978         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2979
2980         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
2981         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, &src_rect64_flipy, surf_rt_dest64, &dst_rect64, 0);
2982         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2983
2984         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
2985         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, &src_rect64, surf_rt_dest64, &dst_rect64_flipy, 0);
2986         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
2987     }
2988
2989     /* rendertarget texture ==> texture, same size (should fail) */
2990     if(surf_tex_rt64 && surf_tex_dest64) {
2991         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_tex_dest64, NULL, 0);
2992         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2993     }
2994
2995     /* Fill the surface of the smaller rendertarget texture with red */
2996     if (surf_tex_rt32 && surf_temp32) {
2997         /* Can't fill the surf_tex_rt directly because it's created in D3DPOOL_DEFAULT */
2998         fill_surface(surf_temp32, 0xffff0000);
2999         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp32, NULL, surf_tex_rt32, NULL);
3000         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %08x\n", hr);
3001     }
3002
3003     /* rendertarget texture ==> offscreenplain, scaling (should fail) */
3004     if(surf_tex_rt32 && surf_offscreen64) {
3005         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_offscreen64, NULL, 0);
3006         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
3007     }
3008
3009     /* rendertarget texture ==> rendertarget texture, scaling */
3010     if(surf_tex_rt32 && surf_tex_rt_dest64 && surf_temp64) {
3011         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_tex_rt_dest64, NULL, 0);
3012         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3013
3014         /* We can't lock rendertarget textures, so copy to our temp surface first */
3015         if (hr == D3D_OK) {
3016             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
3017             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
3018         }
3019
3020         if (hr == D3D_OK) {
3021             color = getPixelColorFromSurface(surf_temp64, 48, 48);
3022             ok(color == 0xffff0000, "StretchRect rendertarget texture ==> rendertarget texture scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
3023         }
3024     }
3025
3026     /* rendertarget texture ==> rendertarget surface, scaling */
3027     if(surf_tex_rt32 && surf_rt_dest64) {
3028         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_rt_dest64, NULL, 0);
3029         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3030
3031         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
3032         ok(color == 0xffff0000, "StretchRect rendertarget texture ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
3033     }
3034
3035     /* rendertarget texture ==> texture, scaling (should fail) */
3036     if(surf_tex_rt32 && surf_tex_dest64) {
3037         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_tex_dest64, NULL, 0);
3038         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
3039     }
3040
3041     /*****************************************************************
3042      * Tests for when the source parameter is a rendertarget surface *
3043      *****************************************************************/
3044
3045     /* Fill the surface of the rendertarget surface with black */
3046     if (surf_rt64)
3047         fill_surface(surf_rt64, 0xff000000);
3048
3049     /* rendertarget texture ==> offscreenplain, same size */
3050     if(surf_rt64 && surf_offscreen64) {
3051         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_offscreen64, NULL, 0);
3052         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
3053     }
3054
3055     /* rendertarget surface ==> rendertarget texture, same size */
3056     if(surf_rt64 && surf_tex_rt_dest64 && surf_temp64) {
3057         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_tex_rt_dest64, NULL, 0);
3058         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3059
3060         /* We can't lock rendertarget textures, so copy to our temp surface first */
3061         if (hr == D3D_OK) {
3062             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
3063             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
3064         }
3065
3066         if (hr == D3D_OK) {
3067             color = getPixelColorFromSurface(surf_temp64, 32, 32);
3068             ok(color == 0xff000000, "StretchRect rendertarget surface ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xff000000.\n", color);
3069         }
3070
3071         /* Blit without scaling */
3072         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, &src_rect64, surf_tex_rt_dest64, &dst_rect64, 0);
3073         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3074
3075         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
3076         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, &src_rect64_flipy, surf_tex_rt_dest64, &dst_rect64, 0);
3077         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3078
3079         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
3080         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, &src_rect64, surf_tex_rt_dest64, &dst_rect64_flipy, 0);
3081         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3082     }
3083
3084     /* rendertarget surface ==> rendertarget surface, same size */
3085     if(surf_rt64 && surf_rt_dest64) {
3086         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_rt_dest64, NULL, 0);
3087         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3088
3089         if (hr == D3D_OK) {
3090             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
3091             ok(color == 0xff000000, "StretchRect rendertarget surface ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xff000000.\n", color);
3092         }
3093
3094         /* Blit without scaling */
3095         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, &src_rect64, surf_rt_dest64, &dst_rect64, 0);
3096         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3097
3098         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
3099         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, &src_rect64_flipy, surf_rt_dest64, &dst_rect64_flipy, 0);
3100         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3101
3102         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
3103         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, &src_rect64, surf_rt_dest64, &dst_rect64_flipy, 0);
3104         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3105     }
3106
3107     /* rendertarget surface ==> texture, same size (should fail) */
3108     if(surf_rt64 && surf_tex_dest64) {
3109         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_tex_dest64, NULL, 0);
3110         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
3111     }
3112
3113     /* Fill the surface of the smaller rendertarget texture with red */
3114     if (surf_rt32)
3115         fill_surface(surf_rt32, 0xffff0000);
3116
3117     /* rendertarget surface ==> offscreenplain, scaling (should fail) */
3118     if(surf_rt32 && surf_offscreen64) {
3119         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_offscreen64, NULL, 0);
3120         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
3121     }
3122
3123     /* rendertarget surface ==> rendertarget texture, scaling */
3124     if(surf_rt32 && surf_tex_rt_dest64 && surf_temp64) {
3125         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_tex_rt_dest64, NULL, 0);
3126         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3127
3128         /* We can't lock rendertarget textures, so copy to our temp surface first */
3129         if (hr == D3D_OK) {
3130             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
3131             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %08x\n", hr);
3132         }
3133
3134         if (hr == D3D_OK) {
3135             color = getPixelColorFromSurface(surf_temp64, 48, 48);
3136             ok(color == 0xffff0000, "StretchRect rendertarget surface ==> rendertarget texture scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
3137         }
3138     }
3139
3140     /* rendertarget surface ==> rendertarget surface, scaling */
3141     if(surf_rt32 && surf_rt_dest64) {
3142         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_rt_dest64, NULL, 0);
3143         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3144
3145         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
3146         ok(color == 0xffff0000, "StretchRect rendertarget surface ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
3147     }
3148
3149     /* rendertarget surface ==> texture, scaling (should fail) */
3150     if(surf_rt32 && surf_tex_dest64) {
3151         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_tex_dest64, NULL, 0);
3152         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
3153     }
3154
3155     /* backbuffer ==> surface tests (no scaling) */
3156     if(backbuffer && surf_tex_rt_dest640_480)
3157     {
3158         RECT src_rect = {0, 0, 640, 480};
3159         RECT src_rect_flipy = {0, 480, 640, 0};
3160         RECT dst_rect = {0, 0, 640, 480};
3161         RECT dst_rect_flipy = {0, 480, 640, 0};
3162
3163         /* Blit with NULL rectangles */
3164         hr = IDirect3DDevice9_StretchRect(device, backbuffer, NULL, surf_tex_rt_dest640_480, NULL, 0);
3165         ok( hr == D3D_OK, "StretchRect backbuffer ==> texture same size failed:\n");
3166
3167         /* Blit without scaling */
3168         hr = IDirect3DDevice9_StretchRect(device, backbuffer, &src_rect, surf_tex_rt_dest640_480, &dst_rect, 0);
3169         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
3170
3171         /* Flipping in y-direction through src_rect, no scaling (not allowed) */
3172         hr = IDirect3DDevice9_StretchRect(device, backbuffer, &src_rect_flipy, surf_tex_rt_dest640_480, &dst_rect, 0);
3173         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3174
3175         /* Flipping in y-direction through dst_rect, no scaling (not allowed) */
3176         hr = IDirect3DDevice9_StretchRect(device, backbuffer, &src_rect, surf_tex_rt_dest640_480, &dst_rect_flipy, 0);
3177         ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
3178     }
3179
3180     /* TODO: Test format conversions */
3181
3182
3183 out:
3184     /* Clean up */
3185     if (backbuffer)
3186         IDirect3DSurface9_Release(backbuffer);
3187     if (surf_rt32)
3188         IDirect3DSurface9_Release(surf_rt32);
3189     if (surf_rt64)
3190         IDirect3DSurface9_Release(surf_rt64);
3191     if (surf_rt_dest64)
3192         IDirect3DSurface9_Release(surf_rt_dest64);
3193     if (surf_temp32)
3194         IDirect3DSurface9_Release(surf_temp32);
3195     if (surf_temp64)
3196         IDirect3DSurface9_Release(surf_temp64);
3197     if (surf_offscreen32)
3198         IDirect3DSurface9_Release(surf_offscreen32);
3199     if (surf_offscreen64)
3200         IDirect3DSurface9_Release(surf_offscreen64);
3201     if (surf_offscreen_dest64)
3202         IDirect3DSurface9_Release(surf_offscreen_dest64);
3203
3204     if (tex_rt32) {
3205         if (surf_tex_rt32)
3206             IDirect3DSurface9_Release(surf_tex_rt32);
3207         IDirect3DTexture9_Release(tex_rt32);
3208     }
3209     if (tex_rt64) {
3210         if (surf_tex_rt64)
3211             IDirect3DSurface9_Release(surf_tex_rt64);
3212         IDirect3DTexture9_Release(tex_rt64);
3213     }
3214     if (tex_rt_dest64) {
3215         if (surf_tex_rt_dest64)
3216             IDirect3DSurface9_Release(surf_tex_rt_dest64);
3217         IDirect3DTexture9_Release(tex_rt_dest64);
3218     }
3219     if (tex_rt_dest640_480) {
3220         if (surf_tex_rt_dest640_480)
3221             IDirect3DSurface9_Release(surf_tex_rt_dest640_480);
3222         IDirect3DTexture9_Release(tex_rt_dest640_480);
3223     }
3224     if (tex32) {
3225         if (surf_tex32)
3226             IDirect3DSurface9_Release(surf_tex32);
3227         IDirect3DTexture9_Release(tex32);
3228     }
3229     if (tex64) {
3230         if (surf_tex64)
3231             IDirect3DSurface9_Release(surf_tex64);
3232         IDirect3DTexture9_Release(tex64);
3233     }
3234     if (tex_dest64) {
3235         if (surf_tex_dest64)
3236             IDirect3DSurface9_Release(surf_tex_dest64);
3237         IDirect3DTexture9_Release(tex_dest64);
3238     }
3239
3240     if (orig_rt) {
3241         hr = IDirect3DDevice9_SetRenderTarget(device, 0, orig_rt);
3242         ok(hr == D3D_OK, "IDirect3DSetRenderTarget failed with %08x\n", hr);
3243         IDirect3DSurface9_Release(orig_rt);
3244     }
3245 }
3246
3247 static void maxmip_test(IDirect3DDevice9 *device)
3248 {
3249     IDirect3DTexture9 *texture = NULL;
3250     IDirect3DSurface9 *surface = NULL;
3251     HRESULT hr;
3252     DWORD color;
3253     static const struct
3254     {
3255         struct
3256         {
3257             float x, y, z;
3258             float s, t;
3259         }
3260         v[4];
3261     }
3262     quads[] =
3263     {
3264         {{
3265             {-1.0, -1.0,  0.0,  0.0,  0.0},
3266             {-1.0,  0.0,  0.0,  0.0,  1.0},
3267             { 0.0, -1.0,  0.0,  1.0,  0.0},
3268             { 0.0,  0.0,  0.0,  1.0,  1.0},
3269         }},
3270         {{
3271             { 0.0, -1.0,  0.0,  0.0,  0.0},
3272             { 0.0,  0.0,  0.0,  0.0,  1.0},
3273             { 1.0, -1.0,  0.0,  1.0,  0.0},
3274             { 1.0,  0.0,  0.0,  1.0,  1.0},
3275         }},
3276         {{
3277             { 0.0,  0.0,  0.0,  0.0,  0.0},
3278             { 0.0,  1.0,  0.0,  0.0,  1.0},
3279             { 1.0,  0.0,  0.0,  1.0,  0.0},
3280             { 1.0,  1.0,  0.0,  1.0,  1.0},
3281         }},
3282         {{
3283             {-1.0,  0.0,  0.0,  0.0,  0.0},
3284             {-1.0,  1.0,  0.0,  0.0,  1.0},
3285             { 0.0,  0.0,  0.0,  1.0,  0.0},
3286             { 0.0,  1.0,  0.0,  1.0,  1.0},
3287         }},
3288     };
3289
3290     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
3291                                         &texture, NULL);
3292     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
3293     if(!texture)
3294     {
3295         skip("Failed to create test texture\n");
3296         return;
3297     }
3298
3299     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
3300     ok(SUCCEEDED(hr), "IDirect3DTexture9_GetSurfaceLevel returned %#x.\n", hr);
3301     fill_surface(surface, 0xffff0000);
3302     IDirect3DSurface9_Release(surface);
3303     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface);
3304     ok(SUCCEEDED(hr), "IDirect3DTexture9_GetSurfaceLevel returned %#x.\n", hr);
3305     fill_surface(surface, 0xff00ff00);
3306     IDirect3DSurface9_Release(surface);
3307     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
3308     ok(SUCCEEDED(hr), "IDirect3DTexture9_GetSurfaceLevel returned %#x.\n", hr);
3309     fill_surface(surface, 0xff0000ff);
3310     IDirect3DSurface9_Release(surface);
3311
3312     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3313     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3314     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3315     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3316
3317     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
3318     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3319
3320     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
3321     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3322
3323     hr = IDirect3DDevice9_BeginScene(device);
3324     if(SUCCEEDED(hr))
3325     {
3326         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
3327         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3328         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[0], sizeof(*quads->v));
3329         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3330
3331         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
3332         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3333         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[1], sizeof(*quads->v));
3334         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3335
3336         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
3337         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3338         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[2], sizeof(*quads->v));
3339         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3340
3341         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
3342         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3343         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[3], sizeof(*quads->v));
3344         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3345         hr = IDirect3DDevice9_EndScene(device);
3346         ok(SUCCEEDED(hr), "EndScene failed (%08x)\n", hr);
3347     }
3348
3349     /* With mipmapping disabled, the max mip level is ignored, only level 0 is used */
3350     color = getPixelColor(device, 160, 360);
3351     ok(color == 0x00ff0000, "MaxMip 0, no mipfilter has color 0x%08x.\n", color);
3352     color = getPixelColor(device, 480, 360);
3353     ok(color == 0x00ff0000, "MaxMip 1, no mipfilter has color 0x%08x.\n", color);
3354     color = getPixelColor(device, 480, 120);
3355     ok(color == 0x00ff0000, "MaxMip 2, no mipfilter has color 0x%08x.\n", color);
3356     color = getPixelColor(device, 160, 120);
3357     ok(color == 0x00ff0000, "MaxMip 3, no mipfilter has color 0x%08x.\n", color);
3358     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3359     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
3360
3361     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
3362     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3363
3364     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
3365     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3366
3367     hr = IDirect3DDevice9_BeginScene(device);
3368     if(SUCCEEDED(hr))
3369     {
3370         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
3371         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3372         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[0], sizeof(*quads->v));
3373         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3374
3375         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
3376         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3377         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[1], sizeof(*quads->v));
3378         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3379
3380         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
3381         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3382         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[2], sizeof(*quads->v));
3383         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3384
3385         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
3386         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3387         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[3], sizeof(*quads->v));
3388         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3389         hr = IDirect3DDevice9_EndScene(device);
3390         ok(SUCCEEDED(hr), "IDirect3DDevice9_EndScene returned %#x.\n", hr);
3391     }
3392
3393     /* Max Mip level 0-2 sample from the specified texture level, Max Mip
3394      * level 3 (> levels in texture) samples from the highest level in the
3395      * texture (level 2). */
3396     color = getPixelColor(device, 160, 360);
3397     ok(color == 0x00ff0000, "MaxMip 0, point mipfilter has color 0x%08x.\n", color);
3398     color = getPixelColor(device, 480, 360);
3399     ok(color == 0x0000ff00, "MaxMip 1, point mipfilter has color 0x%08x.\n", color);
3400     color = getPixelColor(device, 480, 120);
3401     ok(color == 0x000000ff, "MaxMip 2, point mipfilter has color 0x%08x.\n", color);
3402     color = getPixelColor(device, 160, 120);
3403     ok(color == 0x000000ff, "MaxMip 3, point mipfilter has color 0x%08x.\n", color);
3404     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3405     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
3406
3407     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
3408     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3409
3410     hr = IDirect3DDevice9_BeginScene(device);
3411     if(SUCCEEDED(hr))
3412     {
3413         DWORD ret;
3414
3415         /* Mipmapping OFF, LOD level smaller than MAXMIPLEVEL. LOD level limits */
3416         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
3417         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3418         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
3419         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3420         ret = IDirect3DTexture9_SetLOD(texture, 1);
3421         ok(ret == 0, "IDirect3DTexture9_SetLOD returned %u, expected 0\n", ret);
3422         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[0], sizeof(*quads->v));
3423         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3424
3425         /* Mipmapping ON, LOD level smaller than max mip level. LOD level limits */
3426         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
3427         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3428         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
3429         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3430         ret = IDirect3DTexture9_SetLOD(texture, 2);
3431         ok(ret == 1, "IDirect3DTexture9_SetLOD returned %u, expected 1\n", ret);
3432         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[1], sizeof(*quads->v));
3433         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3434
3435         /* Mipmapping ON, LOD level bigger than max mip level. MAXMIPLEVEL limits */
3436         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
3437         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3438         ret = IDirect3DTexture9_SetLOD(texture, 1);
3439         ok(ret == 2, "IDirect3DTexture9_SetLOD returned %u, expected 2\n", ret);
3440         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[2], sizeof(*quads->v));
3441         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3442
3443         /* Mipmapping OFF, LOD level bigger than max mip level. LOD level limits */
3444         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
3445         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3446         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
3447         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3448         ret = IDirect3DTexture9_SetLOD(texture, 1);
3449         ok(ret == 1, "IDirect3DTexture9_SetLOD returned %u, expected 1\n", ret);
3450         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[3], sizeof(*quads->v));
3451         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3452         hr = IDirect3DDevice9_EndScene(device);
3453         ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
3454     }
3455
3456     /* Max Mip level 0-2 sample from the specified texture level, Max Mip
3457      * level 3 (> levels in texture) samples from the highest level in the
3458      * texture (level 2). */
3459     color = getPixelColor(device, 160, 360);
3460     ok(color == 0x0000ff00, "MaxMip 0, LOD 1, none mipfilter has color 0x%08x.\n", color);
3461     color = getPixelColor(device, 480, 360);
3462     ok(color == 0x000000ff, "MaxMip 1, LOD 2, point mipfilter has color 0x%08x.\n", color);
3463     color = getPixelColor(device, 480, 120);
3464     ok(color == 0x000000ff, "MaxMip 2, LOD 1, point mipfilter has color 0x%08x.\n", color);
3465     color = getPixelColor(device, 160, 120);
3466     ok(color == 0x0000ff00, "MaxMip 2, LOD 1, none mipfilter has color 0x%08x.\n", color);
3467
3468     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3469     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
3470
3471     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3472     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3473     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
3474     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3475     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
3476     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
3477     IDirect3DTexture9_Release(texture);
3478 }
3479
3480 static void release_buffer_test(IDirect3DDevice9 *device)
3481 {
3482     IDirect3DVertexBuffer9 *vb = NULL;
3483     IDirect3DIndexBuffer9 *ib = NULL;
3484     HRESULT hr;
3485     BYTE *data;
3486     LONG ref;
3487
3488     static const struct vertex quad[] = {
3489         {-1.0,      -1.0,       0.1,        0xffff0000},
3490         {-1.0,       1.0,       0.1,        0xffff0000},
3491         { 1.0,       1.0,       0.1,        0xffff0000},
3492
3493         {-1.0,      -1.0,       0.1,        0xff00ff00},
3494         {-1.0,       1.0,       0.1,        0xff00ff00},
3495         { 1.0,       1.0,       0.1,        0xff00ff00}
3496     };
3497     short indices[] = {3, 4, 5};
3498
3499     /* Index and vertex buffers should always be creatable */
3500     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, D3DFVF_XYZ | D3DFVF_DIFFUSE,
3501                                               D3DPOOL_MANAGED, &vb, NULL);
3502     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
3503     if(!vb) {
3504         skip("Failed to create a vertex buffer\n");
3505         return;
3506     }
3507     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, NULL);
3508     ok(hr == D3D_OK, "IDirect3DDevice9_CreateIndexBuffer failed with %08x\n", hr);
3509     if(!ib) {
3510         skip("Failed to create an index buffer\n");
3511         return;
3512     }
3513
3514     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), (void **) &data, 0);
3515     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
3516     memcpy(data, quad, sizeof(quad));
3517     hr = IDirect3DVertexBuffer9_Unlock(vb);
3518     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
3519
3520     hr = IDirect3DIndexBuffer9_Lock(ib, 0, sizeof(indices), (void **) &data, 0);
3521     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Lock failed with %08x\n", hr);
3522     memcpy(data, indices, sizeof(indices));
3523     hr = IDirect3DIndexBuffer9_Unlock(ib);
3524     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
3525
3526     hr = IDirect3DDevice9_SetIndices(device, ib);
3527     ok(hr == D3D_OK, "IDirect3DDevice9_SetIndices failed with %08x\n", hr);
3528     hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad[0]));
3529     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
3530     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
3531     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3532
3533     /* Now destroy the bound index buffer and draw again */
3534     ref = IDirect3DIndexBuffer9_Release(ib);
3535     ok(ref == 0, "Index Buffer reference count is %08d\n", ref);
3536
3537     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
3538     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
3539
3540     hr = IDirect3DDevice9_BeginScene(device);
3541     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3542     if(SUCCEEDED(hr))
3543     {
3544         /* Deliberately using minvertexindex = 0 and numVertices = 6 to prevent d3d from
3545          * making assumptions about the indices or vertices
3546          */
3547         hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 3, 3, 0, 1);
3548         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitive failed with %08x\n", hr);
3549         hr = IDirect3DDevice9_EndScene(device);
3550         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3551     }
3552
3553     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3554     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3555
3556     hr = IDirect3DDevice9_SetIndices(device, NULL);
3557     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
3558     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
3559     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
3560
3561     /* Index buffer was already destroyed as part of the test */
3562     IDirect3DVertexBuffer9_Release(vb);
3563 }
3564
3565 static void float_texture_test(IDirect3DDevice9 *device)
3566 {
3567     IDirect3D9 *d3d = NULL;
3568     HRESULT hr;
3569     IDirect3DTexture9 *texture = NULL;
3570     D3DLOCKED_RECT lr;
3571     float *data;
3572     DWORD color;
3573     float quad[] = {
3574         -1.0,      -1.0,       0.1,     0.0,    0.0,
3575         -1.0,       1.0,       0.1,     0.0,    1.0,
3576          1.0,      -1.0,       0.1,     1.0,    0.0,
3577          1.0,       1.0,       0.1,     1.0,    1.0,
3578     };
3579
3580     memset(&lr, 0, sizeof(lr));
3581     IDirect3DDevice9_GetDirect3D(device, &d3d);
3582     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
3583                                      D3DRTYPE_TEXTURE, D3DFMT_R32F) != D3D_OK) {
3584         skip("D3DFMT_R32F textures not supported\n");
3585         goto out;
3586     }
3587
3588     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_R32F,
3589                                         D3DPOOL_MANAGED, &texture, NULL);
3590     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
3591     if(!texture) {
3592         skip("Failed to create R32F texture\n");
3593         goto out;
3594     }
3595
3596     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
3597     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %08x\n", hr);
3598     data = lr.pBits;
3599     *data = 0.0;
3600     hr = IDirect3DTexture9_UnlockRect(texture, 0);
3601     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %08x\n", hr);
3602
3603     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3604     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3605
3606     hr = IDirect3DDevice9_BeginScene(device);
3607     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3608     if(SUCCEEDED(hr))
3609     {
3610         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3611         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3612
3613         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
3614         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3615
3616         hr = IDirect3DDevice9_EndScene(device);
3617         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3618     }
3619     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3620     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3621
3622     color = getPixelColor(device, 240, 320);
3623     ok(color == 0x0000FFFF, "R32F with value 0.0 has color %08x, expected 0x0000FFFF\n", color);
3624
3625     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3626     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3627
3628 out:
3629     if(texture) IDirect3DTexture9_Release(texture);
3630     IDirect3D9_Release(d3d);
3631 }
3632
3633 static void g16r16_texture_test(IDirect3DDevice9 *device)
3634 {
3635     IDirect3D9 *d3d = NULL;
3636     HRESULT hr;
3637     IDirect3DTexture9 *texture = NULL;
3638     D3DLOCKED_RECT lr;
3639     DWORD *data;
3640     DWORD color;
3641     float quad[] = {
3642        -1.0,      -1.0,       0.1,     0.0,    0.0,
3643        -1.0,       1.0,       0.1,     0.0,    1.0,
3644         1.0,      -1.0,       0.1,     1.0,    0.0,
3645         1.0,       1.0,       0.1,     1.0,    1.0,
3646     };
3647
3648     memset(&lr, 0, sizeof(lr));
3649     IDirect3DDevice9_GetDirect3D(device, &d3d);
3650     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
3651        D3DRTYPE_TEXTURE, D3DFMT_G16R16) != D3D_OK) {
3652            skip("D3DFMT_G16R16 textures not supported\n");
3653            goto out;
3654     }
3655
3656     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_G16R16,
3657                                         D3DPOOL_MANAGED, &texture, NULL);
3658     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
3659     if(!texture) {
3660         skip("Failed to create D3DFMT_G16R16 texture\n");
3661         goto out;
3662     }
3663
3664     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
3665     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %08x\n", hr);
3666     data = lr.pBits;
3667     *data = 0x0f00f000;
3668     hr = IDirect3DTexture9_UnlockRect(texture, 0);
3669     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %08x\n", hr);
3670
3671     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3672     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3673
3674     hr = IDirect3DDevice9_BeginScene(device);
3675     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3676     if(SUCCEEDED(hr))
3677     {
3678         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3679         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3680
3681         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
3682         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3683
3684         hr = IDirect3DDevice9_EndScene(device);
3685         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3686     }
3687     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3688     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
3689
3690     color = getPixelColor(device, 240, 320);
3691     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xf0, 0x0f, 0xff), 1),
3692        "D3DFMT_G16R16 with value 0x00ffff00 has color %08x, expected 0x00f00fff\n", color);
3693
3694     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3695     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3696
3697 out:
3698     if(texture) IDirect3DTexture9_Release(texture);
3699     IDirect3D9_Release(d3d);
3700 }
3701
3702 static void texture_transform_flags_test(IDirect3DDevice9 *device)
3703 {
3704     HRESULT hr;
3705     IDirect3D9 *d3d;
3706     D3DFORMAT fmt = D3DFMT_X8R8G8B8;
3707     D3DCAPS9 caps;
3708     IDirect3DTexture9 *texture = NULL;
3709     IDirect3DVolumeTexture9 *volume = NULL;
3710     unsigned int x, y, z;
3711     D3DLOCKED_RECT lr;
3712     D3DLOCKED_BOX lb;
3713     DWORD color;
3714     UINT w, h;
3715     IDirect3DVertexDeclaration9 *decl, *decl2, *decl3;
3716     float identity[16] = {1.0, 0.0, 0.0, 0.0,
3717                            0.0, 1.0, 0.0, 0.0,
3718                            0.0, 0.0, 1.0, 0.0,
3719                            0.0, 0.0, 0.0, 1.0};
3720     static const D3DVERTEXELEMENT9 decl_elements[] = {
3721         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3722         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3723         D3DDECL_END()
3724     };
3725     static const D3DVERTEXELEMENT9 decl_elements2[] = {
3726         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3727         {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3728         D3DDECL_END()
3729     };
3730     static const D3DVERTEXELEMENT9 decl_elements3[] = {
3731         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3732         {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3733         D3DDECL_END()
3734     };
3735     static const unsigned char proj_texdata[] = {0x00, 0x00, 0x00, 0x00,
3736                                                  0x00, 0xff, 0x00, 0x00,
3737                                                  0x00, 0x00, 0x00, 0x00,
3738                                                  0x00, 0x00, 0x00, 0x00};
3739
3740     memset(&lr, 0, sizeof(lr));
3741     memset(&lb, 0, sizeof(lb));
3742     IDirect3DDevice9_GetDirect3D(device, &d3d);
3743     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
3744                                      D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16) == D3D_OK) {
3745         fmt = D3DFMT_A16B16G16R16;
3746     }
3747     IDirect3D9_Release(d3d);
3748
3749     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
3750     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
3751     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements2, &decl2);
3752     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
3753     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements3, &decl3);
3754     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
3755     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, FALSE);
3756     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_SRGBTEXTURE) returned %08x\n", hr);
3757     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
3758     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MAGFILTER) returned %08x\n", hr);
3759     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
3760     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MINFILTER) returned %08x\n", hr);
3761     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
3762     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MIPFILTER) returned %08x\n", hr);
3763     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
3764     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSU) returned %08x\n", hr);
3765     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
3766     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSV) returned %08x\n", hr);
3767     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP);
3768     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSW) returned %08x\n", hr);
3769     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
3770     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState(D3DRS_LIGHTING) returned %08x\n", hr);
3771     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
3772     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3773
3774     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3775     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %08x\n", hr);
3776     w = min(1024, caps.MaxTextureWidth);
3777     h = min(1024, caps.MaxTextureHeight);
3778     hr = IDirect3DDevice9_CreateTexture(device, w, h, 1,
3779                                         0, fmt, D3DPOOL_MANAGED, &texture, NULL);
3780     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
3781     if(!texture) {
3782         skip("Failed to create the test texture\n");
3783         return;
3784     }
3785
3786     /* Unfortunately there is no easy way to set up a texture coordinate passthrough
3787      * in d3d fixed function pipeline, so create a texture that has a gradient from 0.0 to
3788      * 1.0 in red and green for the x and y coords
3789      */
3790     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
3791     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %08x\n", hr);
3792     for(y = 0; y < h; y++) {
3793         for(x = 0; x < w; x++) {
3794             double r_f = (double) y / (double) h;
3795             double g_f = (double) x / (double) w;
3796             if(fmt == D3DFMT_A16B16G16R16) {
3797                 unsigned short r, g;
3798                 unsigned short *dst = (unsigned short *) (((char *) lr.pBits) + y * lr.Pitch + x * 8);
3799                 r = (unsigned short) (r_f * 65536.0);
3800                 g = (unsigned short) (g_f * 65536.0);
3801                 dst[0] = r;
3802                 dst[1] = g;
3803                 dst[2] = 0;
3804                 dst[3] = 65535;
3805             } else {
3806                 unsigned char *dst = ((unsigned char *) lr.pBits) + y * lr.Pitch + x * 4;
3807                 unsigned char r = (unsigned char) (r_f * 255.0);
3808                 unsigned char g = (unsigned char) (g_f * 255.0);
3809                 dst[0] = 0;
3810                 dst[1] = g;
3811                 dst[2] = r;
3812                 dst[3] = 255;
3813             }
3814         }
3815     }
3816     hr = IDirect3DTexture9_UnlockRect(texture, 0);
3817     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect returned %08x\n", hr);
3818     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3819     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
3820
3821     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3822     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3823     hr = IDirect3DDevice9_BeginScene(device);
3824     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3825     if(SUCCEEDED(hr))
3826     {
3827         float quad1[] = {
3828             -1.0,      -1.0,       0.1,     1.0,    1.0,
3829             -1.0,       0.0,       0.1,     1.0,    1.0,
3830              0.0,      -1.0,       0.1,     1.0,    1.0,
3831              0.0,       0.0,       0.1,     1.0,    1.0,
3832         };
3833         float quad2[] = {
3834             -1.0,       0.0,       0.1,     1.0,    1.0,
3835             -1.0,       1.0,       0.1,     1.0,    1.0,
3836              0.0,       0.0,       0.1,     1.0,    1.0,
3837              0.0,       1.0,       0.1,     1.0,    1.0,
3838         };
3839         float quad3[] = {
3840              0.0,       0.0,       0.1,     0.5,    0.5,
3841              0.0,       1.0,       0.1,     0.5,    0.5,
3842              1.0,       0.0,       0.1,     0.5,    0.5,
3843              1.0,       1.0,       0.1,     0.5,    0.5,
3844         };
3845         float quad4[] = {
3846              320,       480,       0.1,     1.0,    0.0,    1.0,
3847              320,       240,       0.1,     1.0,    0.0,    1.0,
3848              640,       480,       0.1,     1.0,    0.0,    1.0,
3849              640,       240,       0.1,     1.0,    0.0,    1.0,
3850         };
3851         float mat[16] = {0.0, 0.0, 0.0, 0.0,
3852                           0.0, 0.0, 0.0, 0.0,
3853                           0.0, 0.0, 0.0, 0.0,
3854                           0.0, 0.0, 0.0, 0.0};
3855
3856         /* What happens with the texture matrix if D3DTSS_TEXTURETRANSFORMFLAGS is disabled? */
3857         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3858         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3859         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
3860         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3861
3862         /* What happens with transforms enabled? */
3863         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3864         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3865         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
3866         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3867
3868         /* What happens if 4 coords are used, but only 2 given ?*/
3869         mat[8] = 1.0;
3870         mat[13] = 1.0;
3871         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3872         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3873         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
3874         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3875         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
3876         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3877
3878         /* What happens with transformed geometry? This setup lead to 0/0 coords with untransformed
3879          * geometry. If the same applies to transformed vertices, the quad will be black, otherwise red,
3880          * due to the coords in the vertices. (turns out red, indeed)
3881          */
3882         memset(mat, 0, sizeof(mat));
3883         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3884         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3885         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_TEX1);
3886         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3887         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3888         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3889         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
3890         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3891
3892         hr = IDirect3DDevice9_EndScene(device);
3893         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3894     }
3895     color = getPixelColor(device, 160, 360);
3896     ok(color_match(color, 0x00FFFF00, 1), "quad 1 has color %08x, expected 0x00FFFF00\n", color);
3897     color = getPixelColor(device, 160, 120);
3898     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
3899     color = getPixelColor(device, 480, 120);
3900     ok(color_match(color, 0x0000FF00, 1), "quad 3 has color %08x, expected 0x0000FF00\n", color);
3901     color = getPixelColor(device, 480, 360);
3902     ok(color_match(color, 0x00FF0000, 1), "quad 4 has color %08x, expected 0x00FF0000\n", color);
3903     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3904     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3905
3906     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
3907     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
3908
3909     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3910     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
3911     hr = IDirect3DDevice9_BeginScene(device);
3912     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
3913     if(SUCCEEDED(hr))
3914     {
3915         float quad1[] = {
3916             -1.0,      -1.0,       0.1,     0.8,    0.2,
3917             -1.0,       0.0,       0.1,     0.8,    0.2,
3918              0.0,      -1.0,       0.1,     0.8,    0.2,
3919              0.0,       0.0,       0.1,     0.8,    0.2,
3920         };
3921         float quad2[] = {
3922             -1.0,       0.0,       0.1,     0.5,    1.0,
3923             -1.0,       1.0,       0.1,     0.5,    1.0,
3924              0.0,       0.0,       0.1,     0.5,    1.0,
3925              0.0,       1.0,       0.1,     0.5,    1.0,
3926         };
3927         float quad3[] = {
3928              0.0,       0.0,       0.1,     0.5,    1.0,
3929              0.0,       1.0,       0.1,     0.5,    1.0,
3930              1.0,       0.0,       0.1,     0.5,    1.0,
3931              1.0,       1.0,       0.1,     0.5,    1.0,
3932         };
3933         float quad4[] = {
3934              0.0,      -1.0,       0.1,     0.8,    0.2,
3935              0.0,       0.0,       0.1,     0.8,    0.2,
3936              1.0,      -1.0,       0.1,     0.8,    0.2,
3937              1.0,       0.0,       0.1,     0.8,    0.2,
3938         };
3939         float mat[16] = {0.0, 0.0, 0.0, 0.0,
3940                           0.0, 0.0, 0.0, 0.0,
3941                           0.0, 1.0, 0.0, 0.0,
3942                           0.0, 0.0, 0.0, 0.0};
3943
3944         /* What happens to the default 1 in the 3rd coordinate if it is disabled?
3945          */
3946         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3947         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3948         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3949         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3950
3951         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
3952         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3953
3954         /* D3DTFF_COUNT1 does not work on Nvidia drivers. It behaves like D3DTTFF_DISABLE. On ATI drivers
3955          * it behaves like COUNT2 because normal textures require 2 coords
3956          */
3957         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
3958         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3959         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 5 * sizeof(float));
3960         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3961
3962         /* Just to be sure, the same as quad2 above */
3963         memset(mat, 0, sizeof(mat));
3964         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3965         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
3966         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3967         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3968         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
3969         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3970
3971         /* Now, what happens to the 2nd coordinate(that is disabled in the matrix) if it is not
3972          * used? And what happens to the first?
3973          */
3974         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
3975         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3976         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
3977         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3978
3979         hr = IDirect3DDevice9_EndScene(device);
3980         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
3981     }
3982     color = getPixelColor(device, 160, 360);
3983     ok(color_match(color, 0x00FF0000, 1), "quad 1 has color %08x, expected 0x00FF0000\n", color);
3984     color = getPixelColor(device, 160, 120);
3985     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
3986     color = getPixelColor(device, 480, 120);
3987     ok(color_match(color, 0x00ff8000, 1) || color == 0x00000000,
3988        "quad 3 has color %08x, expected 0x00ff8000\n", color);
3989     color = getPixelColor(device, 480, 360);
3990     ok(color_match(color, 0x0033cc00, 1) || color_match(color, 0x00FF0000, 1),
3991        "quad 4 has color %08x, expected 0x0033cc00\n", color);
3992     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3993     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
3994
3995     IDirect3DTexture9_Release(texture);
3996
3997     /* Test projected textures, without any fancy matrices */
3998     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff203040, 0.0, 0);
3999     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4000     hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_L8, D3DPOOL_MANAGED, &texture, NULL);
4001     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
4002     hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &identity);
4003     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
4004     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl3);
4005     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
4006
4007     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
4008     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %08x\n", hr);
4009     for(x = 0; x < 4; x++) {
4010         memcpy(((BYTE *) lr.pBits) + lr.Pitch * x, proj_texdata + 4 * x, 4 * sizeof(proj_texdata[0]));
4011     }
4012     hr = IDirect3DTexture9_UnlockRect(texture, 0);
4013     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %08x\n", hr);
4014     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
4015     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
4016
4017     hr = IDirect3DDevice9_BeginScene(device);
4018     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
4019     if(SUCCEEDED(hr))
4020     {
4021         const float proj_quads[] = {
4022            -1.0,   -1.0,    0.1,    0.0,    0.0,    4.0,    6.0,
4023             1.0,   -1.0,    0.1,    4.0,    0.0,    4.0,    6.0,
4024            -1.0,    0.0,    0.1,    0.0,    4.0,    4.0,    6.0,
4025             1.0,    0.0,    0.1,    4.0,    4.0,    4.0,    6.0,
4026            -1.0,    0.0,    0.1,    0.0,    0.0,    4.0,    6.0,
4027             1.0,    0.0,    0.1,    4.0,    0.0,    4.0,    6.0,
4028            -1.0,    1.0,    0.1,    0.0,    4.0,    4.0,    6.0,
4029             1.0,    1.0,    0.1,    4.0,    4.0,    4.0,    6.0,
4030         };
4031
4032         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4 | D3DTTFF_PROJECTED);
4033         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4034         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &proj_quads[0*7], 7 * sizeof(float));
4035         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
4036
4037         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3 | D3DTTFF_PROJECTED);
4038         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4039         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &proj_quads[4*7], 7 * sizeof(float));
4040         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
4041
4042         hr = IDirect3DDevice9_EndScene(device);
4043         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
4044     }
4045
4046     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4047     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
4048     IDirect3DTexture9_Release(texture);
4049
4050     color = getPixelColor(device, 158, 118);
4051     ok(color == 0x00000000, "proj: Pixel 158/118 has color 0x%08x, expected 0x00000000\n", color);
4052     color = getPixelColor(device, 162, 118);
4053     ok(color == 0x00000000, "proj: Pixel 162/118 has color 0x%08x, expected 0x00000000\n", color);
4054     color = getPixelColor(device, 158, 122);
4055     ok(color == 0x00000000, "proj: Pixel 158/122 has color 0x%08x, expected 0x00000000\n", color);
4056     color = getPixelColor(device, 162, 122);
4057     ok(color == 0x00FFFFFF, "proj: Pixel 162/122 has color 0x%08x, expected 0x00FFFFFF\n", color);
4058
4059     color = getPixelColor(device, 158, 178);
4060     ok(color == 0x00000000, "proj: Pixel 158/178 has color 0x%08x, expected 0x00000000\n", color);
4061     color = getPixelColor(device, 162, 178);
4062     ok(color == 0x00FFFFFF, "proj: Pixel 158/178 has color 0x%08x, expected 0x00FFFFFF\n", color);
4063     color = getPixelColor(device, 158, 182);
4064     ok(color == 0x00000000, "proj: Pixel 158/182 has color 0x%08x, expected 0x00000000\n", color);
4065     color = getPixelColor(device, 162, 182);
4066     ok(color == 0x00000000, "proj: Pixel 158/182 has color 0x%08x, expected 0x00000000\n", color);
4067
4068     color = getPixelColor(device, 318, 118);
4069     ok(color == 0x00000000, "proj: Pixel 318/118 has color 0x%08x, expected 0x00000000\n", color);
4070     color = getPixelColor(device, 322, 118);
4071     ok(color == 0x00000000, "proj: Pixel 322/118 has color 0x%08x, expected 0x00000000\n", color);
4072     color = getPixelColor(device, 318, 122);
4073     ok(color == 0x00FFFFFF, "proj: Pixel 318/122 has color 0x%08x, expected 0x00FFFFFF\n", color);
4074     color = getPixelColor(device, 322, 122);
4075     ok(color == 0x00000000, "proj: Pixel 322/122 has color 0x%08x, expected 0x00000000\n", color);
4076
4077     color = getPixelColor(device, 318, 178);
4078     ok(color == 0x00FFFFFF, "proj: Pixel 318/178 has color 0x%08x, expected 0x00FFFFFF\n", color);
4079     color = getPixelColor(device, 322, 178);
4080     ok(color == 0x00000000, "proj: Pixel 322/178 has color 0x%08x, expected 0x00000000\n", color);
4081     color = getPixelColor(device, 318, 182);
4082     ok(color == 0x00000000, "proj: Pixel 318/182 has color 0x%08x, expected 0x00000000\n", color);
4083     color = getPixelColor(device, 322, 182);
4084     ok(color == 0x00000000, "proj: Pixel 322/182 has color 0x%08x, expected 0x00000000\n", color);
4085
4086     color = getPixelColor(device, 238, 298);
4087     ok(color == 0x00000000, "proj: Pixel 238/298 has color 0x%08x, expected 0x00000000\n", color);
4088     color = getPixelColor(device, 242, 298);
4089     ok(color == 0x00000000, "proj: Pixel 242/298 has color 0x%08x, expected 0x00000000\n", color);
4090     color = getPixelColor(device, 238, 302);
4091     ok(color == 0x00000000, "proj: Pixel 238/302 has color 0x%08x, expected 0x00000000\n", color);
4092     color = getPixelColor(device, 242, 302);
4093     ok(color == 0x00FFFFFF, "proj: Pixel 242/302 has color 0x%08x, expected 0x00FFFFFF\n", color);
4094
4095     color = getPixelColor(device, 238, 388);
4096     ok(color == 0x00000000, "proj: Pixel 238/388 has color 0x%08x, expected 0x00000000\n", color);
4097     color = getPixelColor(device, 242, 388);
4098     ok(color == 0x00FFFFFF, "proj: Pixel 242/388 has color 0x%08x, expected 0x00FFFFFF\n", color);
4099     color = getPixelColor(device, 238, 392);
4100     ok(color == 0x00000000, "proj: Pixel 238/392 has color 0x%08x, expected 0x00000000\n", color);
4101     color = getPixelColor(device, 242, 392);
4102     ok(color == 0x00000000, "proj: Pixel 242/392 has color 0x%08x, expected 0x00000000\n", color);
4103
4104     color = getPixelColor(device, 478, 298);
4105     ok(color == 0x00000000, "proj: Pixel 478/298 has color 0x%08x, expected 0x00000000\n", color);
4106     color = getPixelColor(device, 482, 298);
4107     ok(color == 0x00000000, "proj: Pixel 482/298 has color 0x%08x, expected 0x00000000\n", color);
4108     color = getPixelColor(device, 478, 302);
4109     ok(color == 0x00FFFFFF, "proj: Pixel 478/302 has color 0x%08x, expected 0x00FFFFFF\n", color);
4110     color = getPixelColor(device, 482, 302);
4111     ok(color == 0x00000000, "proj: Pixel 482/302 has color 0x%08x, expected 0x00000000\n", color);
4112
4113     color = getPixelColor(device, 478, 388);
4114     ok(color == 0x00FFFFFF, "proj: Pixel 478/388 has color 0x%08x, expected 0x00FFFFFF\n", color);
4115     color = getPixelColor(device, 482, 388);
4116     ok(color == 0x00000000, "proj: Pixel 482/388 has color 0x%08x, expected 0x00000000\n", color);
4117     color = getPixelColor(device, 478, 392);
4118     ok(color == 0x00000000, "proj: Pixel 478/392 has color 0x%08x, expected 0x00000000\n", color);
4119     color = getPixelColor(device, 482, 392);
4120     ok(color == 0x00000000, "proj: Pixel 482/392 has color 0x%08x, expected 0x00000000\n", color);
4121
4122     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4123     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4124
4125     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff203040, 0.0, 0);
4126     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4127     /* Use a smaller volume texture than the biggest possible size for memory and performance reasons
4128      * Thus watch out if sampling from texels between 0 and 1.
4129      */
4130     hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 32, 1, 0, fmt, D3DPOOL_MANAGED, &volume, 0);
4131     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
4132        "IDirect3DDevice9_CreateVolumeTexture failed with %08x\n", hr);
4133     if(!volume) {
4134         skip("Failed to create a volume texture\n");
4135         goto out;
4136     }
4137
4138     hr = IDirect3DVolumeTexture9_LockBox(volume, 0, &lb, NULL, 0);
4139     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_LockBox failed with %08x\n", hr);
4140     for(z = 0; z < 32; z++) {
4141         for(y = 0; y < 32; y++) {
4142             for(x = 0; x < 32; x++) {
4143                 char size = (fmt == D3DFMT_A16B16G16R16 ? 8 : 4);
4144                 void *mem = ((char *)  lb.pBits) + y * lb.RowPitch + z * lb.SlicePitch + x * size;
4145                 float r_f = (float) x / 31.0;
4146                 float g_f = (float) y / 31.0;
4147                 float b_f = (float) z / 31.0;
4148
4149                 if(fmt == D3DFMT_A16B16G16R16) {
4150                     unsigned short *mem_s = mem;
4151                     mem_s[0]  = r_f * 65535.0;
4152                     mem_s[1]  = g_f * 65535.0;
4153                     mem_s[2]  = b_f * 65535.0;
4154                     mem_s[3]  = 65535;
4155                 } else {
4156                     unsigned char *mem_c = mem;
4157                     mem_c[0]  = b_f * 255.0;
4158                     mem_c[1]  = g_f * 255.0;
4159                     mem_c[2]  = r_f * 255.0;
4160                     mem_c[3]  = 255;
4161                 }
4162             }
4163         }
4164     }
4165     hr = IDirect3DVolumeTexture9_UnlockBox(volume, 0);
4166     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %08x\n", hr);
4167
4168     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) volume);
4169     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %08x\n", hr);
4170
4171     hr = IDirect3DDevice9_BeginScene(device);
4172     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
4173     if(SUCCEEDED(hr))
4174     {
4175         float quad1[] = {
4176             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
4177             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
4178              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
4179              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
4180         };
4181         float quad2[] = {
4182             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
4183             -1.0,       1.0,       0.1,     1.0,    1.0,    1.0,
4184              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
4185              0.0,       1.0,       0.1,     1.0,    1.0,    1.0
4186         };
4187         float quad3[] = {
4188              0.0,       0.0,       0.1,     0.0,    0.0,
4189              0.0,       1.0,       0.1,     0.0,    0.0,
4190              1.0,       0.0,       0.1,     0.0,    0.0,
4191              1.0,       1.0,       0.1,     0.0,    0.0
4192         };
4193         float quad4[] = {
4194              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
4195              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
4196              1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
4197              1.0,       0.0,       0.1,     1.0,    1.0,    1.0
4198         };
4199         float mat[16] = {1.0, 0.0, 0.0, 0.0,
4200                          0.0, 0.0, 1.0, 0.0,
4201                          0.0, 1.0, 0.0, 0.0,
4202                          0.0, 0.0, 0.0, 1.0};
4203         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
4204         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
4205
4206         /* Draw a quad with all 3 coords enabled. Nothing fancy. v and w are swapped, but have the same
4207          * values
4208          */
4209         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
4210         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
4211         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
4212         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4213         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
4214         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4215
4216         /* Now disable the w coordinate. Does that change the input, or the output. The coordinates
4217          * are swapped by the matrix. If it changes the input, the v coord will be missing(green),
4218          * otherwise the w will be missing(blue).
4219          * turns out that on nvidia cards the blue color is missing, so it is an output modification.
4220          * On ATI cards the COUNT2 is ignored, and it behaves in the same way as COUNT3.
4221          */
4222         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
4223         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4224         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
4225         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4226
4227         /* default values? Set up the identity matrix, pass in 2 vertex coords, and enable 3 */
4228         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
4229         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
4230         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
4231         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4232         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4233         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
4234         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
4235         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4236
4237         /* D3DTTFF_COUNT1. Set a NULL matrix, and count1, pass in all values as 1.0. Nvidia has count1 ==
4238          * disable. ATI extends it up to the amount of values needed for the volume texture
4239          */
4240         memset(mat, 0, sizeof(mat));
4241         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
4242         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
4243         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
4244         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4245         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
4246         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
4247         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
4248         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4249
4250         hr = IDirect3DDevice9_EndScene(device);
4251         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
4252     }
4253
4254     color = getPixelColor(device, 160, 360);
4255     ok(color == 0x00ffffff, "quad 1 has color %08x, expected 0x00ffffff\n", color);
4256     color = getPixelColor(device, 160, 120);
4257     ok(color == 0x00ffff00 /* NV*/ || color == 0x00ffffff /* ATI */,
4258        "quad 2 has color %08x, expected 0x00ffff00\n", color);
4259     color = getPixelColor(device, 480, 120);
4260     ok(color == 0x000000ff, "quad 3 has color %08x, expected 0x000000ff\n", color);
4261     color = getPixelColor(device, 480, 360);
4262     ok(color == 0x00ffffff || color == 0x0000ff00, "quad 4 has color %08x, expected 0x00ffffff\n", color);
4263
4264     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4265     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4266
4267     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff303030, 0.0, 0);
4268     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4269     hr = IDirect3DDevice9_BeginScene(device);
4270     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
4271     if(SUCCEEDED(hr))
4272     {
4273         float quad1[] = {
4274             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
4275             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
4276              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
4277              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
4278         };
4279         float quad2[] = {
4280             -1.0,       0.0,       0.1,
4281             -1.0,       1.0,       0.1,
4282              0.0,       0.0,       0.1,
4283              0.0,       1.0,       0.1,
4284         };
4285         float quad3[] = {
4286              0.0,       0.0,       0.1,     1.0,
4287              0.0,       1.0,       0.1,     1.0,
4288              1.0,       0.0,       0.1,     1.0,
4289              1.0,       1.0,       0.1,     1.0
4290         };
4291         float mat[16] =  {0.0, 0.0, 0.0, 0.0,
4292                            0.0, 0.0, 0.0, 0.0,
4293                            0.0, 0.0, 0.0, 0.0,
4294                            0.0, 1.0, 0.0, 0.0};
4295         float mat2[16] = {0.0, 0.0, 0.0, 1.0,
4296                            1.0, 0.0, 0.0, 0.0,
4297                            0.0, 1.0, 0.0, 0.0,
4298                            0.0, 0.0, 1.0, 0.0};
4299         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
4300         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
4301
4302         /* Default values? 4 coords used, 3 passed. What happens to the 4th?
4303          * Use COUNT3 because newer Nvidia drivers return black when there are more (output) coords
4304          * than being used by the texture(volume tex -> 3). Again, as shown in earlier test the COUNTx
4305          * affects the post-transformation output, so COUNT3 plus the matrix above is OK for testing the
4306          * 4th *input* coordinate.
4307          */
4308         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
4309         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
4310         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
4311         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4312         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
4313         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4314
4315         /* None passed */
4316         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
4317         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
4318         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4319         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
4320         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
4321         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4322
4323         /* 4 used, 1 passed */
4324         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl2);
4325         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
4326         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat2);
4327         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
4328         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 4 * sizeof(float));
4329         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4330
4331         hr = IDirect3DDevice9_EndScene(device);
4332         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
4333     }
4334     color = getPixelColor(device, 160, 360);
4335     ok(color == 0x0000ff00, "quad 1 has color %08x, expected 0x0000ff00\n", color);
4336     color = getPixelColor(device, 160, 120);
4337     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x00000000\n", color);
4338     color = getPixelColor(device, 480, 120);
4339     ok(color == 0x00ff0000, "quad 3 has color %08x, expected 0x00ff0000\n", color);
4340     /* Quad4: unused */
4341
4342     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4343     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4344
4345     IDirect3DVolumeTexture9_Release(volume);
4346
4347     out:
4348     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
4349     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
4350     IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
4351     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
4352     hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &identity);
4353     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %08x\n", hr);
4354     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4355     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
4356     IDirect3DVertexDeclaration9_Release(decl);
4357     IDirect3DVertexDeclaration9_Release(decl2);
4358     IDirect3DVertexDeclaration9_Release(decl3);
4359 }
4360
4361 static void texdepth_test(IDirect3DDevice9 *device)
4362 {
4363     IDirect3DPixelShader9 *shader;
4364     HRESULT hr;
4365     const float texdepth_test_data1[] = { 0.25,  2.0, 0.0, 0.0};
4366     const float texdepth_test_data2[] = { 0.25,  0.5, 0.0, 0.0};
4367     const float texdepth_test_data3[] = {-1.00,  0.1, 0.0, 0.0};
4368     const float texdepth_test_data4[] = {-0.25, -0.5, 0.0, 0.0};
4369     const float texdepth_test_data5[] = { 1.00, -0.1, 0.0, 0.0};
4370     const float texdepth_test_data6[] = { 1.00,  0.5, 0.0, 0.0};
4371     const float texdepth_test_data7[] = { 0.50,  0.0, 0.0, 0.0};
4372     DWORD shader_code[] = {
4373         0xffff0104,                                                                 /* ps_1_4               */
4374         0x00000051, 0xa00f0001, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000,     /* def c1, 0, 0, 1, 1   */
4375         0x00000001, 0x800f0005, 0xa0e40000,                                         /* mov r5, c0           */
4376         0x0000fffd,                                                                 /* phase                */
4377         0x00000057, 0x800f0005,                                                     /* texdepth r5          */
4378         0x00000001, 0x800f0000, 0xa0e40001,                                         /* mov r0, c1           */
4379         0x0000ffff                                                                  /* end                  */
4380     };
4381     DWORD color;
4382     float vertex[] = {
4383        -1.0,   -1.0,    0.0,
4384         1.0,   -1.0,    1.0,
4385        -1.0,    1.0,    0.0,
4386         1.0,    1.0,    1.0
4387     };
4388
4389     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
4390     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4391
4392     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffff00, 0.0, 0);
4393     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4394     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
4395     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
4396     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
4397     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
4398     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
4399     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
4400     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4401     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetFVF returned %#x.\n", hr);
4402
4403     /* Fill the depth buffer with a gradient */
4404     hr = IDirect3DDevice9_BeginScene(device);
4405     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4406     if(SUCCEEDED(hr))
4407     {
4408         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4409         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4410         hr = IDirect3DDevice9_EndScene(device);
4411         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4412     }
4413
4414     /* Now perform the actual tests. Same geometry, but with the shader */
4415     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
4416     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
4417     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
4418     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
4419     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4420     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4421
4422     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data1, 1);
4423     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4424     hr = IDirect3DDevice9_BeginScene(device);
4425     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4426     if(SUCCEEDED(hr))
4427     {
4428         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4429         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4430
4431         hr = IDirect3DDevice9_EndScene(device);
4432         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4433     }
4434
4435     color = getPixelColor(device, 158, 240);
4436     ok(color == 0x000000ff, "Pixel 158(25%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
4437     color = getPixelColor(device, 162, 240);
4438     ok(color == 0x00ffffff, "Pixel 158(25%% + 2 pixel) has color %08x, expected 0x00ffffff\n", color);
4439
4440     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4441     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4442
4443     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
4444     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
4445
4446     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data2, 1);
4447     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4448     hr = IDirect3DDevice9_BeginScene(device);
4449     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4450     if(SUCCEEDED(hr))
4451     {
4452         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4453         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4454
4455         hr = IDirect3DDevice9_EndScene(device);
4456         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4457     }
4458
4459     color = getPixelColor(device, 318, 240);
4460     ok(color == 0x000000ff, "Pixel 318(50%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
4461     color = getPixelColor(device, 322, 240);
4462     ok(color == 0x00ffff00, "Pixel 322(50%% + 2 pixel) has color %08x, expected 0x00ffff00\n", color);
4463
4464     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4465     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4466
4467     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
4468     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
4469
4470     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data3, 1);
4471     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4472     hr = IDirect3DDevice9_BeginScene(device);
4473     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4474     if(SUCCEEDED(hr))
4475     {
4476         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4477         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4478
4479         hr = IDirect3DDevice9_EndScene(device);
4480         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4481     }
4482
4483     color = getPixelColor(device, 1, 240);
4484     ok(color == 0x00ff0000, "Pixel 1(0%% + 2 pixel) has color %08x, expected 0x00ff0000\n", color);
4485
4486     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4487     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4488
4489     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
4490     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
4491
4492     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data4, 1);
4493     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4494     hr = IDirect3DDevice9_BeginScene(device);
4495     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4496     if(SUCCEEDED(hr))
4497     {
4498         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4499         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4500
4501         hr = IDirect3DDevice9_EndScene(device);
4502         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4503     }
4504     color = getPixelColor(device, 318, 240);
4505     ok(color == 0x000000ff, "Pixel 318(50%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
4506     color = getPixelColor(device, 322, 240);
4507     ok(color == 0x0000ff00, "Pixel 322(50%% + 2 pixel) has color %08x, expected 0x0000ff00\n", color);
4508
4509     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4510     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4511
4512     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
4513     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
4514
4515     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data5, 1);
4516     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4517     hr = IDirect3DDevice9_BeginScene(device);
4518     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4519     if(SUCCEEDED(hr))
4520     {
4521         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4522         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4523
4524         hr = IDirect3DDevice9_EndScene(device);
4525         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4526     }
4527
4528     color = getPixelColor(device, 1, 240);
4529     ok(color == 0x00ffff00, "Pixel 1(0%% + 2 pixel) has color %08x, expected 0x00ffff00\n", color);
4530
4531     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4532     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4533
4534     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
4535     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
4536
4537     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data6, 1);
4538     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4539     hr = IDirect3DDevice9_BeginScene(device);
4540     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4541     if(SUCCEEDED(hr))
4542     {
4543         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4544         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4545
4546         hr = IDirect3DDevice9_EndScene(device);
4547         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4548     }
4549
4550     color = getPixelColor(device, 638, 240);
4551     ok(color == 0x000000ff, "Pixel 638(100%% + 2 pixel) has color %08x, expected 0x000000ff\n", color);
4552
4553     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4554     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4555
4556     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
4557     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
4558
4559     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data7, 1);
4560     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
4561     hr = IDirect3DDevice9_BeginScene(device);
4562     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4563     if(SUCCEEDED(hr))
4564     {
4565         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
4566         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4567
4568         hr = IDirect3DDevice9_EndScene(device);
4569         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4570     }
4571
4572     color = getPixelColor(device, 638, 240);
4573     ok(color == 0x000000ff, "Pixel 638(100%% + 2 pixel) has color %08x, expected 0x000000ff\n", color);
4574
4575     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4576     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4577
4578     /* Cleanup */
4579     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4580     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4581     IDirect3DPixelShader9_Release(shader);
4582
4583     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
4584     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
4585     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
4586     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
4587 }
4588
4589 static void texkill_test(IDirect3DDevice9 *device)
4590 {
4591     IDirect3DPixelShader9 *shader;
4592     HRESULT hr;
4593     DWORD color;
4594
4595     const float vertex[] = {
4596     /*                          bottom  top    right    left */
4597         -1.0,   -1.0,   1.0,   -0.1,    0.9,    0.9,   -0.1,
4598          1.0,   -1.0,   0.0,    0.9,   -0.1,    0.9,   -0.1,
4599         -1.0,    1.0,   1.0,   -0.1,    0.9,   -0.1,    0.9,
4600          1.0,    1.0,   0.0,    0.9,   -0.1,   -0.1,    0.9,
4601     };
4602
4603     DWORD shader_code_11[] = {
4604     0xffff0101,                                                             /* ps_1_1                     */
4605     0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0 */
4606     0x00000041, 0xb00f0000,                                                 /* texkill t0                 */
4607     0x00000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                 */
4608     0x0000ffff                                                              /* end                        */
4609     };
4610     DWORD shader_code_20[] = {
4611     0xffff0200,                                                             /* ps_2_0                     */
4612     0x0200001f, 0x80000000, 0xb00f0000,                                     /* dcl t0                     */
4613     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c0, 0.0, 0.0, 1.0, 1.0 */
4614     0x01000041, 0xb00f0000,                                                 /* texkill t0                 */
4615     0x02000001, 0x800f0800, 0xa0e40000,                                     /* mov oC0, c0                */
4616     0x0000ffff                                                              /* end                        */
4617     };
4618
4619     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
4620     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4621     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader);
4622     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4623
4624     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4625     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4626     hr = IDirect3DDevice9_BeginScene(device);
4627     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4628     if(SUCCEEDED(hr))
4629     {
4630         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1);
4631         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
4632         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 7 * sizeof(float));
4633         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4634         hr = IDirect3DDevice9_EndScene(device);
4635         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4636     }
4637     color = getPixelColor(device, 63, 46);
4638     ok(color == 0x0000ff00, "Pixel 63/46 has color %08x, expected 0x0000ff00\n", color);
4639     color = getPixelColor(device, 66, 46);
4640     ok(color == 0x0000ff00, "Pixel 66/64 has color %08x, expected 0x0000ff00\n", color);
4641     color = getPixelColor(device, 63, 49);
4642     ok(color == 0x0000ff00, "Pixel 63/49 has color %08x, expected 0x0000ff00\n", color);
4643     color = getPixelColor(device, 66, 49);
4644     ok(color == 0x00ff0000, "Pixel 66/49 has color %08x, expected 0x00ff0000\n", color);
4645
4646     color = getPixelColor(device, 578, 46);
4647     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
4648     color = getPixelColor(device, 575, 46);
4649     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
4650     color = getPixelColor(device, 578, 49);
4651     ok(color == 0x0000ff00, "Pixel 578/49 has color %08x, expected 0x0000ff00\n", color);
4652     color = getPixelColor(device, 575, 49);
4653     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
4654
4655     color = getPixelColor(device, 63, 430);
4656     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
4657     color = getPixelColor(device, 63, 433);
4658     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
4659     color = getPixelColor(device, 66, 433);
4660     ok(color == 0x00ff0000, "Pixel 578/49 has color %08x, expected 0x00ff0000\n", color);
4661     color = getPixelColor(device, 66, 430);
4662     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
4663
4664     color = getPixelColor(device, 578, 430);
4665     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
4666     color = getPixelColor(device, 578, 433);
4667     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
4668     color = getPixelColor(device, 575, 433);
4669     ok(color == 0x00ff0000, "Pixel 578/49 has color %08x, expected 0x00ff0000\n", color);
4670     color = getPixelColor(device, 575, 430);
4671     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
4672
4673     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4674     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4675
4676     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4677     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4678     IDirect3DPixelShader9_Release(shader);
4679
4680     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
4681     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
4682     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_20, &shader);
4683     if(FAILED(hr)) {
4684         skip("Failed to create 2.0 test shader, most likely not supported\n");
4685         return;
4686     }
4687
4688     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4689     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
4690     hr = IDirect3DDevice9_BeginScene(device);
4691     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4692     if(SUCCEEDED(hr))
4693     {
4694         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 7 * sizeof(float));
4695         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4696         hr = IDirect3DDevice9_EndScene(device);
4697         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4698     }
4699
4700     color = getPixelColor(device, 63, 46);
4701     ok(color == 0x00ffff00, "Pixel 63/46 has color %08x, expected 0x00ffff00\n", color);
4702     color = getPixelColor(device, 66, 46);
4703     ok(color == 0x00ffff00, "Pixel 66/64 has color %08x, expected 0x00ffff00\n", color);
4704     color = getPixelColor(device, 63, 49);
4705     ok(color == 0x00ffff00, "Pixel 63/49 has color %08x, expected 0x00ffff00\n", color);
4706     color = getPixelColor(device, 66, 49);
4707     ok(color == 0x000000ff, "Pixel 66/49 has color %08x, expected 0x000000ff\n", color);
4708
4709     color = getPixelColor(device, 578, 46);
4710     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
4711     color = getPixelColor(device, 575, 46);
4712     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
4713     color = getPixelColor(device, 578, 49);
4714     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
4715     color = getPixelColor(device, 575, 49);
4716     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
4717
4718     color = getPixelColor(device, 63, 430);
4719     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
4720     color = getPixelColor(device, 63, 433);
4721     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
4722     color = getPixelColor(device, 66, 433);
4723     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
4724     color = getPixelColor(device, 66, 430);
4725     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
4726
4727     color = getPixelColor(device, 578, 430);
4728     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
4729     color = getPixelColor(device, 578, 433);
4730     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
4731     color = getPixelColor(device, 575, 433);
4732     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
4733     color = getPixelColor(device, 575, 430);
4734     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
4735
4736     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4737     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4738
4739     /* Cleanup */
4740     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4741     ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
4742     IDirect3DPixelShader9_Release(shader);
4743 }
4744
4745 static void x8l8v8u8_test(IDirect3DDevice9 *device)
4746 {
4747     IDirect3D9 *d3d9;
4748     HRESULT hr;
4749     IDirect3DTexture9 *texture;
4750     IDirect3DPixelShader9 *shader;
4751     IDirect3DPixelShader9 *shader2;
4752     D3DLOCKED_RECT lr;
4753     DWORD color;
4754     DWORD shader_code[] = {
4755         0xffff0101,                             /* ps_1_1       */
4756         0x00000042, 0xb00f0000,                 /* tex t0       */
4757         0x00000001, 0x800f0000, 0xb0e40000,     /* mov r0, t0   */
4758         0x0000ffff                              /* end          */
4759     };
4760     DWORD shader_code2[] = {
4761         0xffff0101,                             /* ps_1_1       */
4762         0x00000042, 0xb00f0000,                 /* tex t0       */
4763         0x00000001, 0x800f0000, 0xb0ff0000,     /* mov r0, t0.w */
4764         0x0000ffff                              /* end          */
4765     };
4766
4767     float quad[] = {
4768        -1.0,   -1.0,   0.1,     0.5,    0.5,
4769         1.0,   -1.0,   0.1,     0.5,    0.5,
4770        -1.0,    1.0,   0.1,     0.5,    0.5,
4771         1.0,    1.0,   0.1,     0.5,    0.5,
4772     };
4773
4774     memset(&lr, 0, sizeof(lr));
4775     IDirect3DDevice9_GetDirect3D(device, &d3d9);
4776     hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4777                                       0,  D3DRTYPE_TEXTURE, D3DFMT_X8L8V8U8);
4778     IDirect3D9_Release(d3d9);
4779     if(FAILED(hr)) {
4780         skip("No D3DFMT_X8L8V8U8 support\n");
4781         return;
4782     };
4783
4784     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
4785     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4786
4787     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_X8L8V8U8, D3DPOOL_MANAGED, &texture, NULL);
4788     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed (%08x)\n", hr);
4789     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
4790     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed (%08x)\n", hr);
4791     *((DWORD *) lr.pBits) = 0x11ca3141;
4792     hr = IDirect3DTexture9_UnlockRect(texture, 0);
4793     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed (%08x)\n", hr);
4794
4795     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
4796     ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr);
4797     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code2, &shader2);
4798     ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr);
4799
4800     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4801     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed (%08x)\n", hr);
4802     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4803     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4804     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
4805     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
4806
4807     hr = IDirect3DDevice9_BeginScene(device);
4808     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4809     if(SUCCEEDED(hr))
4810     {
4811         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
4812         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4813
4814         hr = IDirect3DDevice9_EndScene(device);
4815         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4816     }
4817     color = getPixelColor(device, 578, 430);
4818     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x82, 0x62, 0xca), 1),
4819        "D3DFMT_X8L8V8U8 = 0x112131ca returns color %08x, expected 0x008262ca\n", color);
4820     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4821     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4822
4823     hr = IDirect3DDevice9_SetPixelShader(device, shader2);
4824     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4825     hr = IDirect3DDevice9_BeginScene(device);
4826     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4827     if(SUCCEEDED(hr))
4828     {
4829         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
4830         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4831
4832         hr = IDirect3DDevice9_EndScene(device);
4833         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4834     }
4835     color = getPixelColor(device, 578, 430);
4836     ok(color == 0x00ffffff, "w component of D3DFMT_X8L8V8U8 = 0x11ca3141 returns color %08x\n", color);
4837     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4838     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4839
4840     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4841     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4842     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4843     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
4844     IDirect3DPixelShader9_Release(shader);
4845     IDirect3DPixelShader9_Release(shader2);
4846     IDirect3DTexture9_Release(texture);
4847 }
4848
4849 static void autogen_mipmap_test(IDirect3DDevice9 *device)
4850 {
4851     HRESULT hr;
4852     IDirect3D9 *d3d;
4853     IDirect3DTexture9 *texture = NULL;
4854     IDirect3DSurface9 *surface;
4855     DWORD color;
4856     const RECT r1 = {256, 256, 512, 512};
4857     const RECT r2 = {512, 256, 768, 512};
4858     const RECT r3 = {256, 512, 512, 768};
4859     const RECT r4 = {512, 512, 768, 768};
4860     unsigned int x, y;
4861     D3DLOCKED_RECT lr;
4862     memset(&lr, 0, sizeof(lr));
4863
4864     IDirect3DDevice9_GetDirect3D(device, &d3d);
4865     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4866        D3DUSAGE_AUTOGENMIPMAP,  D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8) != D3D_OK) {
4867         skip("No autogenmipmap support\n");
4868         IDirect3D9_Release(d3d);
4869         return;
4870     }
4871     IDirect3D9_Release(d3d);
4872
4873     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
4874     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
4875
4876     /* Make the mipmap big, so that a smaller mipmap is used
4877      */
4878     hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 0, D3DUSAGE_AUTOGENMIPMAP,
4879                                         D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4880     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %08x\n", hr);
4881
4882     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
4883     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel returned %08x\n", hr);
4884     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
4885     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %08x\n", hr);
4886     for(y = 0; y < 1024; y++) {
4887         for(x = 0; x < 1024; x++) {
4888             DWORD *dst = (DWORD *) (((BYTE *) lr.pBits) + y * lr.Pitch + x * 4);
4889             POINT pt;
4890
4891             pt.x = x;
4892             pt.y = y;
4893             if(PtInRect(&r1, pt)) {
4894                 *dst = 0xffff0000;
4895             } else if(PtInRect(&r2, pt)) {
4896                 *dst = 0xff00ff00;
4897             } else if(PtInRect(&r3, pt)) {
4898                 *dst = 0xff0000ff;
4899             } else if(PtInRect(&r4, pt)) {
4900                 *dst = 0xff000000;
4901             } else {
4902                 *dst = 0xffffffff;
4903             }
4904         }
4905     }
4906     hr = IDirect3DSurface9_UnlockRect(surface);
4907     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect returned %08x\n", hr);
4908     IDirect3DSurface9_Release(surface);
4909
4910     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
4911     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
4912     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
4913     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
4914
4915     hr = IDirect3DDevice9_BeginScene(device);
4916     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
4917     if(SUCCEEDED(hr)) {
4918         const float quad[] =  {
4919            -0.5,   -0.5,    0.1,    0.0,    0.0,
4920            -0.5,    0.5,    0.1,    0.0,    1.0,
4921             0.5,   -0.5,    0.1,    1.0,    0.0,
4922             0.5,    0.5,    0.1,    1.0,    1.0
4923         };
4924
4925         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4926         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
4927         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
4928         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4929         hr = IDirect3DDevice9_EndScene(device);
4930         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
4931     }
4932     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4933     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %08x\n", hr);
4934     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
4935     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
4936     IDirect3DTexture9_Release(texture);
4937
4938     color = getPixelColor(device, 200, 200);
4939     ok(color == 0x00ffffff, "pixel 200/200 has color %08x, expected 0x00ffffff\n", color);
4940     color = getPixelColor(device, 280, 200);
4941     ok(color == 0x000000ff, "pixel 280/200 has color %08x, expected 0x000000ff\n", color);
4942     color = getPixelColor(device, 360, 200);
4943     ok(color == 0x00000000, "pixel 360/200 has color %08x, expected 0x00000000\n", color);
4944     color = getPixelColor(device, 440, 200);
4945     ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
4946     color = getPixelColor(device, 200, 270);
4947     ok(color == 0x00ffffff, "pixel 200/270 has color %08x, expected 0x00ffffff\n", color);
4948     color = getPixelColor(device, 280, 270);
4949     ok(color == 0x00ff0000, "pixel 280/270 has color %08x, expected 0x00ff0000\n", color);
4950     color = getPixelColor(device, 360, 270);
4951     ok(color == 0x0000ff00, "pixel 360/270 has color %08x, expected 0x0000ff00\n", color);
4952     color = getPixelColor(device, 440, 270);
4953     ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
4954     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4955     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
4956 }
4957
4958 static void test_constant_clamp_vs(IDirect3DDevice9 *device)
4959 {
4960     IDirect3DVertexShader9 *shader_11, *shader_11_2, *shader_20, *shader_20_2;
4961     IDirect3DVertexDeclaration9 *decl;
4962     HRESULT hr;
4963     DWORD color;
4964     DWORD shader_code_11[] =  {
4965         0xfffe0101,                                         /* vs_1_1           */
4966         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4967         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4968         0x00000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4969         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4970         0x0000ffff                                          /* end              */
4971     };
4972     DWORD shader_code_11_2[] =  {
4973         0xfffe0101,                                         /* vs_1_1           */
4974         0x00000051, 0xa00f0001, 0x3fa00000, 0xbf000000, 0xbfc00000, 0x3f800000, /* dcl ... */
4975         0x00000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000, /* dcl ... */
4976         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4977         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4978         0x00000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4979         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4980         0x0000ffff                                          /* end              */
4981     };
4982     DWORD shader_code_20[] =  {
4983         0xfffe0200,                                         /* vs_2_0           */
4984         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4985         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4986         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4987         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4988         0x0000ffff                                          /* end              */
4989     };
4990     DWORD shader_code_20_2[] =  {
4991         0xfffe0200,                                         /* vs_2_0           */
4992         0x05000051, 0xa00f0001, 0x3fa00000, 0xbf000000, 0xbfc00000, 0x3f800000,
4993         0x05000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000,
4994         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4995         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4996         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4997         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4998         0x0000ffff                                          /* end              */
4999     };
5000     static const D3DVERTEXELEMENT9 decl_elements[] = {
5001         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
5002         D3DDECL_END()
5003     };
5004     float quad1[] = {
5005         -1.0,   -1.0,   0.1,
5006          0.0,   -1.0,   0.1,
5007         -1.0,    0.0,   0.1,
5008          0.0,    0.0,   0.1
5009     };
5010     float quad2[] = {
5011          0.0,   -1.0,   0.1,
5012          1.0,   -1.0,   0.1,
5013          0.0,    0.0,   0.1,
5014          1.0,    0.0,   0.1
5015     };
5016     float quad3[] = {
5017          0.0,    0.0,   0.1,
5018          1.0,    0.0,   0.1,
5019          0.0,    1.0,   0.1,
5020          1.0,    1.0,   0.1
5021     };
5022     float quad4[] = {
5023         -1.0,    0.0,   0.1,
5024          0.0,    0.0,   0.1,
5025         -1.0,    1.0,   0.1,
5026          0.0,    1.0,   0.1
5027     };
5028     float test_data_c1[4] = {  1.25, -0.50, -1.50, 1.0};
5029     float test_data_c2[4] = { -0.50,  1.25,  2.00, 1.0};
5030
5031     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
5032     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5033
5034     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_11, &shader_11);
5035     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5036     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_11_2, &shader_11_2);
5037     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
5038     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_20, &shader_20);
5039     if(FAILED(hr)) shader_20 = NULL;
5040     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_20_2, &shader_20_2);
5041     if(FAILED(hr)) shader_20_2 = NULL;
5042     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
5043     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
5044
5045     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, test_data_c1, 1);
5046     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned %08x\n", hr);
5047     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 2, test_data_c2, 1);
5048     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned %08x\n", hr);
5049     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
5050     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
5051
5052     hr = IDirect3DDevice9_BeginScene(device);
5053     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5054     if(SUCCEEDED(hr))
5055     {
5056         hr = IDirect3DDevice9_SetVertexShader(device, shader_11);
5057         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5058         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 3 * sizeof(float));
5059         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5060
5061         hr = IDirect3DDevice9_SetVertexShader(device, shader_11_2);
5062         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5063         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
5064         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5065
5066         if(shader_20) {
5067             hr = IDirect3DDevice9_SetVertexShader(device, shader_20);
5068             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5069             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 3 * sizeof(float));
5070             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5071         }
5072
5073         if(shader_20_2) {
5074             hr = IDirect3DDevice9_SetVertexShader(device, shader_20_2);
5075             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5076             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 3 * sizeof(float));
5077             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5078         }
5079
5080         hr = IDirect3DDevice9_EndScene(device);
5081         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5082     }
5083
5084     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
5085     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5086     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
5087     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
5088
5089     color = getPixelColor(device, 160, 360);
5090     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0xbf, 0x80), 1),
5091        "quad 1 has color %08x, expected 0x00bfbf80\n", color);
5092     color = getPixelColor(device, 480, 360);
5093     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0xbf, 0x80), 1),
5094        "quad 2 has color %08x, expected 0x00bfbf80\n", color);
5095     if(shader_20) {
5096         color = getPixelColor(device, 480, 120);
5097         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0xbf, 0x80), 1),
5098            "quad 3 has color %08x, expected 0x00bfbf80\n", color);
5099     }
5100     if(shader_20_2) {
5101         color = getPixelColor(device, 160, 120);
5102         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0xbf, 0x80), 1),
5103            "quad 4 has color %08x, expected 0x00bfbf80\n", color);
5104     }
5105     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5106     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5107
5108     IDirect3DVertexDeclaration9_Release(decl);
5109     if(shader_20_2) IDirect3DVertexShader9_Release(shader_20_2);
5110     if(shader_20) IDirect3DVertexShader9_Release(shader_20);
5111     IDirect3DVertexShader9_Release(shader_11_2);
5112     IDirect3DVertexShader9_Release(shader_11);
5113 }
5114
5115 static void constant_clamp_ps_test(IDirect3DDevice9 *device)
5116 {
5117     IDirect3DPixelShader9 *shader_11, *shader_12, *shader_14, *shader_20;
5118     HRESULT hr;
5119     DWORD color;
5120     DWORD shader_code_11[] =  {
5121         0xffff0101,                                         /* ps_1_1           */
5122         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
5123         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
5124         0x0000ffff                                          /* end              */
5125     };
5126     DWORD shader_code_12[] =  {
5127         0xffff0102,                                         /* ps_1_2           */
5128         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
5129         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
5130         0x0000ffff                                          /* end              */
5131     };
5132     /* Skip 1.3 shaders because we have only 4 quads(ok, could make them smaller if needed).
5133      * 1.2 and 1.4 shaders behave the same, so it's unlikely that 1.3 shaders are different.
5134      * During development of this test, 1.3 shaders were verified too
5135      */
5136     DWORD shader_code_14[] =  {
5137         0xffff0104,                                         /* ps_1_4           */
5138         /* Try to make one constant local. It gets clamped too, although the binary contains
5139          * the bigger numbers
5140          */
5141         0x00000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000, /* def c2, -0.5, 1.25, 2, 1 */
5142         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
5143         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
5144         0x0000ffff                                          /* end              */
5145     };
5146     DWORD shader_code_20[] =  {
5147         0xffff0200,                                         /* ps_2_0           */
5148         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
5149         0x03000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
5150         0x02000001, 0x800f0800, 0x80e40000,                 /* mov oC0, r0      */
5151         0x0000ffff                                          /* end              */
5152     };
5153     float quad1[] = {
5154         -1.0,   -1.0,   0.1,
5155          0.0,   -1.0,   0.1,
5156         -1.0,    0.0,   0.1,
5157          0.0,    0.0,   0.1
5158     };
5159     float quad2[] = {
5160          0.0,   -1.0,   0.1,
5161          1.0,   -1.0,   0.1,
5162          0.0,    0.0,   0.1,
5163          1.0,    0.0,   0.1
5164     };
5165     float quad3[] = {
5166          0.0,    0.0,   0.1,
5167          1.0,    0.0,   0.1,
5168          0.0,    1.0,   0.1,
5169          1.0,    1.0,   0.1
5170     };
5171     float quad4[] = {
5172         -1.0,    0.0,   0.1,
5173          0.0,    0.0,   0.1,
5174         -1.0,    1.0,   0.1,
5175          0.0,    1.0,   0.1
5176     };
5177     float test_data_c1[4] = {  1.25, -0.50, -1.50, 1.0};
5178     float test_data_c2[4] = { -0.50,  1.25,  2.00, 1.0};
5179
5180     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
5181     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5182
5183     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader_11);
5184     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5185     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12, &shader_12);
5186     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5187     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14, &shader_14);
5188     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5189     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_20, &shader_20);
5190     if(FAILED(hr)) shader_20 = NULL;
5191
5192     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1, 1);
5193     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
5194     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2, 1);
5195     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
5196     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5197     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
5198
5199     hr = IDirect3DDevice9_BeginScene(device);
5200     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5201     if(SUCCEEDED(hr))
5202     {
5203         hr = IDirect3DDevice9_SetPixelShader(device, shader_11);
5204         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5205         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 3 * sizeof(float));
5206         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5207
5208         hr = IDirect3DDevice9_SetPixelShader(device, shader_12);
5209         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5210         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
5211         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5212
5213         hr = IDirect3DDevice9_SetPixelShader(device, shader_14);
5214         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5215         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 3 * sizeof(float));
5216         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5217
5218         if(shader_20) {
5219             hr = IDirect3DDevice9_SetPixelShader(device, shader_20);
5220             ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5221             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 3 * sizeof(float));
5222             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5223         }
5224
5225         hr = IDirect3DDevice9_EndScene(device);
5226         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5227     }
5228     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5229     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5230
5231     color = getPixelColor(device, 160, 360);
5232     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x80, 0x80, 0x00), 1),
5233        "quad 1 has color %08x, expected 0x00808000\n", color);
5234     color = getPixelColor(device, 480, 360);
5235     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x80, 0x80, 0x00), 1),
5236        "quad 2 has color %08x, expected 0x00808000\n", color);
5237     color = getPixelColor(device, 480, 120);
5238     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x80, 0x80, 0x00), 1),
5239        "quad 3 has color %08x, expected 0x00808000\n", color);
5240     if(shader_20) {
5241         color = getPixelColor(device, 160, 120);
5242         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0xbf, 0x80), 1),
5243            "quad 4 has color %08x, expected 0x00bfbf80\n", color);
5244     }
5245     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5246     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5247
5248     if(shader_20) IDirect3DPixelShader9_Release(shader_20);
5249     IDirect3DPixelShader9_Release(shader_14);
5250     IDirect3DPixelShader9_Release(shader_12);
5251     IDirect3DPixelShader9_Release(shader_11);
5252 }
5253
5254 static void dp2add_ps_test(IDirect3DDevice9 *device)
5255 {
5256     IDirect3DPixelShader9 *shader_dp2add = NULL;
5257     IDirect3DPixelShader9 *shader_dp2add_sat = NULL;
5258     HRESULT hr;
5259     DWORD color;
5260
5261     /* DP2ADD is defined as:  (src0.r * src1.r) + (src0.g * src1.g) + src2.
5262      * One D3D restriction of all shader instructions except SINCOS is that no more than 2
5263      * source tokens can be constants.  So, for this exercise, we move contents of c0 to
5264      * r0 first.
5265      * The result here for the r,g,b components should be roughly 0.5:
5266      *   (0.5 * 0.5) + (0.5 * 0.5) + 0.0 = 0.5 */
5267     static const DWORD shader_code_dp2add[] =  {
5268         0xffff0200,                                                             /* ps_2_0                       */
5269         0x05000051, 0xa00f0000, 0x3f000000, 0x3f000000, 0x3f800000, 0x00000000, /* def c0, 0.5, 0.5, 1.0, 0     */
5270
5271         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                   */
5272         0x0400005a, 0x80070000, 0x80000000, 0x80000000, 0x80ff0000,             /* dp2add r0.rgb, r0, r0, r0.a  */
5273
5274         0x02000001, 0x80080000, 0xa0aa0000,                                     /* mov r0.a, c0.b               */
5275         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
5276         0x0000ffff                                                              /* end                          */
5277     };
5278
5279     /* Test the _sat modifier, too.  Result here should be:
5280      *   DP2: (-0.5 * -0.5) + (-0.5 * -0.5) + 2.0 = 2.5
5281      *      _SAT: ==> 1.0
5282      *   ADD: (1.0 + -0.5) = 0.5
5283      */
5284     static const DWORD shader_code_dp2add_sat[] =  {
5285         0xffff0200,                                                             /* ps_2_0                           */
5286         0x05000051, 0xa00f0000, 0xbf000000, 0xbf000000, 0x3f800000, 0x40000000, /* def c0, -0.5, -0.5, 1.0, 2.0     */
5287
5288         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                       */
5289         0x0400005a, 0x80170000, 0x80000000, 0x80000000, 0x80ff0000,             /* dp2add_sat r0.rgb, r0, r0, r0.a  */
5290         0x03000002, 0x80070000, 0x80e40000, 0xa0000000,                         /* add r0.rgb, r0, c0.r             */
5291
5292         0x02000001, 0x80080000, 0xa0aa0000,                                     /* mov r0.a, c0.b                   */
5293         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                      */
5294         0x0000ffff                                                              /* end                              */
5295     };
5296
5297     const float quad[] = {
5298         -1.0,   -1.0,   0.1,
5299          1.0,   -1.0,   0.1,
5300         -1.0,    1.0,   0.1,
5301          1.0,    1.0,   0.1
5302     };
5303
5304
5305     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
5306     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5307
5308     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_dp2add, &shader_dp2add);
5309     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5310
5311     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_dp2add_sat, &shader_dp2add_sat);
5312     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5313
5314     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5315     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
5316
5317     if (shader_dp2add) {
5318
5319         hr = IDirect3DDevice9_SetPixelShader(device, shader_dp2add);
5320         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5321
5322         hr = IDirect3DDevice9_BeginScene(device);
5323         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5324         if(SUCCEEDED(hr))
5325         {
5326             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
5327             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5328
5329             hr = IDirect3DDevice9_EndScene(device);
5330             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5331         }
5332
5333         color = getPixelColor(device, 360, 240);
5334         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x7f, 0x7f, 0x7f), 1),
5335                 "dp2add pixel has color %08x, expected ~0x007f7f7f\n", color);
5336
5337         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5338         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5339
5340         IDirect3DPixelShader9_Release(shader_dp2add);
5341     } else {
5342         skip("dp2add shader creation failed\n");
5343     }
5344
5345     if (shader_dp2add_sat) {
5346
5347         hr = IDirect3DDevice9_SetPixelShader(device, shader_dp2add_sat);
5348         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5349
5350         hr = IDirect3DDevice9_BeginScene(device);
5351         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5352         if(SUCCEEDED(hr))
5353         {
5354             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
5355             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5356
5357             hr = IDirect3DDevice9_EndScene(device);
5358             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5359         }
5360
5361         color = getPixelColor(device, 360, 240);
5362         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x7f, 0x7f, 0x7f), 1),
5363                 "dp2add pixel has color %08x, expected ~0x007f7f7f\n", color);
5364
5365         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5366         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5367
5368         IDirect3DPixelShader9_Release(shader_dp2add_sat);
5369     } else {
5370         skip("dp2add shader creation failed\n");
5371     }
5372
5373     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5374     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5375 }
5376
5377 static void cnd_test(IDirect3DDevice9 *device)
5378 {
5379     IDirect3DPixelShader9 *shader_11, *shader_12, *shader_13, *shader_14;
5380     IDirect3DPixelShader9 *shader_11_coissue, *shader_12_coissue, *shader_13_coissue, *shader_14_coissue;
5381     HRESULT hr;
5382     DWORD color;
5383     /* ps 1.x shaders are rather picky with writemasks and source swizzles. The dp3 is
5384      * used to copy r0.r to all components of r1, then copy r1.a to c0.a. Essentially it
5385      * does a mov r0.a, r0.r, which isn't allowed as-is in 1.x pixel shaders.
5386      */
5387     DWORD shader_code_11[] =  {
5388         0xffff0101,                                                                 /* ps_1_1               */
5389         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
5390         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
5391         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, ???(t0)      */
5392         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3 r1, r0, c0       */
5393         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
5394         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
5395         0x0000ffff                                                                  /* end                  */
5396     };
5397     DWORD shader_code_12[] =  {
5398         0xffff0102,                                                                 /* ps_1_2               */
5399         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
5400         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
5401         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, t0           */
5402         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3 r1, r0, c0       */
5403         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
5404         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
5405         0x0000ffff                                                                  /* end                  */
5406     };
5407     DWORD shader_code_13[] =  {
5408         0xffff0103,                                                                 /* ps_1_3               */
5409         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
5410         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
5411         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, t0           */
5412         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3, r1, r0, c0      */
5413         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
5414         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
5415         0x0000ffff                                                                  /* end                  */
5416     };
5417     DWORD shader_code_14[] =  {
5418         0xffff0104,                                                                 /* ps_1_3               */
5419         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,     /* def c0, 0, 0, 0, 1   */
5420         0x00000040, 0x80070000, 0xb0e40000,                                         /* texcrd r0, t0        */
5421         0x00000001, 0x80080000, 0xa0ff0000,                                         /* mov r0.a, c0.a       */
5422         0x00000050, 0x800f0000, 0x80e40000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0, c1, c2   */
5423         0x0000ffff                                                                  /* end                  */
5424     };
5425
5426     /* Special fun: The coissue flag on cnd: Apparently cnd always selects the 2nd source,
5427      * as if the src0 comparison against 0.5 always evaluates to true. The coissue flag isn't
5428      * set by the compiler, it was added manually after compilation. Note that the COISSUE
5429      * flag on a color(.xyz) operation is only allowed after an alpha operation. DirectX doesn't
5430      * have proper docs, but GL_ATI_fragment_shader explains the pairing of color and alpha ops
5431      * well enough.
5432      *
5433      * The shader attempts to test the range [-1;1] against coissued cnd, which is a bit tricky.
5434      * The input from t0 is [0;1]. 0.5 is subtracted, then we have to multiply with 2. Since
5435      * constants are clamped to [-1;1], a 2.0 is constructed by adding c0.r(=1.0) to c0.r into r1.r,
5436      * then r1(2.0, 0.0, 0.0, 0.0) is passed to dp3(explained above).
5437      */
5438     DWORD shader_code_11_coissue[] =  {
5439         0xffff0101,                                                             /* ps_1_1                   */
5440         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
5441         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
5442         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
5443         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
5444         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
5445         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
5446         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
5447         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
5448         /* 0x40000000 = D3DSI_COISSUE */
5449         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
5450         0x0000ffff                                                              /* end                      */
5451     };
5452     DWORD shader_code_12_coissue[] =  {
5453         0xffff0102,                                                             /* ps_1_2                   */
5454         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
5455         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
5456         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
5457         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
5458         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
5459         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
5460         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
5461         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
5462         /* 0x40000000 = D3DSI_COISSUE */
5463         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
5464         0x0000ffff                                                              /* end                      */
5465     };
5466     DWORD shader_code_13_coissue[] =  {
5467         0xffff0103,                                                             /* ps_1_3                   */
5468         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
5469         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
5470         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
5471         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
5472         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
5473         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
5474         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
5475         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
5476         /* 0x40000000 = D3DSI_COISSUE */
5477         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
5478         0x0000ffff                                                              /* end                      */
5479     };
5480     /* ps_1_4 does not have a different cnd behavior, just pass the [0;1] texcrd result to cnd, it will
5481      * compare against 0.5
5482      */
5483     DWORD shader_code_14_coissue[] =  {
5484         0xffff0104,                                                             /* ps_1_4                   */
5485         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0, 0, 0, 1       */
5486         0x00000040, 0x80070000, 0xb0e40000,                                     /* texcrd r0, t0            */
5487         0x00000001, 0x80080000, 0xa0ff0000,                                     /* mov r0.a, c0.a           */
5488         /* 0x40000000 = D3DSI_COISSUE */
5489         0x40000050, 0x80070000, 0x80e40000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0, c1, c2   */
5490         0x0000ffff                                                              /* end                      */
5491     };
5492     float quad1[] = {
5493         -1.0,   -1.0,   0.1,     0.0,    0.0,    1.0,
5494          0.0,   -1.0,   0.1,     1.0,    0.0,    1.0,
5495         -1.0,    0.0,   0.1,     0.0,    1.0,    0.0,
5496          0.0,    0.0,   0.1,     1.0,    1.0,    0.0
5497     };
5498     float quad2[] = {
5499          0.0,   -1.0,   0.1,     0.0,    0.0,    1.0,
5500          1.0,   -1.0,   0.1,     1.0,    0.0,    1.0,
5501          0.0,    0.0,   0.1,     0.0,    1.0,    0.0,
5502          1.0,    0.0,   0.1,     1.0,    1.0,    0.0
5503     };
5504     float quad3[] = {
5505          0.0,    0.0,   0.1,     0.0,    0.0,    1.0,
5506          1.0,    0.0,   0.1,     1.0,    0.0,    1.0,
5507          0.0,    1.0,   0.1,     0.0,    1.0,    0.0,
5508          1.0,    1.0,   0.1,     1.0,    1.0,    0.0
5509     };
5510     float quad4[] = {
5511         -1.0,    0.0,   0.1,     0.0,    0.0,    1.0,
5512          0.0,    0.0,   0.1,     1.0,    0.0,    1.0,
5513         -1.0,    1.0,   0.1,     0.0,    1.0,    0.0,
5514          0.0,    1.0,   0.1,     1.0,    1.0,    0.0
5515     };
5516     float test_data_c1[4] = {  0.0, 0.0, 0.0, 0.0};
5517     float test_data_c2[4] = {  1.0, 1.0, 1.0, 1.0};
5518     float test_data_c1_coi[4] = {  0.0, 1.0, 0.0, 0.0};
5519     float test_data_c2_coi[4] = {  1.0, 0.0, 1.0, 1.0};
5520
5521     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
5522     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5523
5524     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader_11);
5525     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5526     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12, &shader_12);
5527     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5528     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_13, &shader_13);
5529     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5530     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14, &shader_14);
5531     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5532     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11_coissue, &shader_11_coissue);
5533     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5534     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12_coissue, &shader_12_coissue);
5535     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5536     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_13_coissue, &shader_13_coissue);
5537     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5538     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14_coissue, &shader_14_coissue);
5539     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
5540
5541     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1, 1);
5542     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
5543     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2, 1);
5544     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
5545     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
5546     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
5547
5548     hr = IDirect3DDevice9_BeginScene(device);
5549     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5550     if(SUCCEEDED(hr))
5551     {
5552         hr = IDirect3DDevice9_SetPixelShader(device, shader_11);
5553         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5554         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
5555         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5556
5557         hr = IDirect3DDevice9_SetPixelShader(device, shader_12);
5558         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5559         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
5560         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5561
5562         hr = IDirect3DDevice9_SetPixelShader(device, shader_13);
5563         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5564         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 6 * sizeof(float));
5565         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5566
5567         hr = IDirect3DDevice9_SetPixelShader(device, shader_14);
5568         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5569         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
5570         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5571
5572         hr = IDirect3DDevice9_EndScene(device);
5573         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5574     }
5575
5576     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5577     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
5578
5579     /* This is the 1.4 test. Each component(r, g, b) is tested separately against 0.5 */
5580     color = getPixelColor(device, 158, 118);
5581     ok(color == 0x00ff00ff, "pixel 158, 118 has color %08x, expected 0x00ff00ff\n", color);
5582     color = getPixelColor(device, 162, 118);
5583     ok(color == 0x000000ff, "pixel 162, 118 has color %08x, expected 0x000000ff\n", color);
5584     color = getPixelColor(device, 158, 122);
5585     ok(color == 0x00ffffff, "pixel 162, 122 has color %08x, expected 0x00ffffff\n", color);
5586     color = getPixelColor(device, 162, 122);
5587     ok(color == 0x0000ffff, "pixel 162, 122 has color %08x, expected 0x0000ffff\n", color);
5588
5589     /* 1.1 shader. All 3 components get set, based on the .w comparison */
5590     color = getPixelColor(device, 158, 358);
5591     ok(color == 0x00ffffff, "pixel 158, 358 has color %08x, expected 0x00ffffff\n", color);
5592     color = getPixelColor(device, 162, 358);
5593     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
5594         "pixel 162, 358 has color %08x, expected 0x00000000\n", color);
5595     color = getPixelColor(device, 158, 362);
5596     ok(color == 0x00ffffff, "pixel 158, 362 has color %08x, expected 0x00ffffff\n", color);
5597     color = getPixelColor(device, 162, 362);
5598     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
5599         "pixel 162, 362 has color %08x, expected 0x00000000\n", color);
5600
5601     /* 1.2 shader */
5602     color = getPixelColor(device, 478, 358);
5603     ok(color == 0x00ffffff, "pixel 478, 358 has color %08x, expected 0x00ffffff\n", color);
5604     color = getPixelColor(device, 482, 358);
5605     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
5606         "pixel 482, 358 has color %08x, expected 0x00000000\n", color);
5607     color = getPixelColor(device, 478, 362);
5608     ok(color == 0x00ffffff, "pixel 478, 362 has color %08x, expected 0x00ffffff\n", color);
5609     color = getPixelColor(device, 482, 362);
5610     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
5611         "pixel 482, 362 has color %08x, expected 0x00000000\n", color);
5612
5613     /* 1.3 shader */
5614     color = getPixelColor(device, 478, 118);
5615     ok(color == 0x00ffffff, "pixel 478, 118 has color %08x, expected 0x00ffffff\n", color);
5616     color = getPixelColor(device, 482, 118);
5617     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
5618         "pixel 482, 118 has color %08x, expected 0x00000000\n", color);
5619     color = getPixelColor(device, 478, 122);
5620     ok(color == 0x00ffffff, "pixel 478, 122 has color %08x, expected 0x00ffffff\n", color);
5621     color = getPixelColor(device, 482, 122);
5622     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
5623         "pixel 482, 122 has color %08x, expected 0x00000000\n", color);
5624
5625     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5626     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5627
5628     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
5629     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5630     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1_coi, 1);
5631     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
5632     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2_coi, 1);
5633     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %08x\n", hr);
5634
5635     hr = IDirect3DDevice9_BeginScene(device);
5636     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5637     if(SUCCEEDED(hr))
5638     {
5639         hr = IDirect3DDevice9_SetPixelShader(device, shader_11_coissue);
5640         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5641         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
5642         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5643
5644         hr = IDirect3DDevice9_SetPixelShader(device, shader_12_coissue);
5645         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5646         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
5647         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5648
5649         hr = IDirect3DDevice9_SetPixelShader(device, shader_13_coissue);
5650         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5651         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 6 * sizeof(float));
5652         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5653
5654         hr = IDirect3DDevice9_SetPixelShader(device, shader_14_coissue);
5655         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5656         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
5657         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5658
5659         hr = IDirect3DDevice9_EndScene(device);
5660         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5661     }
5662
5663     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5664     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
5665
5666     /* This is the 1.4 test. The coissue doesn't change the behavior here, but keep in mind
5667      * that we swapped the values in c1 and c2 to make the other tests return some color
5668      */
5669     color = getPixelColor(device, 158, 118);
5670     ok(color == 0x00ffffff, "pixel 158, 118 has color %08x, expected 0x00ffffff\n", color);
5671     color = getPixelColor(device, 162, 118);
5672     ok(color == 0x0000ffff, "pixel 162, 118 has color %08x, expected 0x0000ffff\n", color);
5673     color = getPixelColor(device, 158, 122);
5674     ok(color == 0x00ff00ff, "pixel 162, 122 has color %08x, expected 0x00ff00ff\n", color);
5675     color = getPixelColor(device, 162, 122);
5676     ok(color == 0x000000ff, "pixel 162, 122 has color %08x, expected 0x000000ff\n", color);
5677
5678     /* 1.1 shader. coissue flag changed the semantic of cnd, c1 is always selected
5679      * (The Win7 nvidia driver always selects c2)
5680      */
5681     color = getPixelColor(device, 158, 358);
5682     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5683         "pixel 158, 358 has color %08x, expected 0x0000ff00\n", color);
5684     color = getPixelColor(device, 162, 358);
5685     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5686         "pixel 162, 358 has color %08x, expected 0x0000ff00\n", color);
5687     color = getPixelColor(device, 158, 362);
5688     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5689         "pixel 158, 362 has color %08x, expected 0x0000ff00\n", color);
5690     color = getPixelColor(device, 162, 362);
5691     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5692         "pixel 162, 362 has color %08x, expected 0x0000ff00\n", color);
5693
5694     /* 1.2 shader */
5695     color = getPixelColor(device, 478, 358);
5696     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5697         "pixel 478, 358 has color %08x, expected 0x0000ff00\n", color);
5698     color = getPixelColor(device, 482, 358);
5699     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5700         "pixel 482, 358 has color %08x, expected 0x0000ff00\n", color);
5701     color = getPixelColor(device, 478, 362);
5702     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5703         "pixel 478, 362 has color %08x, expected 0x0000ff00\n", color);
5704     color = getPixelColor(device, 482, 362);
5705     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5706         "pixel 482, 362 has color %08x, expected 0x0000ff00\n", color);
5707
5708     /* 1.3 shader */
5709     color = getPixelColor(device, 478, 118);
5710     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5711         "pixel 478, 118 has color %08x, expected 0x0000ff00\n", color);
5712     color = getPixelColor(device, 482, 118);
5713     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5714         "pixel 482, 118 has color %08x, expected 0x0000ff00\n", color);
5715     color = getPixelColor(device, 478, 122);
5716     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5717         "pixel 478, 122 has color %08x, expected 0x0000ff00\n", color);
5718     color = getPixelColor(device, 482, 122);
5719     ok(color_match(color, 0x0000ff00, 1) || color_match(color, 0x00ff00ff, 1),
5720         "pixel 482, 122 has color %08x, expected 0x0000ff00\n", color);
5721
5722     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5723     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5724
5725     IDirect3DPixelShader9_Release(shader_14_coissue);
5726     IDirect3DPixelShader9_Release(shader_13_coissue);
5727     IDirect3DPixelShader9_Release(shader_12_coissue);
5728     IDirect3DPixelShader9_Release(shader_11_coissue);
5729     IDirect3DPixelShader9_Release(shader_14);
5730     IDirect3DPixelShader9_Release(shader_13);
5731     IDirect3DPixelShader9_Release(shader_12);
5732     IDirect3DPixelShader9_Release(shader_11);
5733 }
5734
5735 static void nested_loop_test(IDirect3DDevice9 *device) {
5736     const DWORD shader_code[] = {
5737         0xffff0300,                                                             /* ps_3_0               */
5738         0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0, 0, 0, 1   */
5739         0x05000051, 0xa00f0001, 0x3d000000, 0x00000000, 0x00000000, 0x00000000, /* def c1, 1/32, 0, 0, 0*/
5740         0x05000030, 0xf00f0000, 0x00000004, 0x00000000, 0x00000002, 0x00000000, /* defi i0, 4, 0, 2, 0  */
5741         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0           */
5742         0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0          */
5743         0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0          */
5744         0x03000002, 0x800f0000, 0x80e40000, 0xa0e40001,                         /* add r0, r0, c1       */
5745         0x0000001d,                                                             /* endloop              */
5746         0x0000001d,                                                             /* endloop              */
5747         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0          */
5748         0x0000ffff                                                              /* end                  */
5749     };
5750     const DWORD vshader_code[] = {
5751         0xfffe0300,                                                             /* vs_3_0               */
5752         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0      */
5753         0x0200001f, 0x80000000, 0xe00f0000,                                     /* dcl_position o0      */
5754         0x02000001, 0xe00f0000, 0x90e40000,                                     /* mov o0, v0           */
5755         0x0000ffff                                                              /* end                  */
5756     };
5757     IDirect3DPixelShader9 *shader;
5758     IDirect3DVertexShader9 *vshader;
5759     HRESULT hr;
5760     DWORD color;
5761     const float quad[] = {
5762         -1.0,   -1.0,   0.1,
5763          1.0,   -1.0,   0.1,
5764         -1.0,    1.0,   0.1,
5765          1.0,    1.0,   0.1
5766     };
5767
5768     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
5769     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed with %08x\n", hr);
5770     hr = IDirect3DDevice9_SetPixelShader(device, shader);
5771     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with %08x\n", hr);
5772     hr = IDirect3DDevice9_CreateVertexShader(device, vshader_code, &vshader);
5773     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader failed with %08x\n", hr);
5774     hr = IDirect3DDevice9_SetVertexShader(device, vshader);
5775     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with %08x\n", hr);
5776     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5777     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
5778     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 0.0, 0);
5779     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
5780
5781     hr = IDirect3DDevice9_BeginScene(device);
5782     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
5783     if(SUCCEEDED(hr))
5784     {
5785         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
5786         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5787         hr = IDirect3DDevice9_EndScene(device);
5788         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
5789     }
5790
5791     color = getPixelColor(device, 360, 240);
5792     ok(color == 0x007f0000 || color == 0x00800000 || color == 0x00810000,
5793        "Nested loop test returned color 0x%08x, expected 0x00800000\n", color);
5794
5795     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5796     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
5797
5798     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5799     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with %08x\n", hr);
5800     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
5801     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with %08x\n", hr);
5802     IDirect3DPixelShader9_Release(shader);
5803     IDirect3DVertexShader9_Release(vshader);
5804 }
5805
5806 struct varying_test_struct
5807 {
5808     const DWORD             *shader_code;
5809     IDirect3DPixelShader9   *shader;
5810     DWORD                   color, color_rhw;
5811     const char              *name;
5812     BOOL                    todo, todo_rhw;
5813 };
5814
5815 struct hugeVertex
5816 {
5817     float pos_x,        pos_y,      pos_z,      rhw;
5818     float weight_1,     weight_2,   weight_3,   weight_4;
5819     float index_1,      index_2,    index_3,    index_4;
5820     float normal_1,     normal_2,   normal_3,   normal_4;
5821     float fog_1,        fog_2,      fog_3,      fog_4;
5822     float texcoord_1,   texcoord_2, texcoord_3, texcoord_4;
5823     float tangent_1,    tangent_2,  tangent_3,  tangent_4;
5824     float binormal_1,   binormal_2, binormal_3, binormal_4;
5825     float depth_1,      depth_2,    depth_3,    depth_4;
5826     DWORD diffuse, specular;
5827 };
5828
5829 static void pretransformed_varying_test(IDirect3DDevice9 *device) {
5830     /* dcl_position: fails to compile */
5831     const DWORD blendweight_code[] = {
5832         0xffff0300,                             /* ps_3_0                   */
5833         0x0200001f, 0x80000001, 0x900f0000,     /* dcl_blendweight, v0      */
5834         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5835         0x0000ffff                              /* end                      */
5836     };
5837     const DWORD blendindices_code[] = {
5838         0xffff0300,                             /* ps_3_0                   */
5839         0x0200001f, 0x80000002, 0x900f0000,     /* dcl_blendindices, v0     */
5840         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5841         0x0000ffff                              /* end                      */
5842     };
5843     const DWORD normal_code[] = {
5844         0xffff0300,                             /* ps_3_0                   */
5845         0x0200001f, 0x80000003, 0x900f0000,     /* dcl_normal, v0           */
5846         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5847         0x0000ffff                              /* end                      */
5848     };
5849     /* psize: fails? */
5850     const DWORD texcoord0_code[] = {
5851         0xffff0300,                             /* ps_3_0                   */
5852         0x0200001f, 0x80000005, 0x900f0000,     /* dcl_texcoord0, v0        */
5853         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5854         0x0000ffff                              /* end                      */
5855     };
5856     const DWORD tangent_code[] = {
5857         0xffff0300,                             /* ps_3_0                   */
5858         0x0200001f, 0x80000006, 0x900f0000,     /* dcl_tangent, v0          */
5859         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5860         0x0000ffff                              /* end                      */
5861     };
5862     const DWORD binormal_code[] = {
5863         0xffff0300,                             /* ps_3_0                   */
5864         0x0200001f, 0x80000007, 0x900f0000,     /* dcl_binormal, v0         */
5865         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5866         0x0000ffff                              /* end                      */
5867     };
5868     /* tessfactor: fails */
5869     /* positiont: fails */
5870     const DWORD color_code[] = {
5871         0xffff0300,                             /* ps_3_0                   */
5872         0x0200001f, 0x8000000a, 0x900f0000,     /* dcl_color0, v0           */
5873         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5874         0x0000ffff                              /* end                      */
5875     };
5876     const DWORD fog_code[] = {
5877         0xffff0300,                             /* ps_3_0                   */
5878         0x0200001f, 0x8000000b, 0x900f0000,     /* dcl_fog, v0              */
5879         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5880         0x0000ffff                              /* end                      */
5881     };
5882     const DWORD depth_code[] = {
5883         0xffff0300,                             /* ps_3_0                   */
5884         0x0200001f, 0x8000000c, 0x900f0000,     /* dcl_depth, v0            */
5885         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5886         0x0000ffff                              /* end                      */
5887     };
5888     const DWORD specular_code[] = {
5889         0xffff0300,                             /* ps_3_0                   */
5890         0x0200001f, 0x8001000a, 0x900f0000,     /* dcl_color1, v0           */
5891         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5892         0x0000ffff                              /* end                      */
5893     };
5894     /* sample: fails */
5895
5896     struct varying_test_struct tests[] = {
5897        {blendweight_code,       NULL,       0x00000000,     0x00191919,     "blendweight"   ,   FALSE,  TRUE  },
5898        {blendindices_code,      NULL,       0x00000000,     0x00000000,     "blendindices"  ,   FALSE,  FALSE },
5899        {normal_code,            NULL,       0x00000000,     0x004c4c4c,     "normal"        ,   FALSE,  TRUE  },
5900        /* Why does dx not forward the texcoord? */
5901        {texcoord0_code,         NULL,       0x00000000,     0x00808c8c,     "texcoord0"     ,   FALSE,  FALSE },
5902        {tangent_code,           NULL,       0x00000000,     0x00999999,     "tangent"       ,   FALSE,  TRUE  },
5903        {binormal_code,          NULL,       0x00000000,     0x00b2b2b2,     "binormal"      ,   FALSE,  TRUE  },
5904        {color_code,             NULL,       0x00e6e6e6,     0x00e6e6e6,     "color"         ,   FALSE,  FALSE },
5905        {fog_code,               NULL,       0x00000000,     0x00666666,     "fog"           ,   FALSE,  TRUE  },
5906        {depth_code,             NULL,       0x00000000,     0x00cccccc,     "depth"         ,   FALSE,  TRUE  },
5907        {specular_code,          NULL,       0x004488ff,     0x004488ff,     "specular"      ,   FALSE,  FALSE }
5908     };
5909     /* Declare a monster vertex type :-) */
5910     static const D3DVERTEXELEMENT9 decl_elements[] = {
5911         {0,   0,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT,      0},
5912         {0,  16,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT,    0},
5913         {0,  32,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES,   0},
5914         {0,  48,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,         0},
5915         {0,  64,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_FOG,            0},
5916         {0,  80,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
5917         {0,  96,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT,        0},
5918         {0, 112,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL,       0},
5919         {0, 128,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_DEPTH,          0},
5920         {0, 144,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
5921         {0, 148,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          1},
5922         D3DDECL_END()
5923     };
5924     struct hugeVertex data[4] = {
5925         {
5926             -1.0,   -1.0,   0.1,    1.0,
5927              0.1,    0.1,   0.1,    0.1,
5928              0.2,    0.2,   0.2,    0.2,
5929              0.3,    0.3,   0.3,    0.3,
5930              0.4,    0.4,   0.4,    0.4,
5931              0.50,   0.55,  0.55,   0.55,
5932              0.6,    0.6,   0.6,    0.7,
5933              0.7,    0.7,   0.7,    0.6,
5934              0.8,    0.8,   0.8,    0.8,
5935              0xe6e6e6e6, /* 0.9 * 256 */
5936              0x224488ff  /* Nothing special */
5937         },
5938         {
5939              1.0,   -1.0,   0.1,    1.0,
5940              0.1,    0.1,   0.1,    0.1,
5941              0.2,    0.2,   0.2,    0.2,
5942              0.3,    0.3,   0.3,    0.3,
5943              0.4,    0.4,   0.4,    0.4,
5944              0.50,   0.55,  0.55,   0.55,
5945              0.6,    0.6,   0.6,    0.7,
5946              0.7,    0.7,   0.7,    0.6,
5947              0.8,    0.8,   0.8,    0.8,
5948              0xe6e6e6e6, /* 0.9 * 256 */
5949              0x224488ff /* Nothing special */
5950         },
5951         {
5952             -1.0,    1.0,   0.1,    1.0,
5953              0.1,    0.1,   0.1,    0.1,
5954              0.2,    0.2,   0.2,    0.2,
5955              0.3,    0.3,   0.3,    0.3,
5956              0.4,    0.4,   0.4,    0.4,
5957              0.50,   0.55,  0.55,   0.55,
5958              0.6,    0.6,   0.6,    0.7,
5959              0.7,    0.7,   0.7,    0.6,
5960              0.8,    0.8,   0.8,    0.8,
5961              0xe6e6e6e6, /* 0.9 * 256 */
5962              0x224488ff /* Nothing special */
5963         },
5964         {
5965              1.0,    1.0,   0.1,    1.0,
5966              0.1,    0.1,   0.1,    0.1,
5967              0.2,    0.2,   0.2,    0.2,
5968              0.3,    0.3,   0.3,    0.3,
5969              0.4,    0.4,   0.4,    0.4,
5970              0.50,   0.55,  0.55,   0.55,
5971              0.6,    0.6,   0.6,    0.7,
5972              0.7,    0.7,   0.7,    0.6,
5973              0.8,    0.8,   0.8,    0.8,
5974              0xe6e6e6e6, /* 0.9 * 256 */
5975              0x224488ff /* Nothing special */
5976         },
5977     };
5978     struct hugeVertex data2[4];
5979     IDirect3DVertexDeclaration9 *decl;
5980     HRESULT hr;
5981     unsigned int i;
5982     DWORD color, r, g, b, r_e, g_e, b_e;
5983
5984     memcpy(data2, data, sizeof(data2));
5985     data2[0].pos_x = 0;     data2[0].pos_y = 0;
5986     data2[1].pos_x = 640;   data2[1].pos_y = 0;
5987     data2[2].pos_x = 0;     data2[2].pos_y = 480;
5988     data2[3].pos_x = 640;   data2[3].pos_y = 480;
5989
5990     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
5991     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
5992     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
5993     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
5994
5995     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
5996     {
5997         hr = IDirect3DDevice9_CreatePixelShader(device, tests[i].shader_code, &tests[i].shader);
5998         ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed for shader %s, hr = %08x\n",
5999            tests[i].name, hr);
6000     }
6001
6002     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
6003     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6004     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
6005     {
6006         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
6007         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
6008
6009         IDirect3DDevice9_SetPixelShader(device, tests[i].shader);
6010         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
6011
6012         hr = IDirect3DDevice9_BeginScene(device);
6013         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6014         if(SUCCEEDED(hr))
6015         {
6016             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, data2, sizeof(data2[0]));
6017             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6018             hr = IDirect3DDevice9_EndScene(device);
6019             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6020         }
6021
6022         color = getPixelColor(device, 360, 240);
6023         r = color & 0x00ff0000 >> 16;
6024         g = color & 0x0000ff00 >>  8;
6025         b = color & 0x000000ff;
6026         r_e = tests[i].color_rhw & 0x00ff0000 >> 16;
6027         g_e = tests[i].color_rhw & 0x0000ff00 >>  8;
6028         b_e = tests[i].color_rhw & 0x000000ff;
6029
6030         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6031         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6032
6033         if(tests[i].todo_rhw) {
6034             /* This isn't a weekend's job to fix, ignore the problem for now. Needs a replacement
6035              * pipeline
6036              */
6037             todo_wine ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
6038                          "Test %s returned color 0x%08x, expected 0x%08x(todo)\n",
6039                          tests[i].name, color, tests[i].color_rhw);
6040         } else {
6041             ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
6042                "Test %s returned color 0x%08x, expected 0x%08x\n",
6043                tests[i].name, color, tests[i].color_rhw);
6044         }
6045     }
6046
6047     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
6048     {
6049         IDirect3DPixelShader9_Release(tests[i].shader);
6050     }
6051
6052     IDirect3DVertexDeclaration9_Release(decl);
6053 }
6054
6055 static void test_compare_instructions(IDirect3DDevice9 *device)
6056 {
6057     DWORD shader_sge_vec_code[] = {
6058         0xfffe0101,                                         /* vs_1_1                   */
6059         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
6060         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
6061         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
6062         0x0000000d, 0xd00f0000, 0x80e40000, 0xa0e40001,     /* sge oD0, r0, c1          */
6063         0x0000ffff                                          /* end                      */
6064     };
6065     DWORD shader_slt_vec_code[] = {
6066         0xfffe0101,                                         /* vs_1_1                   */
6067         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
6068         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
6069         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
6070         0x0000000c, 0xd00f0000, 0x80e40000, 0xa0e40001,     /* slt oD0, r0, c1          */
6071         0x0000ffff                                          /* end                      */
6072     };
6073     DWORD shader_sge_scalar_code[] = {
6074         0xfffe0101,                                         /* vs_1_1                   */
6075         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
6076         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
6077         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
6078         0x0000000d, 0xd0010000, 0x80000000, 0xa0550001,     /* slt oD0.r, r0.r, c1.b    */
6079         0x0000000d, 0xd0020000, 0x80550000, 0xa0aa0001,     /* slt oD0.g, r0.g, c1.r    */
6080         0x0000000d, 0xd0040000, 0x80aa0000, 0xa0000001,     /* slt oD0.b, r0.b, c1.g    */
6081         0x0000ffff                                          /* end                      */
6082     };
6083     DWORD shader_slt_scalar_code[] = {
6084         0xfffe0101,                                         /* vs_1_1                   */
6085         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
6086         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
6087         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
6088         0x0000000c, 0xd0010000, 0x80000000, 0xa0aa0001,     /* slt oD0.r, r0.r, c1.b    */
6089         0x0000000c, 0xd0020000, 0x80550000, 0xa0000001,     /* slt oD0.g, r0.g, c1.r    */
6090         0x0000000c, 0xd0040000, 0x80aa0000, 0xa0550001,     /* slt oD0.b, r0.b, c1.g    */
6091         0x0000ffff                                          /* end                      */
6092     };
6093     IDirect3DVertexShader9 *shader_sge_vec;
6094     IDirect3DVertexShader9 *shader_slt_vec;
6095     IDirect3DVertexShader9 *shader_sge_scalar;
6096     IDirect3DVertexShader9 *shader_slt_scalar;
6097     HRESULT hr, color;
6098     float quad1[] =  {
6099         -1.0,   -1.0,   0.1,
6100          0.0,   -1.0,   0.1,
6101         -1.0,    0.0,   0.1,
6102          0.0,    0.0,   0.1
6103     };
6104     float quad2[] =  {
6105          0.0,   -1.0,   0.1,
6106          1.0,   -1.0,   0.1,
6107          0.0,    0.0,   0.1,
6108          1.0,    0.0,   0.1
6109     };
6110     float quad3[] =  {
6111         -1.0,    0.0,   0.1,
6112          0.0,    0.0,   0.1,
6113         -1.0,    1.0,   0.1,
6114          0.0,    1.0,   0.1
6115     };
6116     float quad4[] =  {
6117          0.0,    0.0,   0.1,
6118          1.0,    0.0,   0.1,
6119          0.0,    1.0,   0.1,
6120          1.0,    1.0,   0.1
6121     };
6122     const float const0[4] = {0.8, 0.2, 0.2, 0.2};
6123     const float const1[4] = {0.2, 0.8, 0.2, 0.2};
6124
6125     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
6126     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
6127
6128     hr = IDirect3DDevice9_CreateVertexShader(device, shader_sge_vec_code, &shader_sge_vec);
6129     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6130     hr = IDirect3DDevice9_CreateVertexShader(device, shader_slt_vec_code, &shader_slt_vec);
6131     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6132     hr = IDirect3DDevice9_CreateVertexShader(device, shader_sge_scalar_code, &shader_sge_scalar);
6133     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6134     hr = IDirect3DDevice9_CreateVertexShader(device, shader_slt_scalar_code, &shader_slt_scalar);
6135     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6136     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, const0, 1);
6137     ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
6138     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, const1, 1);
6139     ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
6140     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
6141     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetFVF failed (%08x)\n", hr);
6142
6143     hr = IDirect3DDevice9_BeginScene(device);
6144     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6145     if(SUCCEEDED(hr))
6146     {
6147         hr = IDirect3DDevice9_SetVertexShader(device, shader_sge_vec);
6148         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6149         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 3);
6150         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6151
6152         hr = IDirect3DDevice9_SetVertexShader(device, shader_slt_vec);
6153         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6154         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2,  quad2, sizeof(float) * 3);
6155         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6156
6157         hr = IDirect3DDevice9_SetVertexShader(device, shader_sge_scalar);
6158         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6159         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 3);
6160         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6161
6162         hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, const0, 1);
6163         ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
6164
6165         hr = IDirect3DDevice9_SetVertexShader(device, shader_slt_scalar);
6166         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6167         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 3);
6168         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6169
6170         hr = IDirect3DDevice9_EndScene(device);
6171         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6172     }
6173
6174     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
6175     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6176
6177     color = getPixelColor(device, 160, 360);
6178     ok(color == 0x00FF00FF, "Compare test: Quad 1(sge vec) returned color 0x%08x, expected 0x00FF00FF\n", color);
6179     color = getPixelColor(device, 480, 360);
6180     ok(color == 0x0000FF00, "Compare test: Quad 2(slt vec) returned color 0x%08x, expected 0x0000FF00\n", color);
6181     color = getPixelColor(device, 160, 120);
6182     ok(color == 0x00FFFFFF, "Compare test: Quad 3(sge scalar) returned color 0x%08x, expected 0x00FFFFFF\n", color);
6183     color = getPixelColor(device, 480, 160);
6184     ok(color == 0x000000ff, "Compare test: Quad 4(slt scalar) returned color 0x%08x, expected 0x000000ff\n", color);
6185
6186     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6187     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6188
6189     IDirect3DVertexShader9_Release(shader_sge_vec);
6190     IDirect3DVertexShader9_Release(shader_slt_vec);
6191     IDirect3DVertexShader9_Release(shader_sge_scalar);
6192     IDirect3DVertexShader9_Release(shader_slt_scalar);
6193 }
6194
6195 static void test_vshader_input(IDirect3DDevice9 *device)
6196 {
6197     static const DWORD swapped_shader_code_3[] =
6198     {
6199         0xfffe0300,                                         /* vs_3_0               */
6200         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
6201         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
6202         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6203         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
6204         0x0200001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
6205         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
6206         0x02000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
6207         0x03000002, 0xe00f0001, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
6208         0x0000ffff                                          /* end                  */
6209     };
6210     static const DWORD swapped_shader_code_1[] =
6211     {
6212         0xfffe0101,                                         /* vs_1_1               */
6213         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6214         0x0000001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
6215         0x0000001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
6216         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov o0, v0           */
6217         0x00000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
6218         0x00000002, 0xd00f0000, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
6219         0x0000ffff                                          /* end                  */
6220     };
6221     static const DWORD swapped_shader_code_2[] =
6222     {
6223         0xfffe0200,                                         /* vs_2_0               */
6224         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6225         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
6226         0x0200001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
6227         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov o0, v0           */
6228         0x02000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
6229         0x03000002, 0xd00f0000, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
6230         0x0000ffff                                          /* end                  */
6231     };
6232     static const DWORD texcoord_color_shader_code_3[] =
6233     {
6234         0xfffe0300,                                         /* vs_3_0               */
6235         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
6236         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
6237         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6238         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
6239         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
6240         0x02000001, 0xe00f0001, 0x90e40001,                 /* mov o1, v1           */
6241         0x0000ffff                                          /* end                  */
6242     };
6243     static const DWORD texcoord_color_shader_code_2[] =
6244     {
6245         0xfffe0200,                                         /* vs_2_0               */
6246         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6247         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
6248         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
6249         0x02000001, 0xd00f0000, 0x90e40001,                 /* mov oD0, v1          */
6250         0x0000ffff                                          /* end                  */
6251     };
6252     static const DWORD texcoord_color_shader_code_1[] =
6253     {
6254         0xfffe0101,                                         /* vs_1_1               */
6255         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6256         0x0000001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
6257         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
6258         0x00000001, 0xd00f0000, 0x90e40001,                 /* mov oD0, v1          */
6259         0x0000ffff                                          /* end                  */
6260     };
6261     static const DWORD color_color_shader_code_3[] =
6262     {
6263         0xfffe0300,                                         /* vs_3_0               */
6264         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
6265         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
6266         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6267         0x0200001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
6268         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
6269         0x03000005, 0xe00f0001, 0xa0e40000, 0x90e40001,     /* mul o1, c0, v1       */
6270         0x0000ffff                                          /* end                  */
6271     };
6272     static const DWORD color_color_shader_code_2[] =
6273     {
6274         0xfffe0200,                                         /* vs_2_0               */
6275         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6276         0x0200001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
6277         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
6278         0x03000005, 0xd00f0000, 0xa0e40000, 0x90e40001,     /* mul oD0, c0, v1      */
6279         0x0000ffff                                          /* end                  */
6280     };
6281     static const DWORD color_color_shader_code_1[] =
6282     {
6283         0xfffe0101,                                         /* vs_1_1               */
6284         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
6285         0x0000001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
6286         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
6287         0x00000005, 0xd00f0000, 0xa0e40000, 0x90e40001,     /* mul oD0, c0, v1      */
6288         0x0000ffff                                          /* end                  */
6289     };
6290     static const DWORD ps3_code[] =
6291     {
6292         0xffff0300,                                         /* ps_3_0               */
6293         0x0200001f, 0x8000000a, 0x900f0000,                 /* dcl_color0 v0        */
6294         0x02000001, 0x800f0800, 0x90e40000,                 /* mov oC0, v0          */
6295         0x0000ffff                                          /* end                  */
6296     };
6297     IDirect3DVertexShader9 *swapped_shader, *texcoord_color_shader, *color_color_shader;
6298     IDirect3DPixelShader9 *ps;
6299     HRESULT hr;
6300     DWORD color;
6301     float quad1[] =  {
6302         -1.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6303          0.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6304         -1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6305          0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6306     };
6307     float quad2[] =  {
6308          0.0,   -1.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6309          1.0,   -1.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6310          0.0,    0.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6311          1.0,    0.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6312     };
6313     float quad3[] =  {
6314         -1.0,    0.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    1.0,    -1.0,   0.0,    0.0,
6315          0.0,    0.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    1.0,     0.0,   0.0,    0.0,
6316         -1.0,    1.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    0.0,    -1.0,   1.0,    0.0,
6317          0.0,    1.0,   0.1,   -1.0,    0.0,    0.0,    0.0,   -1.0,     0.0,   0.0,    0.0,
6318     };
6319     float quad4[] =  {
6320          0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6321          1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6322          0.0,    1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6323          1.0,    1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
6324     };
6325     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd[] = {
6326         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6327         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6328         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
6329         D3DDECL_END()
6330     };
6331     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd_rightorder[] = {
6332         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6333         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
6334         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6335         D3DDECL_END()
6336     };
6337     static const D3DVERTEXELEMENT9 decl_elements_onetexcrd[] = {
6338         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6339         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6340         D3DDECL_END()
6341     };
6342     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd_wrongidx[] = {
6343         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6344         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
6345         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       2},
6346         D3DDECL_END()
6347     };
6348     static const D3DVERTEXELEMENT9 decl_elements_texcoord_color[] = {
6349         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6350         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
6351         D3DDECL_END()
6352     };
6353     static const D3DVERTEXELEMENT9 decl_elements_color_color[] = {
6354         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6355         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6356         D3DDECL_END()
6357     };
6358     static const D3DVERTEXELEMENT9 decl_elements_color_ubyte[] = {
6359         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6360         {0,  12,  D3DDECLTYPE_UBYTE4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6361         D3DDECL_END()
6362     };
6363     static const D3DVERTEXELEMENT9 decl_elements_color_float[] = {
6364         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6365         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6366         D3DDECL_END()
6367     };
6368     IDirect3DVertexDeclaration9 *decl_twotexcrd, *decl_onetexcrd, *decl_twotex_wrongidx, *decl_twotexcrd_rightorder;
6369     IDirect3DVertexDeclaration9 *decl_texcoord_color, *decl_color_color, *decl_color_ubyte, *decl_color_float;
6370     unsigned int i;
6371     float normalize[4] = {1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0};
6372     float no_normalize[4] = {1.0, 1.0, 1.0, 1.0};
6373
6374     struct vertex quad1_color[] =  {
6375        {-1.0,   -1.0,   0.1,    0x00ff8040},
6376        { 0.0,   -1.0,   0.1,    0x00ff8040},
6377        {-1.0,    0.0,   0.1,    0x00ff8040},
6378        { 0.0,    0.0,   0.1,    0x00ff8040}
6379     };
6380     struct vertex quad2_color[] =  {
6381        { 0.0,   -1.0,   0.1,    0x00ff8040},
6382        { 1.0,   -1.0,   0.1,    0x00ff8040},
6383        { 0.0,    0.0,   0.1,    0x00ff8040},
6384        { 1.0,    0.0,   0.1,    0x00ff8040}
6385     };
6386     struct vertex quad3_color[] =  {
6387        {-1.0,    0.0,   0.1,    0x00ff8040},
6388        { 0.0,    0.0,   0.1,    0x00ff8040},
6389        {-1.0,    1.0,   0.1,    0x00ff8040},
6390        { 0.0,    1.0,   0.1,    0x00ff8040}
6391     };
6392     float quad4_color[] =  {
6393          0.0,    0.0,   0.1,    1.0,    1.0,    0.0,    0.0,
6394          1.0,    0.0,   0.1,    1.0,    1.0,    0.0,    1.0,
6395          0.0,    1.0,   0.1,    1.0,    1.0,    0.0,    0.0,
6396          1.0,    1.0,   0.1,    1.0,    1.0,    0.0,    1.0,
6397     };
6398
6399     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd, &decl_twotexcrd);
6400     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6401     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_onetexcrd, &decl_onetexcrd);
6402     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6403     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd_wrongidx, &decl_twotex_wrongidx);
6404     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6405     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd_rightorder, &decl_twotexcrd_rightorder);
6406     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6407
6408     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_texcoord_color, &decl_texcoord_color);
6409     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6410     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_color, &decl_color_color);
6411     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6412     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_ubyte, &decl_color_ubyte);
6413     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6414     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_float, &decl_color_float);
6415     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %08x\n", hr);
6416
6417     hr = IDirect3DDevice9_CreatePixelShader(device, ps3_code, &ps);
6418     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %08x\n", hr);
6419
6420     for(i = 1; i <= 3; i++) {
6421         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
6422         ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
6423         if(i == 3) {
6424             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_3, &swapped_shader);
6425             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6426             hr = IDirect3DDevice9_SetPixelShader(device, ps);
6427             ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
6428         } else if(i == 2){
6429             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_2, &swapped_shader);
6430             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6431         } else if(i == 1) {
6432             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_1, &swapped_shader);
6433             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6434         }
6435
6436         hr = IDirect3DDevice9_BeginScene(device);
6437         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6438         if(SUCCEEDED(hr))
6439         {
6440             hr = IDirect3DDevice9_SetVertexShader(device, swapped_shader);
6441             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6442
6443             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd);
6444             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6445             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 11);
6446             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6447
6448             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_onetexcrd);
6449             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6450             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(float) * 11);
6451             if(i == 3 || i == 2) {
6452                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
6453             } else if(i == 1) {
6454                 /* Succeeds or fails, depending on SW or HW vertex processing */
6455                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x), i = 1\n", hr);
6456             }
6457
6458             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd_rightorder);
6459             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6460             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 11);
6461             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6462
6463             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotex_wrongidx);
6464             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6465             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 11);
6466             if(i == 3 || i == 2) {
6467                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
6468             } else if(i == 1) {
6469                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = 1\n", hr);
6470             }
6471
6472             hr = IDirect3DDevice9_EndScene(device);
6473             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6474         }
6475
6476         if(i == 3 || i == 2) {
6477             color = getPixelColor(device, 160, 360);
6478             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x80), 1),
6479                "Input test: Quad 1(2crd) returned color 0x%08x, expected 0x00FFFF80\n", color);
6480
6481             /* The last value of the read but undefined stream is used, it is 0x00. The defined input is vec4(1, 0, 0, 0) */
6482             color = getPixelColor(device, 480, 360);
6483             ok(color == 0x00FFFF00 || color ==0x00FF0000,
6484                "Input test: Quad 2(1crd) returned color 0x%08x, expected 0x00FFFF00\n", color);
6485             color = getPixelColor(device, 160, 120);
6486             /* Same as above, accept both the last used value and 0.0 for the undefined streams */
6487             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x80), 1) || color == D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00),
6488                "Input test: Quad 3(2crd-wrongidx) returned color 0x%08x, expected 0x00FF0080\n", color);
6489
6490             color = getPixelColor(device, 480, 160);
6491             ok(color == 0x00000000, "Input test: Quad 4(2crd-rightorder) returned color 0x%08x, expected 0x00000000\n", color);
6492         } else if(i == 1) {
6493             color = getPixelColor(device, 160, 360);
6494             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x80), 1),
6495                "Input test: Quad 1(2crd) returned color 0x%08x, expected 0x00FFFF80\n", color);
6496             color = getPixelColor(device, 480, 360);
6497             /* Accept the clear color as well in this case, since SW VP returns an error */
6498             ok(color == 0x00FFFF00 || color == 0x00FF0000, "Input test: Quad 2(1crd) returned color 0x%08x, expected 0x00FFFF00\n", color);
6499             color = getPixelColor(device, 160, 120);
6500             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x80), 1) || color == D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00),
6501                "Input test: Quad 3(2crd-wrongidx) returned color 0x%08x, expected 0x00FF0080\n", color);
6502             color = getPixelColor(device, 480, 160);
6503             ok(color == 0x00000000, "Input test: Quad 4(2crd-rightorder) returned color 0x%08x, expected 0x00000000\n", color);
6504         }
6505
6506         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6507         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6508
6509         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff808080, 0.0, 0);
6510         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
6511
6512         /* Now find out if the whole streams are re-read, or just the last active value for the
6513          * vertices is used.
6514          */
6515         hr = IDirect3DDevice9_BeginScene(device);
6516         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6517         if(SUCCEEDED(hr))
6518         {
6519             float quad1_modified[] =  {
6520                 -1.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,   -1.0,     0.0,   0.0,    0.0,
6521                  0.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.0,    0.0,
6522                 -1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,     0.0,  -1.0,    0.0,
6523                  0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,   -1.0,    -1.0,  -1.0,    0.0,
6524             };
6525             float quad2_modified[] =  {
6526                  0.0,   -1.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6527                  1.0,   -1.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6528                  0.0,    0.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6529                  1.0,    0.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6530             };
6531
6532             hr = IDirect3DDevice9_SetVertexShader(device, swapped_shader);
6533             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6534
6535             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd);
6536             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6537             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 3, quad1_modified, sizeof(float) * 11);
6538             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6539
6540             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_onetexcrd);
6541             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6542             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2_modified, sizeof(float) * 11);
6543             if(i == 3 || i == 2) {
6544                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
6545             } else if(i == 1) {
6546                 /* Succeeds or fails, depending on SW or HW vertex processing */
6547                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x), i = 1\n", hr);
6548             }
6549
6550             hr = IDirect3DDevice9_EndScene(device);
6551             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6552         }
6553
6554         color = getPixelColor(device, 480, 350);
6555         /* vs_1_1 may fail, accept the clear color. Some drivers also set the undefined streams to 0, accept that
6556          * as well.
6557          *
6558          * NOTE: This test fails on the reference rasterizer. In the refrast, the 4 vertices have different colors,
6559          * i.e., the whole old stream is read, and not just the last used attribute. Some games require that this
6560          * does *not* happen, otherwise they can crash because of a read from a bad pointer, so do not accept the
6561          * refrast's result.
6562          *
6563          * A test app for this behavior is Half Life 2 Episode 2 in dxlevel 95, and related games(Portal, TF2).
6564          */
6565         ok(color == 0x000000FF || color == 0x00808080 || color == 0x00000000,
6566            "Input test: Quad 2(different colors) returned color 0x%08x, expected 0x000000FF, 0x00808080 or 0x00000000\n", color);
6567
6568         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6569         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6570
6571         IDirect3DDevice9_SetVertexShader(device, NULL);
6572         IDirect3DDevice9_SetPixelShader(device, NULL);
6573         IDirect3DDevice9_SetVertexDeclaration(device, NULL);
6574
6575         IDirect3DVertexShader9_Release(swapped_shader);
6576     }
6577
6578     for(i = 1; i <= 3; i++) {
6579         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
6580         ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear returned %#x.\n", hr);
6581         if(i == 3) {
6582             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_3, &texcoord_color_shader);
6583             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6584             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_3, &color_color_shader);
6585             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6586             hr = IDirect3DDevice9_SetPixelShader(device, ps);
6587             ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %08x\n", hr);
6588         } else if(i == 2){
6589             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_2, &texcoord_color_shader);
6590             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6591             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_2, &color_color_shader);
6592             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6593         } else if(i == 1) {
6594             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_1, &texcoord_color_shader);
6595             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6596             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_1, &color_color_shader);
6597             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
6598         }
6599
6600         hr = IDirect3DDevice9_BeginScene(device);
6601         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
6602         if(SUCCEEDED(hr))
6603         {
6604             hr = IDirect3DDevice9_SetVertexShader(device, texcoord_color_shader);
6605             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6606             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_texcoord_color);
6607             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6608             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1_color, sizeof(quad1_color[0]));
6609             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6610
6611             hr = IDirect3DDevice9_SetVertexShader(device, color_color_shader);
6612             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6613
6614             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, normalize, 1);
6615             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6616             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_ubyte);
6617             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6618             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2_color, sizeof(quad2_color[0]));
6619             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6620
6621             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, no_normalize, 1);
6622             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
6623             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_color);
6624             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6625             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3_color, sizeof(quad3_color[0]));
6626             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6627
6628             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_float);
6629             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %08x\n", hr);
6630             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4_color, sizeof(float) * 7);
6631             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6632
6633             hr = IDirect3DDevice9_EndScene(device);
6634             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
6635         }
6636         IDirect3DDevice9_SetVertexShader(device, NULL);
6637         IDirect3DDevice9_SetVertexDeclaration(device, NULL);
6638         IDirect3DDevice9_SetPixelShader(device, NULL);
6639
6640         color = getPixelColor(device, 160, 360);
6641         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x80, 0x40), 1),
6642            "Input test: Quad 1(color-texcoord) returned color 0x%08x, expected 0x00ff8040\n", color);
6643         color = getPixelColor(device, 480, 360);
6644         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x40, 0x80, 0xff), 1),
6645            "Input test: Quad 2(color-ubyte) returned color 0x%08x, expected 0x004080ff\n", color);
6646         color = getPixelColor(device, 160, 120);
6647         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x80, 0x40), 1),
6648            "Input test: Quad 3(color-color) returned color 0x%08x, expected 0x00ff8040\n", color);
6649         color = getPixelColor(device, 480, 160);
6650         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00), 1),
6651            "Input test: Quad 4(color-float) returned color 0x%08x, expected 0x00FFFF00\n", color);
6652
6653         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6654         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6655
6656         IDirect3DVertexShader9_Release(texcoord_color_shader);
6657         IDirect3DVertexShader9_Release(color_color_shader);
6658     }
6659
6660     IDirect3DVertexDeclaration9_Release(decl_twotexcrd);
6661     IDirect3DVertexDeclaration9_Release(decl_onetexcrd);
6662     IDirect3DVertexDeclaration9_Release(decl_twotex_wrongidx);
6663     IDirect3DVertexDeclaration9_Release(decl_twotexcrd_rightorder);
6664
6665     IDirect3DVertexDeclaration9_Release(decl_texcoord_color);
6666     IDirect3DVertexDeclaration9_Release(decl_color_color);
6667     IDirect3DVertexDeclaration9_Release(decl_color_ubyte);
6668     IDirect3DVertexDeclaration9_Release(decl_color_float);
6669
6670     IDirect3DPixelShader9_Release(ps);
6671 }
6672
6673 static void srgbtexture_test(IDirect3DDevice9 *device)
6674 {
6675     /* Fill a texture with 0x7f (~ .5), and then turn on the D3DSAMP_SRGBTEXTURE
6676      * texture stage state to render a quad using that texture.  The resulting
6677      * color components should be 0x36 (~ 0.21), per this formula:
6678      *    linear_color = ((srgb_color + 0.055) / 1.055) ^ 2.4
6679      * This is true where srgb_color > 0.04045.
6680      */
6681     IDirect3D9 *d3d = NULL;
6682     HRESULT hr;
6683     LPDIRECT3DTEXTURE9 texture = NULL;
6684     LPDIRECT3DSURFACE9 surface = NULL;
6685     D3DLOCKED_RECT lr;
6686     DWORD color;
6687     float quad[] = {
6688         -1.0,       1.0,       0.0,     0.0,    0.0,
6689          1.0,       1.0,       0.0,     1.0,    0.0,
6690         -1.0,      -1.0,       0.0,     0.0,    1.0,
6691          1.0,      -1.0,       0.0,     1.0,    1.0,
6692     };
6693
6694
6695     memset(&lr, 0, sizeof(lr));
6696     IDirect3DDevice9_GetDirect3D(device, &d3d);
6697     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6698                                     D3DUSAGE_QUERY_SRGBREAD, D3DRTYPE_TEXTURE,
6699                                     D3DFMT_A8R8G8B8) != D3D_OK) {
6700         skip("D3DFMT_A8R8G8B8 textures with SRGBREAD not supported\n");
6701         goto out;
6702     }
6703
6704     hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0,
6705                                         D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
6706                                         &texture, NULL);
6707     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
6708     if(!texture) {
6709         skip("Failed to create A8R8G8B8 texture with SRGBREAD\n");
6710         goto out;
6711     }
6712     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
6713     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
6714
6715     fill_surface(surface, 0xff7f7f7f);
6716     IDirect3DSurface9_Release(surface);
6717
6718     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
6719     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6720     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
6721     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
6722
6723     hr = IDirect3DDevice9_BeginScene(device);
6724     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
6725     if(SUCCEEDED(hr))
6726     {
6727         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, TRUE);
6728         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
6729
6730         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
6731         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
6732
6733
6734         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
6735         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with %08x\n", hr);
6736
6737         hr = IDirect3DDevice9_EndScene(device);
6738         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
6739     }
6740
6741     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6742     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
6743     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, FALSE);
6744     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %08x\n", hr);
6745
6746     color = getPixelColor(device, 320, 240);
6747     ok(color == 0x00363636 || color == 0x00373737, "srgb quad has color %08x, expected 0x00363636\n", color);
6748
6749     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6750     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6751
6752 out:
6753     if(texture) IDirect3DTexture9_Release(texture);
6754     IDirect3D9_Release(d3d);
6755 }
6756
6757 static void shademode_test(IDirect3DDevice9 *device)
6758 {
6759     /* Render a quad and try all of the different fixed function shading models. */
6760     HRESULT hr;
6761     DWORD color0, color1;
6762     DWORD color0_gouraud = 0, color1_gouraud = 0;
6763     DWORD shademode = D3DSHADE_FLAT;
6764     DWORD primtype = D3DPT_TRIANGLESTRIP;
6765     LPVOID data = NULL;
6766     LPDIRECT3DVERTEXBUFFER9 vb_strip = NULL;
6767     LPDIRECT3DVERTEXBUFFER9 vb_list = NULL;
6768     UINT i, j;
6769     struct vertex quad_strip[] =
6770     {
6771         {-1.0f, -1.0f,  0.0f, 0xffff0000  },
6772         {-1.0f,  1.0f,  0.0f, 0xff00ff00  },
6773         { 1.0f, -1.0f,  0.0f, 0xff0000ff  },
6774         { 1.0f,  1.0f,  0.0f, 0xffffffff  }
6775     };
6776     struct vertex quad_list[] =
6777     {
6778         {-1.0f, -1.0f,  0.0f, 0xffff0000  },
6779         {-1.0f,  1.0f,  0.0f, 0xff00ff00  },
6780         { 1.0f, -1.0f,  0.0f, 0xff0000ff  },
6781
6782         {-1.0f,  1.0f,  0.0f, 0xff00ff00  },
6783         { 1.0f, -1.0f,  0.0f, 0xff0000ff  },
6784         { 1.0f,  1.0f,  0.0f, 0xffffffff  }
6785     };
6786
6787     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad_strip),
6788                                              0, 0, D3DPOOL_MANAGED, &vb_strip, NULL);
6789     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
6790     if (FAILED(hr)) goto bail;
6791
6792     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad_list),
6793                                              0, 0, D3DPOOL_MANAGED, &vb_list, NULL);
6794     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
6795     if (FAILED(hr)) goto bail;
6796
6797     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
6798     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6799
6800     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
6801     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
6802
6803     hr = IDirect3DVertexBuffer9_Lock(vb_strip, 0, sizeof(quad_strip), &data, 0);
6804     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
6805     memcpy(data, quad_strip, sizeof(quad_strip));
6806     hr = IDirect3DVertexBuffer9_Unlock(vb_strip);
6807     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
6808
6809     hr = IDirect3DVertexBuffer9_Lock(vb_list, 0, sizeof(quad_list), &data, 0);
6810     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
6811     memcpy(data, quad_list, sizeof(quad_list));
6812     hr = IDirect3DVertexBuffer9_Unlock(vb_list);
6813     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
6814
6815     /* Try it first with a TRIANGLESTRIP.  Do it with different geometry because
6816      * the color fixups we have to do for FLAT shading will be dependent on that. */
6817     hr = IDirect3DDevice9_SetStreamSource(device, 0, vb_strip, 0, sizeof(quad_strip[0]));
6818     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
6819
6820     /* First loop uses a TRIANGLESTRIP geometry, 2nd uses a TRIANGLELIST */
6821     for (j=0; j<2; j++) {
6822
6823         /* Inner loop just changes the D3DRS_SHADEMODE */
6824         for (i=0; i<3; i++) {
6825             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
6826             ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
6827
6828             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SHADEMODE, shademode);
6829             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6830
6831             hr = IDirect3DDevice9_BeginScene(device);
6832             ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
6833             if(SUCCEEDED(hr))
6834             {
6835                 hr = IDirect3DDevice9_DrawPrimitive(device, primtype, 0, 2);
6836                 ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed with %08x\n", hr);
6837
6838                 hr = IDirect3DDevice9_EndScene(device);
6839                 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
6840             }
6841
6842             /* Sample two spots from the output */
6843             color0 = getPixelColor(device, 100, 100); /* Inside first triangle */
6844             color1 = getPixelColor(device, 500, 350); /* Inside second triangle */
6845             switch(shademode) {
6846                 case D3DSHADE_FLAT:
6847                     /* Should take the color of the first vertex of each triangle */
6848                     if (0)
6849                     {
6850                         /* This test depends on EXT_provoking_vertex being
6851                          * available. This extension is currently (20090810)
6852                          * not common enough to let the test fail if it isn't
6853                          * present. */
6854                         ok(color0 == 0x00ff0000, "FLAT shading has color0 %08x, expected 0x00ff0000\n", color0);
6855                         ok(color1 == 0x0000ff00, "FLAT shading has color1 %08x, expected 0x0000ff00\n", color1);
6856                     }
6857                     shademode = D3DSHADE_GOURAUD;
6858                     break;
6859                 case D3DSHADE_GOURAUD:
6860                     /* Should be an interpolated blend */
6861
6862                     ok(color_match(color0, D3DCOLOR_ARGB(0x00, 0x0d, 0xca, 0x28), 2),
6863                        "GOURAUD shading has color0 %08x, expected 0x00dca28\n", color0);
6864                     ok(color_match(color1, D3DCOLOR_ARGB(0x00, 0x0d, 0x45, 0xc7), 2),
6865                        "GOURAUD shading has color1 %08x, expected 0x000d45c7\n", color1);
6866
6867                     color0_gouraud = color0;
6868                     color1_gouraud = color1;
6869
6870                     shademode = D3DSHADE_PHONG;
6871                     break;
6872                 case D3DSHADE_PHONG:
6873                     /* Should be the same as GOURAUD, since no hardware implements this */
6874                     ok(color_match(color0, D3DCOLOR_ARGB(0x00, 0x0d, 0xca, 0x28), 2),
6875                        "PHONG shading has color0 %08x, expected 0x000dca28\n", color0);
6876                     ok(color_match(color1, D3DCOLOR_ARGB(0x00, 0x0d, 0x45, 0xc7), 2),
6877                        "PHONG shading has color1 %08x, expected 0x000d45c7\n", color1);
6878
6879                     ok(color0 == color0_gouraud, "difference between GOURAUD and PHONG shading detected: %08x %08x\n",
6880                             color0_gouraud, color0);
6881                     ok(color1 == color1_gouraud, "difference between GOURAUD and PHONG shading detected: %08x %08x\n",
6882                             color1_gouraud, color1);
6883                     break;
6884             }
6885         }
6886
6887         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6888         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
6889
6890         /* Now, do it all over again with a TRIANGLELIST */
6891         hr = IDirect3DDevice9_SetStreamSource(device, 0, vb_list, 0, sizeof(quad_list[0]));
6892         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
6893         primtype = D3DPT_TRIANGLELIST;
6894         shademode = D3DSHADE_FLAT;
6895     }
6896
6897 bail:
6898     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
6899     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
6900     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
6901     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6902
6903     if (vb_strip)
6904         IDirect3DVertexBuffer9_Release(vb_strip);
6905     if (vb_list)
6906         IDirect3DVertexBuffer9_Release(vb_list);
6907 }
6908
6909 static void alpha_test(IDirect3DDevice9 *device)
6910 {
6911     HRESULT hr;
6912     IDirect3DTexture9 *offscreenTexture;
6913     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
6914     DWORD color;
6915
6916     struct vertex quad1[] =
6917     {
6918         {-1.0f, -1.0f,   0.1f,                          0x4000ff00},
6919         {-1.0f,  0.0f,   0.1f,                          0x4000ff00},
6920         { 1.0f, -1.0f,   0.1f,                          0x4000ff00},
6921         { 1.0f,  0.0f,   0.1f,                          0x4000ff00},
6922     };
6923     struct vertex quad2[] =
6924     {
6925         {-1.0f,  0.0f,   0.1f,                          0xc00000ff},
6926         {-1.0f,  1.0f,   0.1f,                          0xc00000ff},
6927         { 1.0f,  0.0f,   0.1f,                          0xc00000ff},
6928         { 1.0f,  1.0f,   0.1f,                          0xc00000ff},
6929     };
6930     static const float composite_quad[][5] = {
6931         { 0.0f, -1.0f, 0.1f, 0.0f, 1.0f},
6932         { 0.0f,  1.0f, 0.1f, 0.0f, 0.0f},
6933         { 1.0f, -1.0f, 0.1f, 1.0f, 1.0f},
6934         { 1.0f,  1.0f, 0.1f, 1.0f, 0.0f},
6935     };
6936
6937     /* Clear the render target with alpha = 0.5 */
6938     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
6939     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
6940
6941     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
6942     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr);
6943
6944     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
6945     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
6946     if(!backbuffer) {
6947         goto out;
6948     }
6949
6950     hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
6951     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %08x\n", hr);
6952     if(!offscreen) {
6953         goto out;
6954     }
6955
6956     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
6957     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr);
6958
6959     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
6960     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
6961     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
6962     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
6963     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
6964     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
6965     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
6966     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
6967     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
6968     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
6969
6970     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
6971     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6972     if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
6973
6974         /* Draw two quads, one with src alpha blending, one with dest alpha blending. */
6975         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
6976         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6977         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
6978         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6979         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
6980         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6981
6982         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
6983         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6984         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
6985         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6986         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
6987         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6988
6989         /* Switch to the offscreen buffer, and redo the testing. The offscreen render target
6990          * doesn't have an alpha channel. DESTALPHA and INVDESTALPHA "don't work" on render
6991          * targets without alpha channel, they give essentially ZERO and ONE blend factors. */
6992         hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
6993         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
6994         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
6995         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
6996
6997         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
6998         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6999         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
7000         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
7001         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
7002         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7003
7004         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
7005         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
7006         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
7007         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
7008         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
7009         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7010
7011         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
7012         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
7013
7014         /* Render the offscreen texture onto the frame buffer to be able to compare it regularly.
7015          * Disable alpha blending for the final composition
7016          */
7017         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
7018         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
7019         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7020         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr);
7021
7022         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
7023         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr = %08x\n", hr);
7024         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, composite_quad, sizeof(float) * 5);
7025         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7026         hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7027         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr = %08x\n", hr);
7028
7029         hr = IDirect3DDevice9_EndScene(device);
7030         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
7031     }
7032
7033     color = getPixelColor(device, 160, 360);
7034     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1),
7035        "SRCALPHA on frame buffer returned color %08x, expected 0x00bf4000\n", color);
7036
7037     color = getPixelColor(device, 160, 120);
7038     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x7f, 0x00, 0x80), 2),
7039        "DSTALPHA on frame buffer returned color %08x, expected 0x007f0080\n", color);
7040
7041     color = getPixelColor(device, 480, 360);
7042     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1),
7043        "SRCALPHA on texture returned color %08x, expected 0x00bf4000\n", color);
7044
7045     color = getPixelColor(device, 480, 120);
7046     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xff), 1),
7047        "DSTALPHA on texture returned color %08x, expected 0x000000ff\n", color);
7048
7049     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7050
7051     out:
7052     /* restore things */
7053     if(backbuffer) {
7054         IDirect3DSurface9_Release(backbuffer);
7055     }
7056     if(offscreenTexture) {
7057         IDirect3DTexture9_Release(offscreenTexture);
7058     }
7059     if(offscreen) {
7060         IDirect3DSurface9_Release(offscreen);
7061     }
7062 }
7063
7064 struct vertex_shortcolor {
7065     float x, y, z;
7066     unsigned short r, g, b, a;
7067 };
7068 struct vertex_floatcolor {
7069     float x, y, z;
7070     float r, g, b, a;
7071 };
7072
7073 static void fixed_function_decl_test(IDirect3DDevice9 *device)
7074 {
7075     HRESULT hr;
7076     BOOL s_ok, ub_ok, f_ok;
7077     DWORD color, size, i;
7078     void *data;
7079     static const D3DVERTEXELEMENT9 decl_elements_d3dcolor[] = {
7080         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7081         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7082         D3DDECL_END()
7083     };
7084     static const D3DVERTEXELEMENT9 decl_elements_d3dcolor_2streams[] = {
7085         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7086         {1,   0,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7087         D3DDECL_END()
7088     };
7089     static const D3DVERTEXELEMENT9 decl_elements_ubyte4n[] = {
7090         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7091         {0,  12,  D3DDECLTYPE_UBYTE4N,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7092         D3DDECL_END()
7093     };
7094     static const D3DVERTEXELEMENT9 decl_elements_ubyte4n_2streams[] = {
7095         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7096         {1,   0,  D3DDECLTYPE_UBYTE4N,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7097         D3DDECL_END()
7098     };
7099     static const D3DVERTEXELEMENT9 decl_elements_short4[] = {
7100         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7101         {0,  12,  D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7102         D3DDECL_END()
7103     };
7104     static const D3DVERTEXELEMENT9 decl_elements_float[] = {
7105         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7106         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7107         D3DDECL_END()
7108     };
7109     static const D3DVERTEXELEMENT9 decl_elements_positiont[] = {
7110         {0,   0,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT,      0},
7111         {0,  16,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7112         D3DDECL_END()
7113     };
7114     IDirect3DVertexDeclaration9 *dcl_float = NULL, *dcl_short = NULL, *dcl_ubyte = NULL, *dcl_color = NULL;
7115     IDirect3DVertexDeclaration9 *dcl_color_2 = NULL, *dcl_ubyte_2 = NULL, *dcl_positiont;
7116     IDirect3DVertexBuffer9 *vb, *vb2;
7117     struct vertex quad1[] =                             /* D3DCOLOR */
7118     {
7119         {-1.0f, -1.0f,   0.1f,                          0x00ffff00},
7120         {-1.0f,  0.0f,   0.1f,                          0x00ffff00},
7121         { 0.0f, -1.0f,   0.1f,                          0x00ffff00},
7122         { 0.0f,  0.0f,   0.1f,                          0x00ffff00},
7123     };
7124     struct vertex quad2[] =                             /* UBYTE4N */
7125     {
7126         {-1.0f,  0.0f,   0.1f,                          0x00ffff00},
7127         {-1.0f,  1.0f,   0.1f,                          0x00ffff00},
7128         { 0.0f,  0.0f,   0.1f,                          0x00ffff00},
7129         { 0.0f,  1.0f,   0.1f,                          0x00ffff00},
7130     };
7131     struct vertex_shortcolor quad3[] =                  /* short */
7132     {
7133         { 0.0f, -1.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
7134         { 0.0f,  0.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
7135         { 1.0f, -1.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
7136         { 1.0f,  0.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
7137     };
7138     struct vertex_floatcolor quad4[] =
7139     {
7140         { 0.0f,  0.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
7141         { 0.0f,  1.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
7142         { 1.0f,  0.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
7143         { 1.0f,  1.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
7144     };
7145     DWORD colors[] = {
7146         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7147         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7148         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7149         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7150         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7151         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7152         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7153         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7154         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7155         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7156         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7157         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7158         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7159         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7160         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7161         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
7162     };
7163     float quads[] = {
7164         -1.0,   -1.0,     0.1,
7165         -1.0,    0.0,     0.1,
7166          0.0,   -1.0,     0.1,
7167          0.0,    0.0,     0.1,
7168
7169          0.0,   -1.0,     0.1,
7170          0.0,    0.0,     0.1,
7171          1.0,   -1.0,     0.1,
7172          1.0,    0.0,     0.1,
7173
7174          0.0,    0.0,     0.1,
7175          0.0,    1.0,     0.1,
7176          1.0,    0.0,     0.1,
7177          1.0,    1.0,     0.1,
7178
7179         -1.0,    0.0,     0.1,
7180         -1.0,    1.0,     0.1,
7181          0.0,    0.0,     0.1,
7182          0.0,    1.0,     0.1
7183     };
7184     struct tvertex quad_transformed[] = {
7185        {  90,    110,     0.1,      2.0,        0x00ffff00},
7186        { 570,    110,     0.1,      2.0,        0x00ffff00},
7187        {  90,    300,     0.1,      2.0,        0x00ffff00},
7188        { 570,    300,     0.1,      2.0,        0x00ffff00}
7189     };
7190     D3DCAPS9 caps;
7191
7192     memset(&caps, 0, sizeof(caps));
7193     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7194     ok(hr == D3D_OK, "GetDeviceCaps failed, hr = %08x\n", hr);
7195
7196     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
7197     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
7198
7199     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_d3dcolor, &dcl_color);
7200     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7201     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_short4, &dcl_short);
7202     ok(SUCCEEDED(hr) || hr == E_FAIL, "CreateVertexDeclaration failed (%08x)\n", hr);
7203     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_float, &dcl_float);
7204     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7205     if(caps.DeclTypes & D3DDTCAPS_UBYTE4N) {
7206         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_ubyte4n_2streams, &dcl_ubyte_2);
7207         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7208         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_ubyte4n, &dcl_ubyte);
7209         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7210     } else {
7211         trace("D3DDTCAPS_UBYTE4N not supported\n");
7212         dcl_ubyte_2 = NULL;
7213         dcl_ubyte = NULL;
7214     }
7215     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_d3dcolor_2streams, &dcl_color_2);
7216     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7217     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_positiont, &dcl_positiont);
7218     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
7219
7220     size = max(sizeof(quad1), max(sizeof(quad2), max(sizeof(quad3), max(sizeof(quad4), sizeof(quads)))));
7221     hr = IDirect3DDevice9_CreateVertexBuffer(device, size,
7222                                              0, 0, D3DPOOL_MANAGED, &vb, NULL);
7223     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
7224
7225     hr = IDirect3DDevice9_BeginScene(device);
7226     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
7227     f_ok = FALSE; s_ok = FALSE; ub_ok = FALSE;
7228     if(SUCCEEDED(hr)) {
7229         if(dcl_color) {
7230             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color);
7231             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7232             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
7233             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7234         }
7235
7236         /* Tests with non-standard fixed function types fail on the refrast. The ATI driver partially
7237          * accepts them, the nvidia driver accepts them all. All those differences even though we're
7238          * using software vertex processing. Doh!
7239          */
7240         if(dcl_ubyte) {
7241             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte);
7242             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7243             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
7244             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7245             ub_ok = SUCCEEDED(hr);
7246         }
7247
7248         if(dcl_short) {
7249             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_short);
7250             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7251             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(quad3[0]));
7252             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7253             s_ok = SUCCEEDED(hr);
7254         }
7255
7256         if(dcl_float) {
7257             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_float);
7258             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7259             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(quad4[0]));
7260             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7261             f_ok = SUCCEEDED(hr);
7262         }
7263
7264         hr = IDirect3DDevice9_EndScene(device);
7265         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr = %#08x\n", hr);
7266     }
7267
7268     if(dcl_short) {
7269         color = getPixelColor(device, 480, 360);
7270         ok(color == 0x000000ff || !s_ok,
7271            "D3DDECLTYPE_USHORT4N returned color %08x, expected 0x000000ff\n", color);
7272     }
7273     if(dcl_ubyte) {
7274         color = getPixelColor(device, 160, 120);
7275         ok(color == 0x0000ffff || !ub_ok,
7276            "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x0000ffff\n", color);
7277     }
7278     if(dcl_color) {
7279         color = getPixelColor(device, 160, 360);
7280         ok(color == 0x00ffff00,
7281            "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ffff00\n", color);
7282     }
7283     if(dcl_float) {
7284         color = getPixelColor(device, 480, 120);
7285         ok(color == 0x00ff0000 || !f_ok,
7286            "D3DDECLTYPE_FLOAT4 returned color %08x, expected 0x00ff0000\n", color);
7287     }
7288     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7289
7290     /* The following test with vertex buffers doesn't serve to find out new information from windows.
7291      * It is a plain regression test because wined3d uses different codepaths for attribute conversion
7292      * with vertex buffers. It makes sure that the vertex buffer one works, while the above tests
7293      * whether the immediate mode code works
7294      */
7295     f_ok = FALSE; s_ok = FALSE; ub_ok = FALSE;
7296     hr = IDirect3DDevice9_BeginScene(device);
7297     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
7298     if(SUCCEEDED(hr)) {
7299         if(dcl_color) {
7300             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad1), &data, 0);
7301             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7302             memcpy(data, quad1, sizeof(quad1));
7303             hr = IDirect3DVertexBuffer9_Unlock(vb);
7304             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7305             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color);
7306             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7307             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad1[0]));
7308             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7309             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7310             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7311         }
7312
7313         if(dcl_ubyte) {
7314             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad2), &data, 0);
7315             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7316             memcpy(data, quad2, sizeof(quad2));
7317             hr = IDirect3DVertexBuffer9_Unlock(vb);
7318             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7319             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte);
7320             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7321             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad2[0]));
7322             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7323             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7324             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7325                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7326             ub_ok = SUCCEEDED(hr);
7327         }
7328
7329         if(dcl_short) {
7330             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad3), &data, 0);
7331             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7332             memcpy(data, quad3, sizeof(quad3));
7333             hr = IDirect3DVertexBuffer9_Unlock(vb);
7334             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7335             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_short);
7336             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7337             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad3[0]));
7338             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7339             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7340             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7341                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7342             s_ok = SUCCEEDED(hr);
7343         }
7344
7345         if(dcl_float) {
7346             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad4), &data, 0);
7347             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7348             memcpy(data, quad4, sizeof(quad4));
7349             hr = IDirect3DVertexBuffer9_Unlock(vb);
7350             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7351             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_float);
7352             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7353             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad4[0]));
7354             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7355             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7356             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7357                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7358             f_ok = SUCCEEDED(hr);
7359         }
7360
7361         hr = IDirect3DDevice9_EndScene(device);
7362         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr = %#08x\n", hr);
7363     }
7364
7365     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
7366     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7367     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
7368     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7369
7370     if(dcl_short) {
7371         color = getPixelColor(device, 480, 360);
7372         ok(color == 0x000000ff || !s_ok,
7373            "D3DDECLTYPE_USHORT4N returned color %08x, expected 0x000000ff\n", color);
7374     }
7375     if(dcl_ubyte) {
7376         color = getPixelColor(device, 160, 120);
7377         ok(color == 0x0000ffff || !ub_ok,
7378            "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x0000ffff\n", color);
7379     }
7380     if(dcl_color) {
7381         color = getPixelColor(device, 160, 360);
7382         ok(color == 0x00ffff00,
7383            "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ffff00\n", color);
7384     }
7385     if(dcl_float) {
7386         color = getPixelColor(device, 480, 120);
7387         ok(color == 0x00ff0000 || !f_ok,
7388            "D3DDECLTYPE_FLOAT4 returned color %08x, expected 0x00ff0000\n", color);
7389     }
7390     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7391
7392     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
7393     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
7394
7395     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad_transformed), &data, 0);
7396     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7397     memcpy(data, quad_transformed, sizeof(quad_transformed));
7398     hr = IDirect3DVertexBuffer9_Unlock(vb);
7399     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7400
7401     hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_positiont);
7402     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7403
7404     hr = IDirect3DDevice9_BeginScene(device);
7405     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7406     if(SUCCEEDED(hr)) {
7407         hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad_transformed[0]));
7408         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7409         hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7410         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7411
7412         hr = IDirect3DDevice9_EndScene(device);
7413         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7414     }
7415
7416     color = getPixelColor(device, 88, 108);
7417     ok(color == 0x000000ff,
7418        "pixel 88/108 has color %08x, expected 0x000000ff\n", color);
7419     color = getPixelColor(device, 92, 108);
7420     ok(color == 0x000000ff,
7421        "pixel 92/108 has color %08x, expected 0x000000ff\n", color);
7422     color = getPixelColor(device, 88, 112);
7423     ok(color == 0x000000ff,
7424        "pixel 88/112 has color %08x, expected 0x000000ff\n", color);
7425     color = getPixelColor(device, 92, 112);
7426     ok(color == 0x00ffff00,
7427        "pixel 92/112 has color %08x, expected 0x00ffff00\n", color);
7428
7429     color = getPixelColor(device, 568, 108);
7430     ok(color == 0x000000ff,
7431        "pixel 568/108 has color %08x, expected 0x000000ff\n", color);
7432     color = getPixelColor(device, 572, 108);
7433     ok(color == 0x000000ff,
7434        "pixel 572/108 has color %08x, expected 0x000000ff\n", color);
7435     color = getPixelColor(device, 568, 112);
7436     ok(color == 0x00ffff00,
7437        "pixel 568/112 has color %08x, expected 0x00ffff00\n", color);
7438     color = getPixelColor(device, 572, 112);
7439     ok(color == 0x000000ff,
7440        "pixel 572/112 has color %08x, expected 0x000000ff\n", color);
7441
7442     color = getPixelColor(device, 88, 298);
7443     ok(color == 0x000000ff,
7444        "pixel 88/298 has color %08x, expected 0x000000ff\n", color);
7445     color = getPixelColor(device, 92, 298);
7446     ok(color == 0x00ffff00,
7447        "pixel 92/298 has color %08x, expected 0x00ffff00\n", color);
7448     color = getPixelColor(device, 88, 302);
7449     ok(color == 0x000000ff,
7450        "pixel 88/302 has color %08x, expected 0x000000ff\n", color);
7451     color = getPixelColor(device, 92, 302);
7452     ok(color == 0x000000ff,
7453        "pixel 92/302 has color %08x, expected 0x000000ff\n", color);
7454
7455     color = getPixelColor(device, 568, 298);
7456     ok(color == 0x00ffff00,
7457        "pixel 568/298 has color %08x, expected 0x00ffff00\n", color);
7458     color = getPixelColor(device, 572, 298);
7459     ok(color == 0x000000ff,
7460        "pixel 572/298 has color %08x, expected 0x000000ff\n", color);
7461     color = getPixelColor(device, 568, 302);
7462     ok(color == 0x000000ff,
7463        "pixel 568/302 has color %08x, expected 0x000000ff\n", color);
7464     color = getPixelColor(device, 572, 302);
7465     ok(color == 0x000000ff,
7466        "pixel 572/302 has color %08x, expected 0x000000ff\n", color);
7467
7468     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7469
7470     /* This test is pointless without those two declarations: */
7471     if((!dcl_color_2) || (!dcl_ubyte_2)) {
7472         skip("color-ubyte switching test declarations aren't supported\n");
7473         goto out;
7474     }
7475
7476     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quads), &data, 0);
7477     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7478     memcpy(data, quads, sizeof(quads));
7479     hr = IDirect3DVertexBuffer9_Unlock(vb);
7480     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7481     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(colors),
7482                                              0, 0, D3DPOOL_MANAGED, &vb2, NULL);
7483     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
7484     hr = IDirect3DVertexBuffer9_Lock(vb2, 0, sizeof(colors), &data, 0);
7485     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
7486     memcpy(data, colors, sizeof(colors));
7487     hr = IDirect3DVertexBuffer9_Unlock(vb2);
7488     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7489
7490     for(i = 0; i < 2; i++) {
7491         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
7492         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
7493
7494         hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(float) * 3);
7495         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7496         if(i == 0) {
7497             hr = IDirect3DDevice9_SetStreamSource(device, 1, vb2, 0, sizeof(DWORD) * 4);
7498         } else {
7499             hr = IDirect3DDevice9_SetStreamSource(device, 1, vb2, 8, sizeof(DWORD) * 4);
7500         }
7501         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7502
7503         hr = IDirect3DDevice9_BeginScene(device);
7504         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
7505         ub_ok = FALSE;
7506         if(SUCCEEDED(hr)) {
7507             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2);
7508             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7509             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7510             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7511                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7512             ub_ok = SUCCEEDED(hr);
7513
7514             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color_2);
7515             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7516             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 4, 2);
7517             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7518
7519             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2);
7520             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x\n", hr);
7521             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 8, 2);
7522             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7523                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7524             ub_ok = (SUCCEEDED(hr) && ub_ok);
7525
7526             hr = IDirect3DDevice9_EndScene(device);
7527             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
7528         }
7529
7530         if(i == 0) {
7531             color = getPixelColor(device, 480, 360);
7532             ok(color == 0x00ff0000,
7533                "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ff0000\n", color);
7534             color = getPixelColor(device, 160, 120);
7535             ok(color == 0x00ffffff,
7536                 "Unused quad returned color %08x, expected 0x00ffffff\n", color);
7537             color = getPixelColor(device, 160, 360);
7538             ok(color == 0x000000ff || !ub_ok,
7539                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x000000ff\n", color);
7540             color = getPixelColor(device, 480, 120);
7541             ok(color == 0x000000ff || !ub_ok,
7542                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x000000ff\n", color);
7543         } else {
7544             color = getPixelColor(device, 480, 360);
7545             ok(color == 0x000000ff,
7546                "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x000000ff\n", color);
7547             color = getPixelColor(device, 160, 120);
7548             ok(color == 0x00ffffff,
7549                "Unused quad returned color %08x, expected 0x00ffffff\n", color);
7550             color = getPixelColor(device, 160, 360);
7551             ok(color == 0x00ff0000 || !ub_ok,
7552                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x00ff0000\n", color);
7553             color = getPixelColor(device, 480, 120);
7554             ok(color == 0x00ff0000 || !ub_ok,
7555                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x00ff0000\n", color);
7556         }
7557         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7558     }
7559
7560     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
7561     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7562     hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
7563     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x\n", hr);
7564     IDirect3DVertexBuffer9_Release(vb2);
7565
7566     out:
7567     IDirect3DVertexBuffer9_Release(vb);
7568     if(dcl_float) IDirect3DVertexDeclaration9_Release(dcl_float);
7569     if(dcl_short) IDirect3DVertexDeclaration9_Release(dcl_short);
7570     if(dcl_ubyte) IDirect3DVertexDeclaration9_Release(dcl_ubyte);
7571     if(dcl_color) IDirect3DVertexDeclaration9_Release(dcl_color);
7572     if(dcl_color_2) IDirect3DVertexDeclaration9_Release(dcl_color_2);
7573     if(dcl_ubyte_2) IDirect3DVertexDeclaration9_Release(dcl_ubyte_2);
7574     if(dcl_positiont) IDirect3DVertexDeclaration9_Release(dcl_positiont);
7575 }
7576
7577 struct vertex_float16color {
7578     float x, y, z;
7579     DWORD c1, c2;
7580 };
7581
7582 static void test_vshader_float16(IDirect3DDevice9 *device)
7583 {
7584     HRESULT hr;
7585     DWORD color;
7586     void *data;
7587     static const D3DVERTEXELEMENT9 decl_elements[] = {
7588         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7589         {0,  12,  D3DDECLTYPE_FLOAT16_4,D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7590         D3DDECL_END()
7591     };
7592     IDirect3DVertexDeclaration9 *vdecl = NULL;
7593     IDirect3DVertexBuffer9 *buffer = NULL;
7594     IDirect3DVertexShader9 *shader;
7595     DWORD shader_code[] = {
7596         0xfffe0101, 0x0000001f, 0x80000000, 0x900f0000, 0x0000001f, 0x8000000a,
7597         0x900f0001, 0x00000001, 0xc00f0000, 0x90e40000, 0x00000001, 0xd00f0000,
7598         0x90e40001, 0x0000ffff
7599     };
7600     struct vertex_float16color quad[] = {
7601         { -1.0,   -1.0,     0.1,        0x3c000000, 0x00000000 }, /* green */
7602         { -1.0,    0.0,     0.1,        0x3c000000, 0x00000000 },
7603         {  0.0,   -1.0,     0.1,        0x3c000000, 0x00000000 },
7604         {  0.0,    0.0,     0.1,        0x3c000000, 0x00000000 },
7605
7606         {  0.0,   -1.0,     0.1,        0x00003c00, 0x00000000 }, /* red */
7607         {  0.0,    0.0,     0.1,        0x00003c00, 0x00000000 },
7608         {  1.0,   -1.0,     0.1,        0x00003c00, 0x00000000 },
7609         {  1.0,    0.0,     0.1,        0x00003c00, 0x00000000 },
7610
7611         {  0.0,    0.0,     0.1,        0x00000000, 0x00003c00 }, /* blue */
7612         {  0.0,    1.0,     0.1,        0x00000000, 0x00003c00 },
7613         {  1.0,    0.0,     0.1,        0x00000000, 0x00003c00 },
7614         {  1.0,    1.0,     0.1,        0x00000000, 0x00003c00 },
7615
7616         { -1.0,    0.0,     0.1,        0x00000000, 0x3c000000 }, /* alpha */
7617         { -1.0,    1.0,     0.1,        0x00000000, 0x3c000000 },
7618         {  0.0,    0.0,     0.1,        0x00000000, 0x3c000000 },
7619         {  0.0,    1.0,     0.1,        0x00000000, 0x3c000000 },
7620     };
7621
7622     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff102030, 0.0, 0);
7623     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7624
7625     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vdecl);
7626     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed hr=%08x\n", hr);
7627     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
7628     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexShader failed hr=%08x\n", hr);
7629     hr = IDirect3DDevice9_SetVertexShader(device, shader);
7630     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
7631
7632     hr = IDirect3DDevice9_BeginScene(device);
7633     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
7634     if(SUCCEEDED(hr)) {
7635         hr = IDirect3DDevice9_SetVertexDeclaration(device, vdecl);
7636         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%08x\n", hr);
7637         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad +  0, sizeof(quad[0]));
7638         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7639         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad +  4, sizeof(quad[0]));
7640         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7641         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad +  8, sizeof(quad[0]));
7642         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7643         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad + 12, sizeof(quad[0]));
7644         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7645
7646         hr = IDirect3DDevice9_EndScene(device);
7647         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%08x\n", hr);
7648     }
7649     color = getPixelColor(device, 480, 360);
7650     ok(color == 0x00ff0000,
7651        "Input 0x00003c00, 0x00000000 returned color %08x, expected 0x00ff0000\n", color);
7652     color = getPixelColor(device, 160, 120);
7653     ok(color == 0x00000000,
7654        "Input 0x00000000, 0x3c000000 returned color %08x, expected 0x00000000\n", color);
7655     color = getPixelColor(device, 160, 360);
7656     ok(color == 0x0000ff00,
7657        "Input 0x3c000000, 0x00000000 returned color %08x, expected 0x0000ff00\n", color);
7658     color = getPixelColor(device, 480, 120);
7659     ok(color == 0x000000ff,
7660        "Input 0x00000000, 0x00003c00 returned color %08x, expected 0x000000ff\n", color);
7661     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7662
7663     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff102030, 0.0, 0);
7664     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7665
7666     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0,
7667                                              D3DPOOL_MANAGED, &buffer, NULL);
7668     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexBuffer failed, hr=%08x\n", hr);
7669     hr = IDirect3DVertexBuffer9_Lock(buffer, 0, sizeof(quad), &data, 0);
7670     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed, hr=%08x\n", hr);
7671     memcpy(data, quad, sizeof(quad));
7672     hr = IDirect3DVertexBuffer9_Unlock(buffer);
7673     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed, hr=%08x\n", hr);
7674     hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(quad[0]));
7675     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed, hr=%08x\n", hr);
7676
7677     hr = IDirect3DDevice9_BeginScene(device);
7678     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
7679     if(SUCCEEDED(hr)) {
7680             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,  0, 2);
7681             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7682             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,  4, 2);
7683             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7684             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,  8, 2);
7685             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7686             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 12, 2);
7687             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7688
7689             hr = IDirect3DDevice9_EndScene(device);
7690             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%08x\n", hr);
7691     }
7692
7693     color = getPixelColor(device, 480, 360);
7694     ok(color == 0x00ff0000,
7695        "Input 0x00003c00, 0x00000000 returned color %08x, expected 0x00ff0000\n", color);
7696     color = getPixelColor(device, 160, 120);
7697     ok(color == 0x00000000,
7698        "Input 0x00000000, 0x3c000000 returned color %08x, expected 0x00000000\n", color);
7699     color = getPixelColor(device, 160, 360);
7700     ok(color == 0x0000ff00,
7701        "Input 0x3c000000, 0x00000000 returned color %08x, expected 0x0000ff00\n", color);
7702     color = getPixelColor(device, 480, 120);
7703     ok(color == 0x000000ff,
7704        "Input 0x00000000, 0x00003c00 returned color %08x, expected 0x000000ff\n", color);
7705     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7706
7707     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
7708     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed, hr=%08x\n", hr);
7709     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
7710     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%08x\n", hr);
7711     IDirect3DDevice9_SetVertexShader(device, NULL);
7712     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
7713
7714     IDirect3DVertexDeclaration9_Release(vdecl);
7715     IDirect3DVertexShader9_Release(shader);
7716     IDirect3DVertexBuffer9_Release(buffer);
7717 }
7718
7719 static void conditional_np2_repeat_test(IDirect3DDevice9 *device)
7720 {
7721     D3DCAPS9 caps;
7722     IDirect3DTexture9 *texture;
7723     HRESULT hr;
7724     D3DLOCKED_RECT rect;
7725     unsigned int x, y;
7726     DWORD *dst, color;
7727     const float quad[] = {
7728         -1.0,   -1.0,   0.1,   -0.2,   -0.2,
7729          1.0,   -1.0,   0.1,    1.2,   -0.2,
7730         -1.0,    1.0,   0.1,   -0.2,    1.2,
7731          1.0,    1.0,   0.1,    1.2,    1.2
7732     };
7733     memset(&caps, 0, sizeof(caps));
7734
7735     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7736     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%08x\n", hr);
7737     if(!(caps.TextureCaps & D3DPTEXTURECAPS_POW2)) {
7738         /* NP2 conditional requires the POW2 flag. Check that while we're at it */
7739         ok((caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) == 0,
7740            "Card has conditional NP2 support without power of two restriction set\n");
7741         skip("Card has unconditional pow2 support, skipping conditional NP2 tests\n");
7742         return;
7743     } else if(!(caps.TextureCaps & D3DPTEXTURECAPS_POW2)) {
7744         skip("No conditional NP2 support, skipping conditional NP2 tests\n");
7745         return;
7746     }
7747
7748     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
7749     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7750
7751     hr = IDirect3DDevice9_CreateTexture(device, 10, 10, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7752     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed hr=%08x\n", hr);
7753
7754     memset(&rect, 0, sizeof(rect));
7755     hr = IDirect3DTexture9_LockRect(texture, 0, &rect, NULL, 0);
7756     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed hr=%08x\n", hr);
7757     for(y = 0; y < 10; y++) {
7758         for(x = 0; x < 10; x++) {
7759             dst = (DWORD *) ((BYTE *) rect.pBits + y * rect.Pitch + x * sizeof(DWORD));
7760             if(x == 0 || x == 9 || y == 0 || y == 9) {
7761                 *dst = 0x00ff0000;
7762             } else {
7763                 *dst = 0x000000ff;
7764             }
7765         }
7766     }
7767     hr = IDirect3DTexture9_UnlockRect(texture, 0);
7768     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed hr=%08x\n", hr);
7769
7770     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
7771     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
7772     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
7773     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed hr=%08x\n", hr);
7774     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
7775     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed hr=%08x\n", hr);
7776     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7777     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%08x\n", hr);
7778
7779     hr = IDirect3DDevice9_BeginScene(device);
7780     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
7781     if(SUCCEEDED(hr)) {
7782         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
7783         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7784
7785         hr = IDirect3DDevice9_EndScene(device);
7786         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
7787     }
7788
7789     color = getPixelColor(device,    1,  1);
7790     ok(color == 0x00ff0000, "NP2: Pixel   1,  1 has color %08x, expected 0x00ff0000\n", color);
7791     color = getPixelColor(device, 639, 479);
7792     ok(color == 0x00ff0000, "NP2: Pixel 639, 479 has color %08x, expected 0x00ff0000\n", color);
7793
7794     color = getPixelColor(device, 135, 101);
7795     ok(color == 0x00ff0000, "NP2: Pixel 135, 101 has color %08x, expected 0x00ff0000\n", color);
7796     color = getPixelColor(device, 140, 101);
7797     ok(color == 0x00ff0000, "NP2: Pixel 140, 101 has color %08x, expected 0x00ff0000\n", color);
7798     color = getPixelColor(device, 135, 105);
7799     ok(color == 0x00ff0000, "NP2: Pixel 135, 105 has color %08x, expected 0x00ff0000\n", color);
7800     color = getPixelColor(device, 140, 105);
7801     ok(color == 0x000000ff, "NP2: Pixel 140, 105 has color %08x, expected 0x000000ff\n", color);
7802
7803     color = getPixelColor(device, 135, 376);
7804     ok(color == 0x00ff0000, "NP2: Pixel 135, 376 has color %08x, expected 0x00ff0000\n", color);
7805     color = getPixelColor(device, 140, 376);
7806     ok(color == 0x000000ff, "NP2: Pixel 140, 376 has color %08x, expected 0x000000ff\n", color);
7807     color = getPixelColor(device, 135, 379);
7808     ok(color == 0x00ff0000, "NP2: Pixel 135, 379 has color %08x, expected 0x00ff0000\n", color);
7809     color = getPixelColor(device, 140, 379);
7810     ok(color == 0x00ff0000, "NP2: Pixel 140, 379 has color %08x, expected 0x00ff0000\n", color);
7811
7812     color = getPixelColor(device, 500, 101);
7813     ok(color == 0x00ff0000, "NP2: Pixel 500, 101 has color %08x, expected 0x00ff0000\n", color);
7814     color = getPixelColor(device, 504, 101);
7815     ok(color == 0x00ff0000, "NP2: Pixel 504, 101 has color %08x, expected 0x00ff0000\n", color);
7816     color = getPixelColor(device, 500, 105);
7817     ok(color == 0x000000ff, "NP2: Pixel 500, 105 has color %08x, expected 0x000000ff\n", color);
7818     color = getPixelColor(device, 504, 105);
7819     ok(color == 0x00ff0000, "NP2: Pixel 504, 105 has color %08x, expected 0x00ff0000\n", color);
7820
7821     color = getPixelColor(device, 500, 376);
7822     ok(color == 0x000000ff, "NP2: Pixel 500, 376 has color %08x, expected 0x000000ff\n", color);
7823     color = getPixelColor(device, 504, 376);
7824     ok(color == 0x00ff0000, "NP2: Pixel 504, 376 has color %08x, expected 0x00ff0000\n", color);
7825     color = getPixelColor(device, 500, 380);
7826     ok(color == 0x00ff0000, "NP2: Pixel 500, 380 has color %08x, expected 0x00ff0000\n", color);
7827     color = getPixelColor(device, 504, 380);
7828     ok(color == 0x00ff0000, "NP2: Pixel 504, 380 has color %08x, expected 0x00ff0000\n", color);
7829
7830     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7831
7832     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7833     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
7834     IDirect3DTexture9_Release(texture);
7835 }
7836
7837 static void vFace_register_test(IDirect3DDevice9 *device)
7838 {
7839     HRESULT hr;
7840     DWORD color;
7841     const DWORD shader_code[] = {
7842         0xffff0300,                                                             /* ps_3_0                     */
7843         0x05000051, 0xa00f0000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c0, 0.0, 1.0, 0.0, 0.0 */
7844         0x05000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1, 1.0, 0.0, 0.0, 0.0 */
7845         0x0200001f, 0x80000000, 0x900f1001,                                     /* dcl vFace                  */
7846         0x02000001, 0x800f0001, 0xa0e40001,                                     /* mov r1, c1                 */
7847         0x04000058, 0x800f0000, 0x90e41001, 0xa0e40000, 0x80e40001,             /* cmp r0, vFace, c0, r1      */
7848         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                */
7849         0x0000ffff                                                              /* END                        */
7850     };
7851     const DWORD vshader_code[] = {
7852         0xfffe0300,                                                             /* vs_3_0               */
7853         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0      */
7854         0x0200001f, 0x80000000, 0xe00f0000,                                     /* dcl_position o0      */
7855         0x02000001, 0xe00f0000, 0x90e40000,                                     /* mov o0, v0           */
7856         0x0000ffff                                                              /* end                  */
7857     };
7858     IDirect3DPixelShader9 *shader;
7859     IDirect3DVertexShader9 *vshader;
7860     IDirect3DTexture9 *texture;
7861     IDirect3DSurface9 *surface, *backbuffer;
7862     const float quad[] = {
7863         -1.0,   -1.0,   0.1,
7864          1.0,   -1.0,   0.1,
7865         -1.0,    0.0,   0.1,
7866
7867          1.0,   -1.0,   0.1,
7868          1.0,    0.0,   0.1,
7869         -1.0,    0.0,   0.1,
7870
7871         -1.0,    0.0,   0.1,
7872         -1.0,    1.0,   0.1,
7873          1.0,    0.0,   0.1,
7874
7875          1.0,    0.0,   0.1,
7876         -1.0,    1.0,   0.1,
7877          1.0,    1.0,   0.1,
7878     };
7879     const float blit[] = {
7880          0.0,   -1.0,   0.1,    0.0,    0.0,
7881          1.0,   -1.0,   0.1,    1.0,    0.0,
7882          0.0,    1.0,   0.1,    0.0,    1.0,
7883          1.0,    1.0,   0.1,    1.0,    1.0,
7884     };
7885
7886     hr = IDirect3DDevice9_CreateVertexShader(device, vshader_code, &vshader);
7887     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader failed hr=%08x\n", hr);
7888     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
7889     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed hr=%08x\n", hr);
7890     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7891     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed hr=%08x\n", hr);
7892     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7893     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed hr=%08x\n", hr);
7894     hr = IDirect3DDevice9_SetPixelShader(device, shader);
7895     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
7896     hr = IDirect3DDevice9_SetVertexShader(device, vshader);
7897     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
7898     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
7899     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
7900     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7901     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed hr=%08x\n", hr);
7902
7903     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
7904     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7905
7906     hr = IDirect3DDevice9_BeginScene(device);
7907     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
7908     if(SUCCEEDED(hr)) {
7909         /* First, draw to the texture and the back buffer to test both offscreen and onscreen cases */
7910         hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
7911         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
7912         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
7913         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
7914         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 4, quad, sizeof(float) * 3);
7915         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7916         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
7917         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
7918         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 4, quad, sizeof(float) * 3);
7919         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7920
7921         /* Blit the texture onto the back buffer to make it visible */
7922         hr = IDirect3DDevice9_SetVertexShader(device, NULL);
7923         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed, hr=%08x\n", hr);
7924         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
7925         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed, hr=%08x\n", hr);
7926         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
7927         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
7928         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
7929         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed, hr=%08x\n", hr);
7930         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
7931         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed, hr=%08x\n", hr);
7932         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7933         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
7934
7935         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, blit, sizeof(float) * 5);
7936         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
7937
7938         hr = IDirect3DDevice9_EndScene(device);
7939         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
7940     }
7941
7942     color = getPixelColor(device, 160, 360);
7943     ok(color == 0x00ff0000, "vFace: Onscreen rendered front facing quad has color 0x%08x, expected 0x00ff0000\n", color);
7944     color = getPixelColor(device, 160, 120);
7945     ok(color == 0x0000ff00, "vFace: Onscreen rendered back facing quad has color 0x%08x, expected 0x0000ff00\n", color);
7946     color = getPixelColor(device, 480, 360);
7947     ok(color == 0x0000ff00, "vFace: Offscreen rendered back facing quad has color 0x%08x, expected 0x0000ff00\n", color);
7948     color = getPixelColor(device, 480, 120);
7949     ok(color == 0x00ff0000, "vFace: Offscreen rendered front facing quad has color 0x%08x, expected 0x00ff0000\n", color);
7950     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7951
7952     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
7953     IDirect3DDevice9_SetTexture(device, 0, NULL);
7954     IDirect3DPixelShader9_Release(shader);
7955     IDirect3DVertexShader9_Release(vshader);
7956     IDirect3DSurface9_Release(surface);
7957     IDirect3DSurface9_Release(backbuffer);
7958     IDirect3DTexture9_Release(texture);
7959 }
7960
7961 static void fixed_function_bumpmap_test(IDirect3DDevice9 *device)
7962 {
7963     HRESULT hr;
7964     DWORD color;
7965     int i;
7966     D3DCAPS9 caps;
7967     BOOL L6V5U5_supported = FALSE;
7968     IDirect3DTexture9 *tex1, *tex2;
7969     D3DLOCKED_RECT locked_rect;
7970
7971     static const float quad[][7] = {
7972         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f},
7973         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f},
7974         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 1.0f, 0.0f},
7975         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 1.0f, 1.0f},
7976     };
7977
7978     static const D3DVERTEXELEMENT9 decl_elements[] = {
7979         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7980         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
7981         {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
7982         D3DDECL_END()
7983     };
7984
7985     /* use asymmetric matrix to test loading */
7986     float bumpenvmat[4] = {0.0,0.5,-0.5,0.0};
7987     float scale, offset;
7988
7989     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
7990     IDirect3DTexture9           *texture            = NULL;
7991
7992     memset(&caps, 0, sizeof(caps));
7993     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7994     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%08x\n", hr);
7995     if(!(caps.TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAP)) {
7996         skip("D3DTEXOPCAPS_BUMPENVMAP not set, skipping bumpmap tests\n");
7997         return;
7998     } else {
7999         /* This check is disabled, some Windows drivers do not handle D3DUSAGE_QUERY_LEGACYBUMPMAP properly.
8000          * They report that it is not supported, but after that bump mapping works properly. So just test
8001          * if the format is generally supported, and check the BUMPENVMAP flag
8002          */
8003         IDirect3D9 *d3d9;
8004
8005         IDirect3DDevice9_GetDirect3D(device, &d3d9);
8006         hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
8007                                           D3DRTYPE_TEXTURE, D3DFMT_L6V5U5);
8008         L6V5U5_supported = SUCCEEDED(hr);
8009         hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
8010                                           D3DRTYPE_TEXTURE, D3DFMT_V8U8);
8011         IDirect3D9_Release(d3d9);
8012         if(FAILED(hr)) {
8013             skip("D3DFMT_V8U8 not supported for legacy bump mapping\n");
8014             return;
8015         }
8016     }
8017
8018     /* Generate the textures */
8019     generate_bumpmap_textures(device);
8020
8021     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
8022     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8023     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
8024     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8025     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
8026     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8027     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
8028     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8029
8030     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BUMPENVMAP);
8031     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8032     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
8033     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8034     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_CURRENT );
8035     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8036
8037     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
8038     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8039     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
8040     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8041     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
8042     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8043
8044     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
8045     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8046
8047     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
8048     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
8049
8050     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
8051     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
8052
8053
8054     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
8055     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
8056     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
8057     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
8058
8059     hr = IDirect3DDevice9_BeginScene(device);
8060     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
8061
8062     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
8063     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
8064
8065     hr = IDirect3DDevice9_EndScene(device);
8066     ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
8067
8068     /* on MacOS(10.5.4, radeon X1600), the white dots are have color 0x00fbfbfb rather than 0x00ffffff. This is
8069      * kinda strange since no calculations are done on the sampled colors, only on the texture coordinates.
8070      * But since testing the color match is not the purpose of the test don't be too picky
8071      */
8072     color = getPixelColor(device, 320-32, 240);
8073     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
8074     color = getPixelColor(device, 320+32, 240);
8075     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
8076     color = getPixelColor(device, 320, 240-32);
8077     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
8078     color = getPixelColor(device, 320, 240+32);
8079     ok(color_match(color, 0x00ffffff, 4), "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
8080     color = getPixelColor(device, 320, 240);
8081     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
8082     color = getPixelColor(device, 320+32, 240+32);
8083     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
8084     color = getPixelColor(device, 320-32, 240+32);
8085     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
8086     color = getPixelColor(device, 320+32, 240-32);
8087     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
8088     color = getPixelColor(device, 320-32, 240-32);
8089     ok(color_match(color, 0x00000000, 4), "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
8090     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8091     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
8092
8093     for(i = 0; i < 2; i++) {
8094         hr = IDirect3DDevice9_GetTexture(device, i, (IDirect3DBaseTexture9 **) &texture);
8095         ok(SUCCEEDED(hr), "IDirect3DDevice9_GetTexture failed (0x%08x)\n", hr);
8096         IDirect3DTexture9_Release(texture); /* For the GetTexture */
8097         hr = IDirect3DDevice9_SetTexture(device, i, NULL);
8098         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
8099         IDirect3DTexture9_Release(texture); /* To destroy it */
8100     }
8101
8102     if(!(caps.TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAPLUMINANCE)) {
8103         skip("D3DTOP_BUMPENVMAPLUMINANCE not supported, skipping\n");
8104         goto cleanup;
8105     }
8106     if(L6V5U5_supported == FALSE) {
8107         skip("L6V5U5_supported not supported, skipping D3DTOP_BUMPENVMAPLUMINANCE test\n");
8108         goto cleanup;
8109     }
8110
8111     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0, 0x8);
8112     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
8113     /* This test only tests the luminance part. The bumpmapping part was already tested above and
8114      * would only make this test more complicated
8115      */
8116     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_L6V5U5, D3DPOOL_MANAGED, &tex1, NULL);
8117     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
8118     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &tex2, NULL);
8119     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
8120
8121     memset(&locked_rect, 0, sizeof(locked_rect));
8122     hr = IDirect3DTexture9_LockRect(tex1, 0, &locked_rect, NULL, 0);
8123     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
8124     *((DWORD *)locked_rect.pBits) = 0x4000; /* L = 0.25, V = 0.0, U = 0.0 */
8125     hr = IDirect3DTexture9_UnlockRect(tex1, 0);
8126     ok(SUCCEEDED(hr), "UnlockRect failed with 0x%08x\n", hr);
8127
8128     memset(&locked_rect, 0, sizeof(locked_rect));
8129     hr = IDirect3DTexture9_LockRect(tex2, 0, &locked_rect, NULL, 0);
8130     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
8131     *((DWORD *)locked_rect.pBits) = 0x00ff80c0;
8132     hr = IDirect3DTexture9_UnlockRect(tex2, 0);
8133     ok(SUCCEEDED(hr), "UnlockRect failed with 0x%08x\n", hr);
8134
8135     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex1);
8136     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
8137     hr = IDirect3DDevice9_SetTexture(device, 1, (IDirect3DBaseTexture9 *) tex2);
8138     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
8139
8140     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BUMPENVMAPLUMINANCE);
8141     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8142     scale = 2.0;
8143     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLSCALE, *((DWORD *)&scale));
8144     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8145     offset = 0.1;
8146     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLOFFSET, *((DWORD *)&offset));
8147     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8148
8149     hr = IDirect3DDevice9_BeginScene(device);
8150     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
8151     if(SUCCEEDED(hr)) {
8152         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
8153         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
8154         hr = IDirect3DDevice9_EndScene(device);
8155         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
8156     }
8157
8158     color = getPixelColor(device, 320, 240);
8159     /* red:   1.0  * (0.25 * 2.0 + 0.1) = 1.0  * 0.6 = 0.6  = 0x99
8160      * green: 0.5  * (0.25 * 2.0 + 0.1) = 0.5  * 0.6 = 0.3  = 0x4c
8161      * green: 0.75 * (0.25 * 2.0 + 0.1) = 0.75 * 0.6 = 0.45 = 0x72
8162      */
8163     ok(color_match(color, 0x00994c72, 5), "bumpmap failed: Got color 0x%08x, expected 0x00994c72.\n", color);
8164     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8165     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
8166
8167     /* Check a result scale factor > 1.0 */
8168     scale = 10;
8169     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLSCALE, *((DWORD *)&scale));
8170     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8171     offset = 10;
8172     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLOFFSET, *((DWORD *)&offset));
8173     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8174
8175     hr = IDirect3DDevice9_BeginScene(device);
8176     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
8177     if(SUCCEEDED(hr)) {
8178         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
8179         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
8180         hr = IDirect3DDevice9_EndScene(device);
8181         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
8182     }
8183     color = getPixelColor(device, 320, 240);
8184     ok(color_match(color, 0x00ff80c0, 1), "bumpmap failed: Got color 0x%08x, expected 0x00ff80c0.\n", color);
8185     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8186     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
8187
8188     /* Check clamping in the scale factor calculation */
8189     scale = 1000;
8190     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLSCALE, *((DWORD *)&scale));
8191     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8192     offset = -1;
8193     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVLOFFSET, *((DWORD *)&offset));
8194     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8195
8196     hr = IDirect3DDevice9_BeginScene(device);
8197     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
8198     if(SUCCEEDED(hr)) {
8199         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
8200         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
8201         hr = IDirect3DDevice9_EndScene(device);
8202         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
8203     }
8204     color = getPixelColor(device, 320, 240);
8205     ok(color_match(color, 0x00ff80c0, 1), "bumpmap failed: Got color 0x%08x, expected 0x00ff80c0.\n", color);
8206     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8207     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
8208
8209     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
8210     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
8211     hr = IDirect3DDevice9_SetTexture(device, 1, NULL);
8212     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
8213
8214     IDirect3DTexture9_Release(tex1);
8215     IDirect3DTexture9_Release(tex2);
8216
8217 cleanup:
8218     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
8219     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8220     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
8221     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
8222
8223     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
8224     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
8225     IDirect3DVertexDeclaration9_Release(vertex_declaration);
8226 }
8227
8228 static void stencil_cull_test(IDirect3DDevice9 *device) {
8229     HRESULT hr;
8230     IDirect3DSurface9 *depthstencil = NULL;
8231     D3DSURFACE_DESC desc;
8232     float quad1[] = {
8233         -1.0,   -1.0,   0.1,
8234          0.0,   -1.0,   0.1,
8235         -1.0,    0.0,   0.1,
8236          0.0,    0.0,   0.1,
8237     };
8238     float quad2[] = {
8239          0.0,   -1.0,   0.1,
8240          1.0,   -1.0,   0.1,
8241          0.0,    0.0,   0.1,
8242          1.0,    0.0,   0.1,
8243     };
8244     float quad3[] = {
8245         0.0,    0.0,   0.1,
8246         1.0,    0.0,   0.1,
8247         0.0,    1.0,   0.1,
8248         1.0,    1.0,   0.1,
8249     };
8250     float quad4[] = {
8251         -1.0,    0.0,   0.1,
8252          0.0,    0.0,   0.1,
8253         -1.0,    1.0,   0.1,
8254          0.0,    1.0,   0.1,
8255     };
8256     struct vertex painter[] = {
8257        {-1.0,   -1.0,   0.0,    0x00000000},
8258        { 1.0,   -1.0,   0.0,    0x00000000},
8259        {-1.0,    1.0,   0.0,    0x00000000},
8260        { 1.0,    1.0,   0.0,    0x00000000},
8261     };
8262     WORD indices_cw[]  = {0, 1, 3};
8263     WORD indices_ccw[] = {0, 2, 3};
8264     unsigned int i;
8265     DWORD color;
8266
8267     IDirect3DDevice9_GetDepthStencilSurface(device, &depthstencil);
8268     if(depthstencil == NULL) {
8269         skip("No depth stencil buffer\n");
8270         return;
8271     }
8272     hr = IDirect3DSurface9_GetDesc(depthstencil, &desc);
8273     ok(hr == D3D_OK, "IDirect3DSurface9_GetDesc failed with %08x\n", hr);
8274     IDirect3DSurface9_Release(depthstencil);
8275     if(desc.Format != D3DFMT_D24S8 && desc.Format != D3DFMT_D24X4S4) {
8276         skip("No 4 or 8 bit stencil surface\n");
8277         return;
8278     }
8279
8280     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_STENCIL, 0x00ff0000, 0.0, 0x8);
8281     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
8282     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8283
8284     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILFAIL, D3DSTENCILOP_INCR);
8285     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8286     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR);
8287     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8288     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
8289     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8290     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILREF, 0x3);
8291     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8292
8293     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_REPLACE);
8294     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8295     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_DECR);
8296     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8297     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CCW_STENCILPASS, D3DSTENCILOP_INCR);
8298     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8299
8300     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, TRUE);
8301     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8302     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TWOSIDEDSTENCILMODE, FALSE);
8303     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8304
8305     /* First pass: Fill the stencil buffer with some values... */
8306     hr = IDirect3DDevice9_BeginScene(device);
8307     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
8308     if(SUCCEEDED(hr))
8309     {
8310         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_CW);
8311         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8312         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8313                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad1, sizeof(float) * 3);
8314         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8315         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8316                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad1, sizeof(float) * 3);
8317         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8318
8319         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TWOSIDEDSTENCILMODE, TRUE);
8320         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8321         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
8322         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8323         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8324                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad2, sizeof(float) * 3);
8325         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8326         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8327                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad2, sizeof(float) * 3);
8328         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8329
8330         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_CW);
8331         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8332         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8333                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad3, sizeof(float) * 3);
8334         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8335         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8336                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad3, sizeof(float) * 3);
8337         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8338
8339         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_CCW);
8340         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8341         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8342                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad4, sizeof(float) * 3);
8343         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8344         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
8345                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad4, sizeof(float) * 3);
8346         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawIndexedPrimitiveUP returned %#x.\n", hr);
8347
8348         hr = IDirect3DDevice9_EndScene(device);
8349         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
8350     }
8351
8352     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8353     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
8354     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8355     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
8356     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8357     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
8358     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8359     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TWOSIDEDSTENCILMODE, FALSE);
8360     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8361     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
8362     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8363     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILFUNC, D3DCMP_EQUAL);
8364     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8365
8366     /* 2nd pass: Make the stencil values visible */
8367     hr = IDirect3DDevice9_BeginScene(device);
8368     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
8369     if(SUCCEEDED(hr))
8370     {
8371         IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
8372         for(i = 0; i < 16; i++) {
8373             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILREF, i);
8374             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8375
8376             painter[0].diffuse = (i * 16); /* Creates shades of blue */
8377             painter[1].diffuse = (i * 16);
8378             painter[2].diffuse = (i * 16);
8379             painter[3].diffuse = (i * 16);
8380             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, painter, sizeof(painter[0]));
8381             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
8382         }
8383         hr = IDirect3DDevice9_EndScene(device);
8384         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
8385     }
8386
8387     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
8388     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
8389
8390     color = getPixelColor(device, 160, 420);
8391     ok(color == 0x00000030, "CCW triangle, twoside FALSE, cull cw, replace, has color 0x%08x, expected 0x00000030\n", color);
8392     color = getPixelColor(device, 160, 300);
8393     ok(color == 0x00000080, "CW triangle, twoside FALSE, cull cw, culled, has color 0x%08x, expected 0x00000080\n", color);
8394
8395     color = getPixelColor(device, 480, 420);
8396     ok(color == 0x00000090, "CCW triangle, twoside TRUE, cull off, incr, has color 0x%08x, expected 0x00000090\n", color);
8397     color = getPixelColor(device, 480, 300);
8398     ok(color == 0x00000030, "CW triangle, twoside TRUE, cull off, replace, has color 0x%08x, expected 0x00000030\n", color);
8399
8400     color = getPixelColor(device, 160, 180);
8401     ok(color == 0x00000080, "CCW triangle, twoside TRUE, cull ccw, culled, has color 0x%08x, expected 0x00000080\n", color);
8402     color = getPixelColor(device, 160, 60);
8403     ok(color == 0x00000030, "CW triangle, twoside TRUE, cull ccw, replace, has color 0x%08x, expected 0x00000030\n", color);
8404
8405     color = getPixelColor(device, 480, 180);
8406     ok(color == 0x00000090, "CCW triangle, twoside TRUE, cull cw, incr, has color 0x%08x, expected 0x00000090\n", color);
8407     color = getPixelColor(device, 480, 60);
8408     ok(color == 0x00000080, "CW triangle, twoside TRUE, cull cw, culled, has color 0x%08x, expected 0x00000080\n", color);
8409
8410     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8411     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
8412 }
8413
8414 static void vpos_register_test(IDirect3DDevice9 *device)
8415 {
8416     HRESULT hr;
8417     DWORD color;
8418     const DWORD shader_code[] = {
8419     0xffff0300,                                                             /* ps_3_0                     */
8420     0x0200001f, 0x80000000, 0x90031000,                                     /* dcl vPos.xy                */
8421     0x03000002, 0x80030000, 0x90541000, 0xa1fe0000,                         /* sub r0.xy, vPos.xy, c0.zw  */
8422     0x02000001, 0x800f0001, 0xa0e40000,                                     /* mov r1, c0                 */
8423     0x02000001, 0x80080002, 0xa0550000,                                     /* mov r2.a, c0.y             */
8424     0x02000001, 0x80010002, 0xa0550000,                                     /* mov r2.r, c0.y             */
8425     0x04000058, 0x80020002, 0x80000000, 0x80000001, 0x80550001,             /* cmp r2.g, r0.x, r1.x, r1.y */
8426     0x04000058, 0x80040002, 0x80550000, 0x80000001, 0x80550001,             /* cmp r2.b, r0.y, r1.x, r1.y */
8427     0x02000001, 0x800f0800, 0x80e40002,                                     /* mov oC0, r2                */
8428     0x0000ffff                                                              /* end                        */
8429     };
8430     const DWORD shader_frac_code[] = {
8431     0xffff0300,                                                             /* ps_3_0                     */
8432     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0 */
8433     0x0200001f, 0x80000000, 0x90031000,                                     /* dcl vPos.xy                */
8434     0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                 */
8435     0x02000013, 0x80030000, 0x90541000,                                     /* frc r0.xy, vPos.xy         */
8436     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                */
8437     0x0000ffff                                                              /* end                        */
8438     };
8439     const DWORD vshader_code[] = {
8440         0xfffe0300,                                                             /* vs_3_0               */
8441         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0      */
8442         0x0200001f, 0x80000000, 0xe00f0000,                                     /* dcl_position o0      */
8443         0x02000001, 0xe00f0000, 0x90e40000,                                     /* mov o0, v0           */
8444         0x0000ffff                                                              /* end                  */
8445     };
8446     IDirect3DVertexShader9 *vshader;
8447     IDirect3DPixelShader9 *shader, *shader_frac;
8448     IDirect3DSurface9 *surface = NULL, *backbuffer;
8449     const float quad[] = {
8450         -1.0,   -1.0,   0.1,    0.0,    0.0,
8451          1.0,   -1.0,   0.1,    1.0,    0.0,
8452         -1.0,    1.0,   0.1,    0.0,    1.0,
8453          1.0,    1.0,   0.1,    1.0,    1.0,
8454     };
8455     D3DLOCKED_RECT lr;
8456     float constant[4] = {1.0, 0.0, 320, 240};
8457     DWORD *pos;
8458
8459     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
8460     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8461     hr = IDirect3DDevice9_CreateVertexShader(device, vshader_code, &vshader);
8462     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader failed hr=%08x\n", hr);
8463     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
8464     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed hr=%08x\n", hr);
8465     hr = IDirect3DDevice9_CreatePixelShader(device, shader_frac_code, &shader_frac);
8466     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed hr=%08x\n", hr);
8467     hr = IDirect3DDevice9_SetPixelShader(device, shader);
8468     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
8469     hr = IDirect3DDevice9_SetVertexShader(device, vshader);
8470     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
8471     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8472     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
8473     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
8474     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed hr=%08x\n", hr);
8475
8476     hr = IDirect3DDevice9_BeginScene(device);
8477     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8478     if(SUCCEEDED(hr)) {
8479         hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, constant, 1);
8480         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF failed hr=%08x\n", hr);
8481         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
8482         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8483         hr = IDirect3DDevice9_EndScene(device);
8484         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8485     }
8486
8487     /* This has to be pixel exact */
8488     color = getPixelColor(device, 319, 239);
8489     ok(color == 0x00000000, "vPos: Pixel 319,239 has color 0x%08x, expected 0x00000000\n", color);
8490     color = getPixelColor(device, 320, 239);
8491     ok(color == 0x0000ff00, "vPos: Pixel 320,239 has color 0x%08x, expected 0x0000ff00\n", color);
8492     color = getPixelColor(device, 319, 240);
8493     ok(color == 0x000000ff, "vPos: Pixel 319,240 has color 0x%08x, expected 0x000000ff\n", color);
8494     color = getPixelColor(device, 320, 240);
8495     ok(color == 0x0000ffff, "vPos: Pixel 320,240 has color 0x%08x, expected 0x0000ffff\n", color);
8496     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8497
8498     hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, D3DFMT_X8R8G8B8, 0, 0, TRUE,
8499                                              &surface, NULL);
8500     ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed hr=%08x\n", hr);
8501     hr = IDirect3DDevice9_BeginScene(device);
8502     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8503     if(SUCCEEDED(hr)) {
8504         constant[2] = 16; constant[3] = 16;
8505         hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, constant, 1);
8506         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF failed hr=%08x\n", hr);
8507         hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
8508         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8509         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
8510         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8511         hr = IDirect3DDevice9_EndScene(device);
8512         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8513     }
8514     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, D3DLOCK_READONLY);
8515     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr=%08x\n", hr);
8516
8517     pos = (DWORD *) (((BYTE *) lr.pBits) + 14 * lr.Pitch + 14 * sizeof(DWORD));
8518     color = *pos & 0x00ffffff;
8519     ok(color == 0x00000000, "Pixel 14/14 has color 0x%08x, expected 0x00000000\n", color);
8520     pos = (DWORD *) (((BYTE *) lr.pBits) + 14 * lr.Pitch + 18 * sizeof(DWORD));
8521     color = *pos & 0x00ffffff;
8522     ok(color == 0x0000ff00, "Pixel 14/18 has color 0x%08x, expected 0x0000ff00\n", color);
8523     pos = (DWORD *) (((BYTE *) lr.pBits) + 18 * lr.Pitch + 14 * sizeof(DWORD));
8524     color = *pos & 0x00ffffff;
8525     ok(color == 0x000000ff, "Pixel 18/14 has color 0x%08x, expected 0x000000ff\n", color);
8526     pos = (DWORD *) (((BYTE *) lr.pBits) + 18 * lr.Pitch + 18 * sizeof(DWORD));
8527     color = *pos & 0x00ffffff;
8528     ok(color == 0x0000ffff, "Pixel 18/18 has color 0x%08x, expected 0x0000ffff\n", color);
8529
8530     hr = IDirect3DSurface9_UnlockRect(surface);
8531     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr=%08x\n", hr);
8532
8533     /* Test the fraction value of vPos. This is tested with the offscreen target and not the backbuffer to
8534      * have full control over the multisampling setting inside this test
8535      */
8536     hr = IDirect3DDevice9_SetPixelShader(device, shader_frac);
8537     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
8538     hr = IDirect3DDevice9_BeginScene(device);
8539     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8540     if(SUCCEEDED(hr)) {
8541         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
8542         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8543         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
8544         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8545         hr = IDirect3DDevice9_EndScene(device);
8546         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8547     }
8548     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
8549     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8550
8551     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, D3DLOCK_READONLY);
8552     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr=%08x\n", hr);
8553
8554     pos = (DWORD *) (((BYTE *) lr.pBits) + 14 * lr.Pitch + 14 * sizeof(DWORD));
8555     color = *pos & 0x00ffffff;
8556     ok(color == 0x00000000, "vPos fraction test has color 0x%08x, expected 0x00000000\n", color);
8557
8558     hr = IDirect3DSurface9_UnlockRect(surface);
8559     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr=%08x\n", hr);
8560
8561     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
8562     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%08x\n", hr);
8563     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
8564     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
8565     IDirect3DPixelShader9_Release(shader);
8566     IDirect3DPixelShader9_Release(shader_frac);
8567     IDirect3DVertexShader9_Release(vshader);
8568     if(surface) IDirect3DSurface9_Release(surface);
8569     IDirect3DSurface9_Release(backbuffer);
8570 }
8571
8572 static BOOL point_match(IDirect3DDevice9 *device, UINT x, UINT y, UINT r)
8573 {
8574     D3DCOLOR color;
8575
8576     color = D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0xff);
8577     if (!color_match(getPixelColor(device, x + r, y), color, 1)) return FALSE;
8578     if (!color_match(getPixelColor(device, x - r, y), color, 1)) return FALSE;
8579     if (!color_match(getPixelColor(device, x, y + r), color, 1)) return FALSE;
8580     if (!color_match(getPixelColor(device, x, y - r), color, 1)) return FALSE;
8581
8582     ++r;
8583     color = D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xff);
8584     if (!color_match(getPixelColor(device, x + r, y), color, 1)) return FALSE;
8585     if (!color_match(getPixelColor(device, x - r, y), color, 1)) return FALSE;
8586     if (!color_match(getPixelColor(device, x, y + r), color, 1)) return FALSE;
8587     if (!color_match(getPixelColor(device, x, y - r), color, 1)) return FALSE;
8588
8589     return TRUE;
8590 }
8591
8592 static void pointsize_test(IDirect3DDevice9 *device)
8593 {
8594     HRESULT hr;
8595     D3DCAPS9 caps;
8596     D3DMATRIX matrix;
8597     D3DMATRIX identity;
8598     float ptsize, ptsize_orig, ptsizemax_orig, ptsizemin_orig;
8599     DWORD color;
8600     IDirect3DSurface9 *rt, *backbuffer;
8601     IDirect3DTexture9 *tex1, *tex2;
8602     RECT rect = {0, 0, 128, 128};
8603     D3DLOCKED_RECT lr;
8604     const DWORD tex1_data[4] = {0x00ff0000, 0x00ff0000,
8605                                 0x00000000, 0x00000000};
8606     const DWORD tex2_data[4] = {0x00000000, 0x0000ff00,
8607                                 0x00000000, 0x0000ff00};
8608
8609     const float vertices[] = {
8610         64,     64,     0.1,
8611         128,    64,     0.1,
8612         192,    64,     0.1,
8613         256,    64,     0.1,
8614         320,    64,     0.1,
8615         384,    64,     0.1,
8616         448,    64,     0.1,
8617         512,    64,     0.1,
8618     };
8619
8620     /* 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 */
8621     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;
8622     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;
8623     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;
8624     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;
8625
8626     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;
8627     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;
8628     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;
8629     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;
8630
8631     memset(&caps, 0, sizeof(caps));
8632     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8633     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%08x\n", hr);
8634     if(caps.MaxPointSize < 32.0) {
8635         skip("MaxPointSize < 32.0, skipping(MaxPointsize = %f)\n", caps.MaxPointSize);
8636         return;
8637     }
8638
8639     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 0.0, 0);
8640     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8641     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, &matrix);
8642     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed, hr=%08x\n", hr);
8643     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8644     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%08x\n", hr);
8645     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSIZE, (DWORD *) &ptsize_orig);
8646     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed hr=%08x\n", hr);
8647
8648     hr = IDirect3DDevice9_BeginScene(device);
8649     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%08x\n", hr);
8650     if (SUCCEEDED(hr))
8651     {
8652         ptsize = 15.0;
8653         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8654         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8655         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[0], sizeof(float) * 3);
8656         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8657
8658         ptsize = 31.0;
8659         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8660         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8661         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[3], sizeof(float) * 3);
8662         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8663
8664         ptsize = 30.75;
8665         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8666         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8667         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[6], sizeof(float) * 3);
8668         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8669
8670         if (caps.MaxPointSize >= 63.0)
8671         {
8672             ptsize = 63.0;
8673             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8674             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8675             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[9], sizeof(float) * 3);
8676             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8677
8678             ptsize = 62.75;
8679             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8680             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8681             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[15], sizeof(float) * 3);
8682             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8683         }
8684
8685         ptsize = 1.0;
8686         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8687         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8688         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[12], sizeof(float) * 3);
8689         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8690
8691         hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSIZE_MAX, (DWORD *) (&ptsizemax_orig));
8692         ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed, hr=%08x\n", hr);
8693         hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSIZE_MIN, (DWORD *) (&ptsizemin_orig));
8694         ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed, hr=%08x\n", hr);
8695
8696         /* What happens if point scaling is disabled, and POINTSIZE_MAX < POINTSIZE? */
8697         ptsize = 15.0;
8698         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8699         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8700         ptsize = 1.0;
8701         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MAX, *((DWORD *) (&ptsize)));
8702         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8703         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[18], sizeof(float) * 3);
8704         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8705
8706         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MAX, *((DWORD *) (&ptsizemax_orig)));
8707         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8708
8709         /* pointsize < pointsize_min < pointsize_max?
8710          * pointsize = 1.0, pointsize_min = 15.0, pointsize_max = default(usually 64.0) */
8711         ptsize = 1.0;
8712         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8713         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8714         ptsize = 15.0;
8715         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MIN, *((DWORD *) (&ptsize)));
8716         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8717         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[21], sizeof(float) * 3);
8718         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8719
8720         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE_MIN, *((DWORD *) (&ptsizemin_orig)));
8721         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8722
8723         hr = IDirect3DDevice9_EndScene(device);
8724         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%08x\n", hr);
8725     }
8726
8727     ok(point_match(device, 64, 64, 7), "point_match(64, 64, 7) failed, expected point size 15.\n");
8728     ok(point_match(device, 128, 64, 15), "point_match(128, 64, 15) failed, expected point size 31.\n");
8729     ok(point_match(device, 192, 64, 15), "point_match(192, 64, 15) failed, expected point size 31.\n");
8730
8731     if (caps.MaxPointSize >= 63.0)
8732     {
8733         ok(point_match(device, 256, 64, 31), "point_match(256, 64, 31) failed, expected point size 63.\n");
8734         ok(point_match(device, 384, 64, 31), "point_match(384, 64, 31) failed, expected point size 63.\n");
8735     }
8736
8737     ok(point_match(device, 320, 64, 0), "point_match(320, 64, 0) failed, expected point size 1.\n");
8738     /* ptsize = 15, ptsize_max = 1 --> point has size 1 */
8739     ok(point_match(device, 448, 64, 0), "point_match(448, 64, 0) failed, expected point size 1.\n");
8740     /* ptsize = 1, ptsize_max = default(64), ptsize_min = 15 --> point has size 15 */
8741     ok(point_match(device, 512, 64, 7), "point_match(512, 64, 7) failed, expected point size 15.\n");
8742
8743     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8744
8745     /* The following code tests point sprites with two textures, to see if each texture coordinate unit
8746      * generates texture coordinates for the point(result: Yes, it does)
8747      *
8748      * However, not all GL implementations support point sprites(they need GL_ARB_point_sprite), but there
8749      * is no point sprite cap bit in d3d because native d3d software emulates point sprites. Until the
8750      * SW emulation is implemented in wined3d, this test will fail on GL drivers that does not support them.
8751      */
8752     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 0.0, 0);
8753     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8754
8755     hr = IDirect3DDevice9_CreateTexture(device, 2, 2, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tex1, NULL);
8756     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed hr=%08x\n", hr);
8757     hr = IDirect3DDevice9_CreateTexture(device, 2, 2, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &tex2, NULL);
8758     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed hr=%08x\n", hr);
8759     memset(&lr, 0, sizeof(lr));
8760     hr = IDirect3DTexture9_LockRect(tex1, 0, &lr, NULL, 0);
8761     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed hr=%08x\n", hr);
8762     memcpy(lr.pBits, tex1_data, sizeof(tex1_data));
8763     hr = IDirect3DTexture9_UnlockRect(tex1, 0);
8764     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed hr=%08x\n", hr);
8765     memset(&lr, 0, sizeof(lr));
8766     hr = IDirect3DTexture9_LockRect(tex2, 0, &lr, NULL, 0);
8767     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed hr=%08x\n", hr);
8768     memcpy(lr.pBits, tex2_data, sizeof(tex2_data));
8769     hr = IDirect3DTexture9_UnlockRect(tex2, 0);
8770     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed hr=%08x\n", hr);
8771     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex1);
8772     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
8773     hr = IDirect3DDevice9_SetTexture(device, 1, (IDirect3DBaseTexture9 *) tex2);
8774     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
8775     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
8776     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed hr=%08x\n", hr);
8777     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
8778     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed hr=%08x\n", hr);
8779     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
8780     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed hr=%08x\n", hr);
8781     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
8782     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed hr=%08x\n", hr);
8783     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
8784     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed hr=%08x\n", hr);
8785
8786     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSPRITEENABLE, TRUE);
8787     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed hr=%08x\n", hr);
8788     ptsize = 32.0;
8789     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8790     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%08x\n", hr);
8791
8792     hr = IDirect3DDevice9_BeginScene(device);
8793     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed, hr=%08x\n", hr);
8794     if(SUCCEEDED(hr))
8795     {
8796         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[0], sizeof(float) * 3);
8797         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
8798         hr = IDirect3DDevice9_EndScene(device);
8799         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%08x\n", hr);
8800     }
8801
8802     color = getPixelColor(device, 64-4, 64-4);
8803     ok(color == 0x00ff0000, "pSprite: Pixel (64-4),(64-4) has color 0x%08x, expected 0x00ff0000\n", color);
8804     color = getPixelColor(device, 64-4, 64+4);
8805     ok(color == 0x00000000, "pSprite: Pixel (64-4),(64+4) has color 0x%08x, expected 0x00000000\n", color);
8806     color = getPixelColor(device, 64+4, 64+4);
8807     ok(color == 0x0000ff00, "pSprite: Pixel (64+4),(64+4) has color 0x%08x, expected 0x0000ff00\n", color);
8808     color = getPixelColor(device, 64+4, 64-4);
8809     ok(color == 0x00ffff00, "pSprite: Pixel (64+4),(64-4) has color 0x%08x, expected 0x00ffff00\n", color);
8810     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8811
8812     U(matrix).m[0][0] =  1.0f / 64.0f;
8813     U(matrix).m[1][1] = -1.0f / 64.0f;
8814     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, &matrix);
8815     ok(SUCCEEDED(hr), "SetTransform failed, hr %#x.\n", hr);
8816
8817     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
8818     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
8819
8820     hr = IDirect3DDevice9_CreateRenderTarget(device, 128, 128, D3DFMT_A8R8G8B8,
8821             D3DMULTISAMPLE_NONE, 0, TRUE, &rt, NULL );
8822     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
8823
8824     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
8825     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
8826     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ffff, 0.0f, 0);
8827     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
8828
8829     hr = IDirect3DDevice9_BeginScene(device);
8830     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
8831     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[0], sizeof(float) * 3);
8832     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
8833     hr = IDirect3DDevice9_EndScene(device);
8834     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
8835
8836     hr = IDirect3DDevice9_StretchRect(device, rt, &rect, backbuffer, &rect, D3DTEXF_NONE);
8837     ok(SUCCEEDED(hr), "StretchRect failed, hr %#x.\n", hr);
8838     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
8839     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
8840     IDirect3DSurface9_Release(backbuffer);
8841     IDirect3DSurface9_Release(rt);
8842
8843     color = getPixelColor(device, 64-4, 64-4);
8844     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00), 0),
8845             "Expected color 0x00ff0000, got 0x%08x.\n", color);
8846     color = getPixelColor(device, 64+4, 64-4);
8847     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00), 0),
8848             "Expected color 0x00ffff00, got 0x%08x.\n", color);
8849     color = getPixelColor(device, 64-4, 64+4);
8850     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00), 0),
8851             "Expected color 0x00000000, got 0x%08x.\n", color);
8852     color = getPixelColor(device, 64+4, 64+4);
8853     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 0),
8854             "Expected color 0x0000ff00, got 0x%08x.\n", color);
8855
8856     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8857     ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
8858
8859     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
8860     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed hr=%08x\n", hr);
8861     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
8862     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed hr=%08x\n", hr);
8863     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
8864     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
8865     hr = IDirect3DDevice9_SetTexture(device, 1, NULL);
8866     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%08x\n", hr);
8867     IDirect3DTexture9_Release(tex1);
8868     IDirect3DTexture9_Release(tex2);
8869
8870     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSPRITEENABLE, FALSE);
8871     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed hr=%08x\n", hr);
8872     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize_orig)));
8873     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed hr=%08x\n", hr);
8874     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, &identity);
8875     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed, hr=%08x\n", hr);
8876 }
8877
8878 static void multiple_rendertargets_test(IDirect3DDevice9 *device)
8879 {
8880     static const DWORD vshader_code[] =
8881     {
8882         0xfffe0300,                                                             /* vs_3_0                     */
8883         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0            */
8884         0x0200001f, 0x80000000, 0xe00f0000,                                     /* dcl_position o0            */
8885         0x02000001, 0xe00f0000, 0x90e40000,                                     /* mov o0, v0                 */
8886         0x0000ffff                                                              /* end                        */
8887     };
8888     static const DWORD pshader_code1[] =
8889     {
8890         0xffff0300,                                                             /* ps_3_0                     */
8891         0x05000051, 0xa00f0000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c0, 0.0, 1.0, 0.0, 0.0 */
8892         0x02000001, 0x800f0800, 0xa0e40000,                                     /* mov oC0, c0                */
8893         0x0000ffff                                                              /* end                        */
8894     };
8895     static const DWORD pshader_code2[] =
8896     {
8897         0xffff0300,                                                             /* ps_3_0                     */
8898         0x05000051, 0xa00f0000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c0, 0.0, 1.0, 0.0, 0.0 */
8899         0x05000051, 0xa00f0001, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, /* def c1, 0.0, 0.0, 1.0, 0.0 */
8900         0x02000001, 0x800f0800, 0xa0e40000,                                     /* mov oC0, c0                */
8901         0x02000001, 0x800f0801, 0xa0e40001,                                     /* mov oC1, c1                */
8902         0x0000ffff                                                              /* end                        */
8903     };
8904
8905     HRESULT hr;
8906     IDirect3DVertexShader9 *vs;
8907     IDirect3DPixelShader9 *ps1, *ps2;
8908     IDirect3DTexture9 *tex1, *tex2;
8909     IDirect3DSurface9 *surf1, *surf2, *backbuf, *readback;
8910     D3DCAPS9 caps;
8911     DWORD color;
8912     UINT i, j;
8913     float quad[] = {
8914        -1.0,   -1.0,    0.1,
8915         1.0,   -1.0,    0.1,
8916        -1.0,    1.0,    0.1,
8917         1.0,    1.0,    0.1,
8918     };
8919     float texquad[] = {
8920        -1.0,   -1.0,    0.1,    0.0,    0.0,
8921         0.0,   -1.0,    0.1,    1.0,    0.0,
8922        -1.0,    1.0,    0.1,    0.0,    1.0,
8923         0.0,    1.0,    0.1,    1.0,    1.0,
8924
8925         0.0,   -1.0,    0.1,    0.0,    0.0,
8926         1.0,   -1.0,    0.1,    1.0,    0.0,
8927         0.0,    1.0,    0.1,    0.0,    1.0,
8928         1.0,    1.0,    0.1,    1.0,    1.0,
8929     };
8930
8931     memset(&caps, 0, sizeof(caps));
8932     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8933     ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed, hr=%08x\n", hr);
8934     if(caps.NumSimultaneousRTs < 2) {
8935         skip("Only 1 simultaneous render target supported, skipping MRT test\n");
8936         return;
8937     }
8938
8939     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0, 0);
8940     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%08x\n", hr);
8941
8942     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 16, 16,
8943             D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &readback, NULL);
8944     ok(SUCCEEDED(hr), "CreateOffscreenPlainSurface failed, hr %#x.\n", hr);
8945
8946     hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, D3DUSAGE_RENDERTARGET,
8947             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex1, NULL);
8948     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
8949     hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, D3DUSAGE_RENDERTARGET,
8950             D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex2, NULL);
8951     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%08x\n", hr);
8952     hr = IDirect3DDevice9_CreateVertexShader(device, vshader_code, &vs);
8953     ok(SUCCEEDED(hr), "CreateVertexShader failed, hr %#x.\n", hr);
8954     hr = IDirect3DDevice9_CreatePixelShader(device, pshader_code1, &ps1);
8955     ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr);
8956     hr = IDirect3DDevice9_CreatePixelShader(device, pshader_code2, &ps2);
8957     ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr);
8958
8959     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuf);
8960     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderTarget failed, hr=%08x\n", hr);
8961     hr = IDirect3DTexture9_GetSurfaceLevel(tex1, 0, &surf1);
8962     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed, hr=%08x\n", hr);
8963     hr = IDirect3DTexture9_GetSurfaceLevel(tex2, 0, &surf2);
8964     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed, hr=%08x\n", hr);
8965
8966     hr = IDirect3DDevice9_SetVertexShader(device, vs);
8967     ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
8968     hr = IDirect3DDevice9_SetRenderTarget(device, 0, surf1);
8969     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8970     hr = IDirect3DDevice9_SetRenderTarget(device, 1, surf2);
8971     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
8972     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8973     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr=%08x\n", hr);
8974
8975     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
8976     ok(SUCCEEDED(hr), "Clear failed, hr %#x,\n", hr);
8977     hr = IDirect3DDevice9_GetRenderTargetData(device, surf1, readback);
8978     ok(SUCCEEDED(hr), "GetRenderTargetData failed, hr %#x.\n", hr);
8979     color = getPixelColorFromSurface(readback, 8, 8);
8980     ok(color_match(color, D3DCOLOR_ARGB(0xff, 0x00, 0x00, 0xff), 0),
8981             "Expected color 0x000000ff, got 0x%08x.\n", color);
8982     hr = IDirect3DDevice9_GetRenderTargetData(device, surf2, readback);
8983     ok(SUCCEEDED(hr), "GetRenderTargetData failed, hr %#x.\n", hr);
8984     color = getPixelColorFromSurface(readback, 8, 8);
8985     ok(color_match(color, D3DCOLOR_ARGB(0xff, 0x00, 0x00, 0xff), 0),
8986             "Expected color 0x000000ff, got 0x%08x.\n", color);
8987
8988     /* Render targets not written by the pixel shader should be unmodified. */
8989     hr = IDirect3DDevice9_SetPixelShader(device, ps1);
8990     ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
8991     hr = IDirect3DDevice9_BeginScene(device);
8992     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
8993     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
8994     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
8995     hr = IDirect3DDevice9_EndScene(device);
8996     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
8997     hr = IDirect3DDevice9_GetRenderTargetData(device, surf1, readback);
8998     ok(SUCCEEDED(hr), "GetRenderTargetData failed, hr %#x.\n", hr);
8999     color = getPixelColorFromSurface(readback, 8, 8);
9000     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 0),
9001             "Expected color 0xff00ff00, got 0x%08x.\n", color);
9002     hr = IDirect3DDevice9_GetRenderTargetData(device, surf2, readback);
9003     ok(SUCCEEDED(hr), "GetRenderTargetData failed, hr %#x.\n", hr);
9004     for (i = 6; i < 10; ++i)
9005     {
9006         for (j = 6; j < 10; ++j)
9007         {
9008             color = getPixelColorFromSurface(readback, j, i);
9009             ok(color_match(color, D3DCOLOR_ARGB(0xff, 0x00, 0x00, 0xff), 0),
9010                     "Expected color 0xff0000ff, got 0x%08x at %u, %u.\n", color, j, i);
9011         }
9012     }
9013
9014     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
9015     ok(SUCCEEDED(hr), "Clear failed, hr %#x,\n", hr);
9016     hr = IDirect3DDevice9_GetRenderTargetData(device, surf1, readback);
9017     ok(SUCCEEDED(hr), "GetRenderTargetData failed, hr %#x.\n", hr);
9018     color = getPixelColorFromSurface(readback, 8, 8);
9019     ok(color_match(color, D3DCOLOR_ARGB(0xff, 0x00, 0xff, 0x00), 0),
9020             "Expected color 0x0000ff00, got 0x%08x.\n", color);
9021     hr = IDirect3DDevice9_GetRenderTargetData(device, surf2, readback);
9022     ok(SUCCEEDED(hr), "GetRenderTargetData failed, hr %#x.\n", hr);
9023     color = getPixelColorFromSurface(readback, 8, 8);
9024     ok(color_match(color, D3DCOLOR_ARGB(0xff, 0x00, 0xff, 0x00), 0),
9025             "Expected color 0x0000ff00, got 0x%08x.\n", color);
9026
9027     hr = IDirect3DDevice9_SetPixelShader(device, ps2);
9028     ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
9029
9030     hr = IDirect3DDevice9_BeginScene(device);
9031     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed, hr=%08x\n", hr);
9032     if(SUCCEEDED(hr)) {
9033         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
9034         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
9035
9036         hr = IDirect3DDevice9_SetVertexShader(device, NULL);
9037         ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
9038         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
9039         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed, hr=%08x\n", hr);
9040         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuf);
9041         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
9042         hr = IDirect3DDevice9_SetRenderTarget(device, 1, NULL);
9043         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
9044         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
9045         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr=%08x\n", hr);
9046
9047         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex1);
9048         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
9049         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &texquad[0], 5 * sizeof(float));
9050         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
9051
9052         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex2);
9053         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
9054         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &texquad[20], 5 * sizeof(float));
9055         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%08x\n", hr);
9056
9057         hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
9058         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%08x\n", hr);
9059
9060         hr = IDirect3DDevice9_EndScene(device);
9061         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%08x\n", hr);
9062     }
9063
9064     color = getPixelColor(device, 160, 240);
9065     ok(color == 0x0000ff00, "Texture 1(output color 1) has color 0x%08x, expected 0x0000ff00\n", color);
9066     color = getPixelColor(device, 480, 240);
9067     ok(color == 0x000000ff, "Texture 2(output color 2) has color 0x%08x, expected 0x000000ff\n", color);
9068     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9069
9070     IDirect3DPixelShader9_Release(ps2);
9071     IDirect3DPixelShader9_Release(ps1);
9072     IDirect3DVertexShader9_Release(vs);
9073     IDirect3DTexture9_Release(tex1);
9074     IDirect3DTexture9_Release(tex2);
9075     IDirect3DSurface9_Release(surf1);
9076     IDirect3DSurface9_Release(surf2);
9077     IDirect3DSurface9_Release(backbuf);
9078     IDirect3DSurface9_Release(readback);
9079 }
9080
9081 struct formats {
9082     const char *fmtName;
9083     D3DFORMAT textureFormat;
9084     DWORD resultColorBlending;
9085     DWORD resultColorNoBlending;
9086 };
9087
9088 static const struct formats test_formats[] = {
9089   { "D3DFMT_G16R16", D3DFMT_G16R16, 0x001818ff, 0x002010ff},
9090   { "D3DFMT_R16F", D3DFMT_R16F, 0x0018ffff, 0x0020ffff },
9091   { "D3DFMT_G16R16F", D3DFMT_G16R16F, 0x001818ff, 0x002010ff },
9092   { "D3DFMT_A16B16G16R16F", D3DFMT_A16B16G16R16F, 0x00181800, 0x00201000 },
9093   { "D3DFMT_R32F", D3DFMT_R32F, 0x0018ffff, 0x0020ffff },
9094   { "D3DFMT_G32R32F", D3DFMT_G32R32F, 0x001818ff, 0x002010ff },
9095   { "D3DFMT_A32B32G32R32F", D3DFMT_A32B32G32R32F, 0x00181800, 0x00201000 },
9096   { NULL, 0 }
9097 };
9098
9099 static void pixelshader_blending_test(IDirect3DDevice9 *device)
9100 {
9101     HRESULT hr;
9102     IDirect3DTexture9 *offscreenTexture = NULL;
9103     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
9104     IDirect3D9 *d3d = NULL;
9105     DWORD color;
9106     DWORD r0, g0, b0, r1, g1, b1;
9107     int fmt_index;
9108
9109     static const float quad[][5] = {
9110         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
9111         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
9112         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
9113         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
9114     };
9115
9116     /* Quad with R=0x10, G=0x20 */
9117     static const struct vertex quad1[] = {
9118         {-1.0f, -1.0f, 0.1f, 0x80102000},
9119         {-1.0f,  1.0f, 0.1f, 0x80102000},
9120         { 1.0f, -1.0f, 0.1f, 0x80102000},
9121         { 1.0f,  1.0f, 0.1f, 0x80102000},
9122     };
9123
9124     /* Quad with R=0x20, G=0x10 */
9125     static const struct vertex quad2[] = {
9126         {-1.0f, -1.0f, 0.1f, 0x80201000},
9127         {-1.0f,  1.0f, 0.1f, 0x80201000},
9128         { 1.0f, -1.0f, 0.1f, 0x80201000},
9129         { 1.0f,  1.0f, 0.1f, 0x80201000},
9130     };
9131
9132     IDirect3DDevice9_GetDirect3D(device, &d3d);
9133
9134     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
9135     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
9136     if(!backbuffer) {
9137         goto out;
9138     }
9139
9140     for(fmt_index=0; test_formats[fmt_index].textureFormat != 0; fmt_index++)
9141     {
9142         D3DFORMAT fmt = test_formats[fmt_index].textureFormat;
9143
9144         if (IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
9145                 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, fmt) != D3D_OK)
9146         {
9147             skip("%s textures not supported as render targets.\n", test_formats[fmt_index].fmtName);
9148             continue;
9149         }
9150
9151         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
9152         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
9153
9154         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, fmt, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
9155         ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %08x\n", hr);
9156         if(!offscreenTexture) {
9157             continue;
9158         }
9159
9160         hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
9161         ok(hr == D3D_OK, "Can't get offscreen surface, hr = %08x\n", hr);
9162         if(!offscreen) {
9163             continue;
9164         }
9165
9166         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
9167         ok(hr == D3D_OK, "SetFVF failed, hr = %08x\n", hr);
9168
9169         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9170         ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9171         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9172         ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9173         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
9174         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
9175         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
9176         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
9177         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
9178         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
9179
9180         /* Below we will draw two quads with different colors and try to blend them together.
9181          * The result color is compared with the expected outcome.
9182          */
9183         if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
9184             hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
9185             ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
9186             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 0.0, 0);
9187             ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
9188
9189             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
9190             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
9191
9192             /* Draw a quad using color 0x0010200 */
9193             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_ONE);
9194             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
9195             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_ZERO);
9196             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
9197             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
9198             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
9199
9200             /* Draw a quad using color 0x0020100 */
9201             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
9202             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
9203             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
9204             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
9205             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
9206             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
9207
9208             /* We don't want to blend the result on the backbuffer */
9209             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
9210             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
9211
9212             /* Prepare rendering the 'blended' texture quad to the backbuffer */
9213             hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
9214             ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
9215             hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
9216             ok(hr == D3D_OK, "SetTexture failed, %08x\n", hr);
9217
9218             hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
9219             ok(hr == D3D_OK, "SetFVF failed, hr = %08x\n", hr);
9220
9221             /* This time with the texture */
9222             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
9223             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %08x\n", hr);
9224
9225             IDirect3DDevice9_EndScene(device);
9226         }
9227
9228         if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, fmt) == D3D_OK) {
9229             /* Compare the color of the center quad with our expectation */
9230             color = getPixelColor(device, 320, 240);
9231             r0 = (color & 0x00ff0000) >> 16;
9232             g0 = (color & 0x0000ff00) >>  8;
9233             b0 = (color & 0x000000ff) >>  0;
9234
9235             r1 = (test_formats[fmt_index].resultColorBlending & 0x00ff0000) >> 16;
9236             g1 = (test_formats[fmt_index].resultColorBlending & 0x0000ff00) >>  8;
9237             b1 = (test_formats[fmt_index].resultColorBlending & 0x000000ff) >>  0;
9238
9239             ok(r0 >= max(r1, 1) - 1 && r0 <= r1 + 1 &&
9240                g0 >= max(g1, 1) - 1 && g0 <= g1 + 1 &&
9241                b0 >= max(b1, 1) - 1 && b0 <= b1 + 1,
9242                "Offscreen failed for %s: Got color %#08x, expected %#08x.\n", test_formats[fmt_index].fmtName, color, test_formats[fmt_index].resultColorBlending);
9243         } else {
9244             /* No pixel shader blending is supported so expect garbage. The type of 'garbage' depends on the driver version and OS.
9245              * E.g. on G16R16 ati reports (on old r9600 drivers) 0x00ffffff and on modern ones 0x002010ff which is also what Nvidia
9246              * reports. On Vista Nvidia seems to report 0x00ffffff on Geforce7 cards. */
9247             color = getPixelColor(device, 320, 240);
9248             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);
9249         }
9250         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9251
9252         IDirect3DDevice9_SetTexture(device, 0, NULL);
9253         if(offscreenTexture) {
9254             IDirect3DTexture9_Release(offscreenTexture);
9255         }
9256         if(offscreen) {
9257             IDirect3DSurface9_Release(offscreen);
9258         }
9259     }
9260
9261 out:
9262     /* restore things */
9263     if(backbuffer) {
9264         IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
9265         IDirect3DSurface9_Release(backbuffer);
9266     }
9267 }
9268
9269 static void tssargtemp_test(IDirect3DDevice9 *device)
9270 {
9271     HRESULT hr;
9272     DWORD color;
9273     static const struct vertex quad[] = {
9274         {-1.0,     -1.0,    0.1,    0x00ff0000},
9275         { 1.0,     -1.0,    0.1,    0x00ff0000},
9276         {-1.0,      1.0,    0.1,    0x00ff0000},
9277         { 1.0,      1.0,    0.1,    0x00ff0000}
9278     };
9279     D3DCAPS9 caps;
9280
9281     memset(&caps, 0, sizeof(caps));
9282     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9283     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %08x\n", hr);
9284     if(!(caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP)) {
9285         skip("D3DPMISCCAPS_TSSARGTEMP not supported\n");
9286         return;
9287     }
9288
9289     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
9290     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9291
9292     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9293     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9294     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
9295     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9296
9297     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9298     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9299     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
9300     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9301     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_RESULTARG, D3DTA_TEMP);
9302     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9303
9304     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_ADD);
9305     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9306     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLORARG1, D3DTA_CURRENT);
9307     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9308     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLORARG2, D3DTA_TEMP);
9309     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9310
9311     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_COLOROP, D3DTOP_DISABLE);
9312     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9313
9314     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0x0000ff00);
9315     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
9316     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
9317     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %08x\n", hr);
9318
9319     hr = IDirect3DDevice9_BeginScene(device);
9320     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed, hr = %08x\n", hr);
9321     if(SUCCEEDED(hr)) {
9322         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
9323         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed with %08x\n", hr);
9324         hr = IDirect3DDevice9_EndScene(device);
9325         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr = %08x\n", hr);
9326     }
9327     color = getPixelColor(device, 320, 240);
9328     ok(color == 0x00FFFF00, "TSSARGTEMP test returned color 0x%08x, expected 0x00FFFF00\n", color);
9329     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9330
9331     /* Set stage 1 back to default */
9332     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_RESULTARG, D3DTA_CURRENT);
9333     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9334     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
9335     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9336     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
9337     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9338     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
9339     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9340     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_COLOROP, D3DTOP_DISABLE);
9341     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
9342 }
9343
9344 struct testdata
9345 {
9346     DWORD idxVertex; /* number of instances in the first stream */
9347     DWORD idxColor; /* number of instances in the second stream */
9348     DWORD idxInstance; /* should be 1 ?? */
9349     DWORD color1; /* color 1 instance */
9350     DWORD color2; /* color 2 instance */
9351     DWORD color3; /* color 3 instance */
9352     DWORD color4; /* color 4 instance */
9353     WORD strVertex; /* specify which stream to use 0-2*/
9354     WORD strColor;
9355     WORD strInstance;
9356 };
9357
9358 static const struct testdata testcases[]=
9359 {
9360     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  0 */
9361     {3, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0, 1, 2}, /*  1 */
9362     {2, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0, 1, 2}, /*  2 */
9363     {1, 4, 1, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0, 1, 2}, /*  3 */
9364     {4, 3, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  4 */
9365     {4, 2, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  5 */
9366     {4, 1, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  6 */
9367     {4, 0, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  7 */
9368     {3, 3, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0, 1, 2}, /*  8 */
9369     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 1, 0, 2}, /*  9 */
9370     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 2, 1}, /* 10 */
9371     {4, 4, 1, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 2, 3, 1}, /* 11 */
9372     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 2, 0, 1}, /* 12 */
9373     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 1, 2, 3}, /* 13 */
9374 /*
9375     This draws one instance on some machines, no instance on others
9376     {0, 4, 1, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0, 1, 2},
9377 */
9378 /*
9379     This case is handled in a stand alone test, SetStreamSourceFreq(0,(D3DSTREAMSOURCE_INSTANCEDATA | 1))  has to return D3DERR_INVALIDCALL!
9380     {4, 4, 1, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 2, 1, 0, D3DERR_INVALIDCALL},
9381 */
9382 };
9383
9384 /* Drawing Indexed Geometry with instances*/
9385 static void stream_test(IDirect3DDevice9 *device)
9386 {
9387     IDirect3DVertexBuffer9 *vb = NULL;
9388     IDirect3DVertexBuffer9 *vb2 = NULL;
9389     IDirect3DVertexBuffer9 *vb3 = NULL;
9390     IDirect3DIndexBuffer9 *ib = NULL;
9391     IDirect3DVertexDeclaration9 *pDecl = NULL;
9392     IDirect3DVertexShader9 *shader = NULL;
9393     HRESULT hr;
9394     BYTE *data;
9395     DWORD color;
9396     DWORD ind;
9397     unsigned i;
9398
9399     const DWORD shader_code[] =
9400     {
9401         0xfffe0101,                                     /* vs_1_1 */
9402         0x0000001f, 0x80000000, 0x900f0000,             /* dcl_position v0 */
9403         0x0000001f, 0x8000000a, 0x900f0001,             /* dcl_color0 v1 */
9404         0x0000001f, 0x80000005, 0x900f0002,             /* dcl_texcoord v2 */
9405         0x00000001, 0x800f0000, 0x90e40000,             /* mov r0, v0 */
9406         0x00000002, 0xc00f0000, 0x80e40000, 0x90e40002, /* add oPos, r0, v2 */
9407         0x00000001, 0xd00f0000, 0x90e40001,             /* mov oD0, v1 */
9408         0x0000ffff
9409     };
9410
9411     const float quad[][3] =
9412     {
9413         {-0.5f, -0.5f,  1.1f}, /*0 */
9414         {-0.5f,  0.5f,  1.1f}, /*1 */
9415         { 0.5f, -0.5f,  1.1f}, /*2 */
9416         { 0.5f,  0.5f,  1.1f}, /*3 */
9417     };
9418
9419     const float vertcolor[][4] =
9420     {
9421         {1.0f, 0.0f, 0.0f, 1.0f}, /*0 */
9422         {1.0f, 0.0f, 0.0f, 1.0f}, /*1 */
9423         {1.0f, 0.0f, 0.0f, 1.0f}, /*2 */
9424         {1.0f, 0.0f, 0.0f, 1.0f}, /*3 */
9425     };
9426
9427     /* 4 position for 4 instances */
9428     const float instancepos[][3] =
9429     {
9430         {-0.6f,-0.6f, 0.0f},
9431         { 0.6f,-0.6f, 0.0f},
9432         { 0.6f, 0.6f, 0.0f},
9433         {-0.6f, 0.6f, 0.0f},
9434     };
9435
9436     short indices[] = {0, 1, 2, 1, 2, 3};
9437
9438     D3DVERTEXELEMENT9 decl[] =
9439     {
9440         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9441         {1, 0,  D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
9442         {2, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
9443         D3DDECL_END()
9444     };
9445
9446     /* set the default value because it isn't done in wine? */
9447     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 1);
9448     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9449
9450     /* check for D3DSTREAMSOURCE_INDEXEDDATA at stream0 */
9451     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 0, (D3DSTREAMSOURCE_INSTANCEDATA | 1));
9452     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9453
9454     /* check wrong cases */
9455     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 0);
9456     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9457     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9458     ok(hr == D3D_OK && ind == 1, "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9459     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 2);
9460     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9461     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9462     ok(hr == D3D_OK && ind == 2, "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9463     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, (D3DSTREAMSOURCE_INDEXEDDATA | 0));
9464     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9465     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9466     ok(hr == D3D_OK && ind == (D3DSTREAMSOURCE_INDEXEDDATA | 0), "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9467     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, (D3DSTREAMSOURCE_INSTANCEDATA | 0));
9468     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9469     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9470     ok(hr == D3D_OK && ind == (0U | D3DSTREAMSOURCE_INSTANCEDATA), "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9471     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA | 0));
9472     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9473     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
9474     ok(hr == D3D_OK && ind == (0U | D3DSTREAMSOURCE_INSTANCEDATA), "IDirect3DDevice9_GetStreamSourceFreq failed with %08x\n", hr);
9475
9476     /* set the default value back */
9477     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 1);
9478     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x\n", hr);
9479
9480     /* create all VertexBuffers*/
9481     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0, D3DPOOL_MANAGED, &vb, NULL);
9482     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
9483     if(!vb) {
9484         skip("Failed to create a vertex buffer\n");
9485         return;
9486     }
9487     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(vertcolor), 0, 0, D3DPOOL_MANAGED, &vb2, NULL);
9488     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
9489     if(!vb2) {
9490         skip("Failed to create a vertex buffer\n");
9491         goto out;
9492     }
9493     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(instancepos), 0, 0, D3DPOOL_MANAGED, &vb3, NULL);
9494     ok(hr == D3D_OK, "CreateVertexBuffer failed with %08x\n", hr);
9495     if(!vb3) {
9496         skip("Failed to create a vertex buffer\n");
9497         goto out;
9498     }
9499
9500     /* create IndexBuffer*/
9501     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, NULL);
9502     ok(hr == D3D_OK, "IDirect3DDevice9_CreateIndexBuffer failed with %08x\n", hr);
9503     if(!ib) {
9504         skip("Failed to create a index buffer\n");
9505         goto out;
9506     }
9507
9508     /* copy all Buffers (Vertex + Index)*/
9509     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), (void **) &data, 0);
9510     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
9511     memcpy(data, quad, sizeof(quad));
9512     hr = IDirect3DVertexBuffer9_Unlock(vb);
9513     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
9514     hr = IDirect3DVertexBuffer9_Lock(vb2, 0, sizeof(vertcolor), (void **) &data, 0);
9515     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
9516     memcpy(data, vertcolor, sizeof(vertcolor));
9517     hr = IDirect3DVertexBuffer9_Unlock(vb2);
9518     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
9519     hr = IDirect3DVertexBuffer9_Lock(vb3, 0, sizeof(instancepos), (void **) &data, 0);
9520     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %08x\n", hr);
9521     memcpy(data, instancepos, sizeof(instancepos));
9522     hr = IDirect3DVertexBuffer9_Unlock(vb3);
9523     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %08x\n", hr);
9524     hr = IDirect3DIndexBuffer9_Lock(ib, 0, sizeof(indices), (void **) &data, 0);
9525     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Lock failed with %08x\n", hr);
9526     memcpy(data, indices, sizeof(indices));
9527     hr = IDirect3DIndexBuffer9_Unlock(ib);
9528     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
9529
9530     /* create VertexShader */
9531     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
9532     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexShader failed hr=%08x\n", hr);
9533     if(!shader) {
9534         skip("Failed to create a vetex shader\n");
9535         goto out;
9536     }
9537
9538     hr = IDirect3DDevice9_SetVertexShader(device, shader);
9539     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed hr=%08x\n", hr);
9540
9541     hr = IDirect3DDevice9_SetIndices(device, ib);
9542     ok(hr == D3D_OK, "IDirect3DDevice9_SetIndices failed with %08x\n", hr);
9543
9544     /* run all tests */
9545     for( i = 0; i < sizeof(testcases)/sizeof(testcases[0]); ++i)
9546     {
9547         struct testdata act = testcases[i];
9548         decl[0].Stream = act.strVertex;
9549         decl[1].Stream = act.strColor;
9550         decl[2].Stream = act.strInstance;
9551         /* create VertexDeclarations */
9552         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl, &pDecl);
9553         ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed hr=%08x (case %i)\n", hr, i);
9554
9555         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
9556         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x (case %i)\n", hr, i);
9557
9558         hr = IDirect3DDevice9_BeginScene(device);
9559         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x (case %i)\n", hr, i);
9560         if(SUCCEEDED(hr))
9561         {
9562             hr = IDirect3DDevice9_SetVertexDeclaration(device, pDecl);
9563             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x (case %i)\n", hr, i);
9564
9565             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strVertex, (D3DSTREAMSOURCE_INDEXEDDATA | act.idxVertex));
9566             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9567             hr = IDirect3DDevice9_SetStreamSource(device, act.strVertex, vb, 0, sizeof(quad[0]));
9568             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9569
9570             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strColor, (D3DSTREAMSOURCE_INDEXEDDATA | act.idxColor));
9571             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9572             hr = IDirect3DDevice9_SetStreamSource(device, act.strColor, vb2, 0, sizeof(vertcolor[0]));
9573             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9574
9575             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strInstance, (D3DSTREAMSOURCE_INSTANCEDATA | act.idxInstance));
9576             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9577             hr = IDirect3DDevice9_SetStreamSource(device, act.strInstance, vb3, 0, sizeof(instancepos[0]));
9578             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9579
9580             hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2);
9581             ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitive failed with %08x (case %i)\n", hr, i);
9582             hr = IDirect3DDevice9_EndScene(device);
9583             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x (case %i)\n", hr, i);
9584
9585             /* set all StreamSource && StreamSourceFreq back to default */
9586             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strVertex, 1);
9587             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9588             hr = IDirect3DDevice9_SetStreamSource(device, act.strVertex, NULL, 0, 0);
9589             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9590             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.idxColor, 1);
9591             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9592             hr = IDirect3DDevice9_SetStreamSource(device, act.idxColor, NULL, 0, 0);
9593             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9594             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.idxInstance, 1);
9595             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %08x (case %i)\n", hr, i);
9596             hr = IDirect3DDevice9_SetStreamSource(device, act.idxInstance, NULL, 0, 0);
9597             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
9598         }
9599
9600         hr = IDirect3DVertexDeclaration9_Release(pDecl);
9601         ok(hr == D3D_OK, "IDirect3DVertexDeclaration9_Release failed with %08x (case %i)\n", hr, i);
9602
9603         color = getPixelColor(device, 160, 360);
9604         ok(color == act.color1, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color1, i);
9605         color = getPixelColor(device, 480, 360);
9606         ok(color == act.color2, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color2, i);
9607         color = getPixelColor(device, 480, 120);
9608         ok(color == act.color3, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color3, i);
9609         color = getPixelColor(device, 160, 120);
9610         ok(color == act.color4, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color4, i);
9611
9612         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9613         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x (case %i)\n", hr, i);
9614     }
9615
9616     hr = IDirect3DDevice9_SetIndices(device, NULL);
9617     ok(hr == D3D_OK, "IDirect3DDevice9_SetIndices failed with %08x\n", hr);
9618
9619 out:
9620     if(vb) IDirect3DVertexBuffer9_Release(vb);
9621     if(vb2)IDirect3DVertexBuffer9_Release(vb2);
9622     if(vb3)IDirect3DVertexBuffer9_Release(vb3);
9623     if(ib)IDirect3DIndexBuffer9_Release(ib);
9624     if(shader)IDirect3DVertexShader9_Release(shader);
9625 }
9626
9627 static void np2_stretch_rect_test(IDirect3DDevice9 *device) {
9628     IDirect3DSurface9 *src = NULL, *dst = NULL, *backbuffer = NULL;
9629     IDirect3DTexture9 *dsttex = NULL;
9630     HRESULT hr;
9631     DWORD color;
9632     D3DRECT r1 = {0,  0,  50,  50 };
9633     D3DRECT r2 = {50, 0,  100, 50 };
9634     D3DRECT r3 = {50, 50, 100, 100};
9635     D3DRECT r4 = {0,  50,  50, 100};
9636     const float quad[] = {
9637         -1.0,   -1.0,   0.1,    0.0,    0.0,
9638          1.0,   -1.0,   0.1,    1.0,    0.0,
9639         -1.0,    1.0,   0.1,    0.0,    1.0,
9640          1.0,    1.0,   0.1,    1.0,    1.0,
9641     };
9642
9643     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
9644     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %08x\n", hr);
9645
9646     hr = IDirect3DDevice9_CreateRenderTarget(device, 100, 100, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &src, NULL );
9647     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_CreateRenderTarget failed with %08x\n", hr);
9648     hr = IDirect3DDevice9_CreateTexture(device, 25, 25, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &dsttex, NULL);
9649     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_CreateTexture failed with %08x\n", hr);
9650
9651     if(!src || !dsttex) {
9652         skip("One or more test resources could not be created\n");
9653         goto cleanup;
9654     }
9655
9656     hr = IDirect3DTexture9_GetSurfaceLevel(dsttex, 0, &dst);
9657     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %08x\n", hr);
9658
9659     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
9660     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9661
9662     /* Clear the StretchRect destination for debugging */
9663     hr = IDirect3DDevice9_SetRenderTarget(device, 0, dst);
9664     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
9665     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
9666     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9667
9668     hr = IDirect3DDevice9_SetRenderTarget(device, 0, src);
9669     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
9670
9671     hr = IDirect3DDevice9_Clear(device, 1, &r1, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
9672     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9673     hr = IDirect3DDevice9_Clear(device, 1, &r2, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
9674     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9675     hr = IDirect3DDevice9_Clear(device, 1, &r3, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
9676     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9677     hr = IDirect3DDevice9_Clear(device, 1, &r4, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
9678     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
9679
9680     /* Stretchrect before setting the render target back to the backbuffer. This will make Wine use
9681      * the target -> texture GL blit path
9682      */
9683     hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst, NULL, D3DTEXF_POINT);
9684     ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %08x\n", hr);
9685     IDirect3DSurface9_Release(dst);
9686
9687     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
9688     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %08x\n", hr);
9689
9690     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) dsttex);
9691     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9692     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
9693     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
9694     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9695     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with %08x\n", hr);
9696     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9697     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with %08x\n", hr);
9698
9699     hr = IDirect3DDevice9_BeginScene(device);
9700     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
9701     if(SUCCEEDED(hr)) {
9702         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
9703         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
9704         hr = IDirect3DDevice9_EndScene(device);
9705         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
9706     }
9707
9708     color = getPixelColor(device, 160, 360);
9709     ok(color == 0x00ff0000, "stretchrect: Pixel 160,360 has color 0x%08x, expected 0x00ff0000\n", color);
9710     color = getPixelColor(device, 480, 360);
9711     ok(color == 0x0000ff00, "stretchrect: Pixel 480,360 has color 0x%08x, expected 0x0000ff00\n", color);
9712     color = getPixelColor(device, 480, 120);
9713     ok(color == 0x000000ff, "stretchrect: Pixel 480,120 has color 0x%08x, expected 0x000000ff\n", color);
9714     color = getPixelColor(device, 160, 120);
9715     ok(color == 0x00000000, "stretchrect: Pixel 160,120 has color 0x%08x, expected 0x00000000\n", color);
9716     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9717     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
9718
9719     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
9720     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9721     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
9722     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %08x\n", hr);
9723
9724 cleanup:
9725     if(src) IDirect3DSurface9_Release(src);
9726     if(backbuffer) IDirect3DSurface9_Release(backbuffer);
9727     if(dsttex) IDirect3DTexture9_Release(dsttex);
9728 }
9729
9730 static void texop_test(IDirect3DDevice9 *device)
9731 {
9732     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
9733     IDirect3DTexture9 *texture = NULL;
9734     D3DLOCKED_RECT locked_rect;
9735     D3DCOLOR color;
9736     D3DCAPS9 caps;
9737     HRESULT hr;
9738     unsigned i;
9739
9740     static const struct {
9741         float x, y, z;
9742         float s, t;
9743         D3DCOLOR diffuse;
9744     } quad[] = {
9745         {-1.0f, -1.0f, 0.1f, -1.0f, -1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)},
9746         {-1.0f,  1.0f, 0.1f, -1.0f,  1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)},
9747         { 1.0f, -1.0f, 0.1f,  1.0f, -1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)},
9748         { 1.0f,  1.0f, 0.1f,  1.0f,  1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)}
9749     };
9750
9751     static const D3DVERTEXELEMENT9 decl_elements[] = {
9752         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9753         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
9754         {0, 20, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
9755         D3DDECL_END()
9756     };
9757
9758     static const struct {
9759         D3DTEXTUREOP op;
9760         const char *name;
9761         DWORD caps_flag;
9762         D3DCOLOR result;
9763     } test_data[] = {
9764         {D3DTOP_SELECTARG1,                "SELECTARG1",                D3DTEXOPCAPS_SELECTARG1,                D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
9765         {D3DTOP_SELECTARG2,                "SELECTARG2",                D3DTEXOPCAPS_SELECTARG2,                D3DCOLOR_ARGB(0x00, 0x33, 0x33, 0x33)},
9766         {D3DTOP_MODULATE,                  "MODULATE",                  D3DTEXOPCAPS_MODULATE,                  D3DCOLOR_ARGB(0x00, 0x00, 0x33, 0x00)},
9767         {D3DTOP_MODULATE2X,                "MODULATE2X",                D3DTEXOPCAPS_MODULATE2X,                D3DCOLOR_ARGB(0x00, 0x00, 0x66, 0x00)},
9768         {D3DTOP_MODULATE4X,                "MODULATE4X",                D3DTEXOPCAPS_MODULATE4X,                D3DCOLOR_ARGB(0x00, 0x00, 0xcc, 0x00)},
9769         {D3DTOP_ADD,                       "ADD",                       D3DTEXOPCAPS_ADD,                       D3DCOLOR_ARGB(0x00, 0x33, 0xff, 0x33)},
9770         {D3DTOP_ADDSIGNED,                 "ADDSIGNED",                 D3DTEXOPCAPS_ADDSIGNED,                 D3DCOLOR_ARGB(0x00, 0x00, 0xb2, 0x00)},
9771         {D3DTOP_ADDSIGNED2X,               "ADDSIGNED2X",               D3DTEXOPCAPS_ADDSIGNED2X,               D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
9772         {D3DTOP_SUBTRACT,                  "SUBTRACT",                  D3DTEXOPCAPS_SUBTRACT,                  D3DCOLOR_ARGB(0x00, 0x00, 0xcc, 0x00)},
9773         {D3DTOP_ADDSMOOTH,                 "ADDSMOOTH",                 D3DTEXOPCAPS_ADDSMOOTH,                 D3DCOLOR_ARGB(0x00, 0x33, 0xff, 0x33)},
9774         {D3DTOP_BLENDDIFFUSEALPHA,         "BLENDDIFFUSEALPHA",         D3DTEXOPCAPS_BLENDDIFFUSEALPHA,         D3DCOLOR_ARGB(0x00, 0x22, 0x77, 0x22)},
9775         {D3DTOP_BLENDTEXTUREALPHA,         "BLENDTEXTUREALPHA",         D3DTEXOPCAPS_BLENDTEXTUREALPHA,         D3DCOLOR_ARGB(0x00, 0x14, 0xad, 0x14)},
9776         {D3DTOP_BLENDFACTORALPHA,          "BLENDFACTORALPHA",          D3DTEXOPCAPS_BLENDFACTORALPHA,          D3DCOLOR_ARGB(0x00, 0x07, 0xe4, 0x07)},
9777         {D3DTOP_BLENDTEXTUREALPHAPM,       "BLENDTEXTUREALPHAPM",       D3DTEXOPCAPS_BLENDTEXTUREALPHAPM,       D3DCOLOR_ARGB(0x00, 0x14, 0xff, 0x14)},
9778         {D3DTOP_BLENDCURRENTALPHA,         "BLENDCURRENTALPHA",         D3DTEXOPCAPS_BLENDCURRENTALPHA,         D3DCOLOR_ARGB(0x00, 0x22, 0x77, 0x22)},
9779         {D3DTOP_MODULATEALPHA_ADDCOLOR,    "MODULATEALPHA_ADDCOLOR",    D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR,    D3DCOLOR_ARGB(0x00, 0x1f, 0xff, 0x1f)},
9780         {D3DTOP_MODULATECOLOR_ADDALPHA,    "MODULATECOLOR_ADDALPHA",    D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA,    D3DCOLOR_ARGB(0x00, 0x99, 0xcc, 0x99)},
9781         {D3DTOP_MODULATEINVALPHA_ADDCOLOR, "MODULATEINVALPHA_ADDCOLOR", D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR, D3DCOLOR_ARGB(0x00, 0x14, 0xff, 0x14)},
9782         {D3DTOP_MODULATEINVCOLOR_ADDALPHA, "MODULATEINVCOLOR_ADDALPHA", D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA, D3DCOLOR_ARGB(0x00, 0xcc, 0x99, 0xcc)},
9783         /* BUMPENVMAP & BUMPENVMAPLUMINANCE have their own tests */
9784         {D3DTOP_DOTPRODUCT3,               "DOTPRODUCT3",               D3DTEXOPCAPS_DOTPRODUCT3,               D3DCOLOR_ARGB(0x00, 0x99, 0x99, 0x99)},
9785         {D3DTOP_MULTIPLYADD,               "MULTIPLYADD",               D3DTEXOPCAPS_MULTIPLYADD,               D3DCOLOR_ARGB(0x00, 0xff, 0x33, 0x00)},
9786         {D3DTOP_LERP,                      "LERP",                      D3DTEXOPCAPS_LERP,                      D3DCOLOR_ARGB(0x00, 0x00, 0x33, 0x33)},
9787     };
9788
9789     memset(&caps, 0, sizeof(caps));
9790     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9791     ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x\n", hr);
9792
9793     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
9794     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed with 0x%08x\n", hr);
9795     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
9796     ok(SUCCEEDED(hr), "SetVertexDeclaration failed with 0x%08x\n", hr);
9797
9798     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
9799     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed with 0x%08x\n", hr);
9800     hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
9801     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
9802     *((DWORD *)locked_rect.pBits) = D3DCOLOR_ARGB(0x99, 0x00, 0xff, 0x00);
9803     hr = IDirect3DTexture9_UnlockRect(texture, 0);
9804     ok(SUCCEEDED(hr), "UnlockRect failed with 0x%08x\n", hr);
9805     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
9806     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
9807
9808     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG0, D3DTA_DIFFUSE);
9809     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9810     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9811     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9812     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9813     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9814
9815     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
9816     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
9817
9818     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
9819     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9820     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0xdd333333);
9821     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9822     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA);
9823     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
9824
9825     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
9826     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9827
9828     for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
9829     {
9830         if (!(caps.TextureOpCaps & test_data[i].caps_flag))
9831         {
9832             skip("tex operation %s not supported\n", test_data[i].name);
9833             continue;
9834         }
9835
9836         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, test_data[i].op);
9837         ok(SUCCEEDED(hr), "SetTextureStageState (%s) failed with 0x%08x\n", test_data[i].name, hr);
9838
9839         hr = IDirect3DDevice9_BeginScene(device);
9840         ok(SUCCEEDED(hr), "BeginScene failed with 0x%08x\n", hr);
9841
9842         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
9843         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
9844
9845         hr = IDirect3DDevice9_EndScene(device);
9846         ok(SUCCEEDED(hr), "EndScene failed with 0x%08x\n", hr);
9847
9848         color = getPixelColor(device, 320, 240);
9849         ok(color_match(color, test_data[i].result, 3), "Operation %s returned color 0x%08x, expected 0x%08x\n",
9850                 test_data[i].name, color, test_data[i].result);
9851
9852         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9853         ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
9854     }
9855
9856     if (texture) IDirect3DTexture9_Release(texture);
9857     if (vertex_declaration) IDirect3DVertexDeclaration9_Release(vertex_declaration);
9858 }
9859
9860 static void yuv_color_test(IDirect3DDevice9 *device) {
9861     HRESULT hr;
9862     IDirect3DSurface9 *surface = NULL, *target = NULL;
9863     unsigned int fmt, i;
9864     D3DFORMAT format;
9865     const char *fmt_string;
9866     D3DLOCKED_RECT lr;
9867     IDirect3D9 *d3d;
9868     HRESULT color;
9869     DWORD ref_color_left, ref_color_right;
9870
9871     struct {
9872         DWORD in;           /* The input color */
9873         DWORD uyvy_left;    /* "in" interpreted as uyvy and transformed to RGB, pixel 1/1*/
9874         DWORD uyvy_right;   /* "in" interpreted as uyvy and transformed to RGB, pixel 2/1*/
9875         DWORD yuy2_left;    /* "in" interpreted as yuy2 and transformed to RGB, pixel 1/1 */
9876         DWORD yuy2_right;   /* "in" interpreted as yuy2 and transformed to RGB, pixel 2/1 */
9877     } test_data[] = {
9878     /* Originally I wanted to avoid being evil, and set Y1 = Y2 to avoid triggering troubles in shader converters,
9879      * but the main difference between YUY2 and UYVY is the swapped ordering of the chroma and luminance
9880      * values. However, handling the two Y's properly could have a big impact on image quality, so be picky about
9881      * that
9882      */
9883       { 0x00000000, 0x00008700, 0x00008700, 0x00008700, 0x00008700 },
9884       { 0xff000000, 0x00008700, 0x004bff1c, 0x00b30000, 0x00b30000 },
9885       { 0x00ff0000, 0x00b30000, 0x00b30000, 0x00008700, 0x004bff1c },
9886       { 0x0000ff00, 0x004bff1c, 0x00008700, 0x000030e1, 0x000030e1 },
9887       { 0x000000ff, 0x000030e1, 0x000030e1, 0x004bff1c, 0x00008700 },
9888       { 0xffff0000, 0x00b30000, 0x00ffd01c, 0x00b30000, 0x00ffd01c },
9889       { 0xff00ff00, 0x004bff1c, 0x004bff1c, 0x00b300e1, 0x00b300e1 },
9890       { 0xff0000ff, 0x000030e1, 0x004bffff, 0x00ffd01c, 0x00b30000 },
9891       { 0x00ffff00, 0x00ffd01c, 0x00b30000, 0x000030e1, 0x004bffff },
9892       { 0x00ff00ff, 0x00b300e1, 0x00b300e1, 0x004bff1c, 0x004bff1c },
9893       { 0x0000ffff, 0x004bffff, 0x000030e1, 0x004bffff, 0x000030e1 },
9894       { 0xffffff00, 0x00ffd01c, 0x00ffd01c, 0x00b300e1, 0x00ff79ff },
9895       { 0xffff00ff, 0x00b300e1, 0x00ff79ff, 0x00ffd01c, 0x00ffd01c },
9896       { 0xffffffff, 0x00ff79ff, 0x00ff79ff, 0x00ff79ff, 0x00ff79ff },
9897
9898       { 0x4cff4c54, 0x00ff0000, 0x00ff0000, 0x000b8b00, 0x00b6ffa3 },
9899       { 0x00800080, 0x00000000, 0x00000000, 0x0000ff00, 0x0000ff00 },
9900       { 0xFF80FF80, 0x00ffffff, 0x00ffffff, 0x00ff00ff, 0x00ff00ff },
9901       { 0x1c6b1cff, 0x000000fd, 0x000000fd, 0x006dff45, 0x0000d500 },
9902     };
9903
9904     hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
9905     ok(hr == D3D_OK, "IDirect3DDevice9_GetDirect3D failed, hr = %08x\n", hr);
9906     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &target);
9907     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderTarget failed, hr = %08x\n", hr);
9908
9909     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX0);
9910     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %08x\n", hr);
9911
9912     for(fmt = 0; fmt < 2; fmt++) {
9913         if(fmt == 0) {
9914             format = D3DFMT_UYVY;
9915             fmt_string = "D3DFMT_UYVY";
9916         } else {
9917             format = D3DFMT_YUY2;
9918             fmt_string = "D3DFMT_YUY2";
9919         }
9920
9921         /* Some(all?) Windows drivers do not support YUV 3D textures, only 2D surfaces in StretchRect. Thus use
9922                        * StretchRect to draw the YUV surface onto the screen instead of drawPrimitive
9923                        */
9924         if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
9925                                         D3DRTYPE_SURFACE, format) != D3D_OK) {
9926             skip("%s is not supported\n", fmt_string);
9927             continue;
9928         }
9929
9930         /* A pixel is effectively 16 bit large, but two pixels are stored together, so the minimum size is 2x1 */
9931         hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 2, 1, format, D3DPOOL_DEFAULT, &surface, NULL);
9932         ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed, hr = %08x\n", hr);
9933
9934         for(i = 0; i < (sizeof(test_data)/sizeof(test_data[0])); i++) {
9935             if(fmt == 0) {
9936                 ref_color_left = test_data[i].uyvy_left;
9937                 ref_color_right = test_data[i].uyvy_right;
9938             } else {
9939                 ref_color_left = test_data[i].yuy2_left;
9940                 ref_color_right = test_data[i].yuy2_right;
9941             }
9942
9943             memset(&lr, 0, sizeof(lr));
9944             hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
9945             ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr = %08x\n", hr);
9946             *((DWORD *) lr.pBits) = test_data[i].in;
9947             hr = IDirect3DSurface9_UnlockRect(surface);
9948             ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr = %08x\n", hr);
9949
9950             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
9951             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
9952             hr = IDirect3DDevice9_StretchRect(device, surface, NULL, target, NULL, D3DTEXF_POINT);
9953             ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with 0x%08x\n", hr);
9954
9955             /* Native D3D can't resist filtering the YUY surface, even though we asked it not to do so above. To
9956              * prevent running into precision problems, read a far left and far right pixel. In the future we may
9957              * want to add tests for the filtered pixels as well.
9958              *
9959              * Unfortunately different implementations(Windows-NV and Mac-ATI tested) interpret some colors vastly
9960              * differently, so we need a max diff of 16
9961              */
9962             color = getPixelColor(device, 40, 240);
9963
9964             /* Newer versions of the Nvidia Windows driver mix up the U and V channels, breaking all the tests
9965              * where U != V. Skip the entire test if this bug in this case
9966              */
9967             if (broken(test_data[i].in == 0xff000000 && color == 0x00008800 && format == D3DFMT_UYVY))
9968             {
9969                 skip("Nvidia channel confusion bug detected, skipping YUV tests\n");
9970                 IDirect3DSurface9_Release(surface);
9971                 goto out;
9972             }
9973
9974             ok(color_match(color, ref_color_left, 18),
9975                "Input 0x%08x: Got color 0x%08x for pixel 1/1, expected 0x%08x, format %s\n",
9976                test_data[i].in, color, ref_color_left, fmt_string);
9977             color = getPixelColor(device, 600, 240);
9978             ok(color_match(color, ref_color_right, 18),
9979                "Input 0x%08x: Got color 0x%08x for pixel 2/1, expected 0x%08x, format %s\n",
9980                test_data[i].in, color, ref_color_right, fmt_string);
9981             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9982             ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
9983         }
9984         IDirect3DSurface9_Release(surface);
9985     }
9986
9987 out:
9988     IDirect3DSurface9_Release(target);
9989     IDirect3D9_Release(d3d);
9990 }
9991
9992 static void texop_range_test(IDirect3DDevice9 *device)
9993 {
9994     static const struct {
9995         float x, y, z;
9996         D3DCOLOR diffuse;
9997     } quad[] = {
9998         {-1.0f, -1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)},
9999         {-1.0f,  1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)},
10000         { 1.0f, -1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)},
10001         { 1.0f,  1.0f, 0.1f, D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff)}
10002     };
10003     HRESULT hr;
10004     IDirect3DTexture9 *texture;
10005     D3DLOCKED_RECT locked_rect;
10006     D3DCAPS9 caps;
10007     DWORD color;
10008
10009     /* We need ADD and SUBTRACT operations */
10010     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10011     ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x\n", hr);
10012     if (!(caps.TextureOpCaps & D3DTEXOPCAPS_ADD)) {
10013         skip("D3DTOP_ADD is not supported, skipping value range test\n");
10014         return;
10015     }
10016     if (!(caps.TextureOpCaps & D3DTEXOPCAPS_SUBTRACT)) {
10017         skip("D3DTEXOPCAPS_SUBTRACT is not supported, skipping value range test\n");
10018         return;
10019     }
10020
10021     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
10022     ok(SUCCEEDED(hr), "SetFVF failed with 0x%08x\n", hr);
10023     /* Stage 1: result = diffuse(=1.0) + diffuse
10024      * stage 2: result = result - tfactor(= 0.5)
10025      */
10026     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0x80808080);
10027     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
10028     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
10029     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10030     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
10031     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10032     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
10033     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10034     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_CURRENT);
10035     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10036     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10037     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10038     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SUBTRACT);
10039     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10040
10041     hr = IDirect3DDevice9_BeginScene(device);
10042     ok(SUCCEEDED(hr), "BeginScene failed with 0x%08x\n", hr);
10043     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
10044     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10045     hr = IDirect3DDevice9_EndScene(device);
10046     ok(SUCCEEDED(hr), "EndScene failed with 0x%08x\n", hr);
10047
10048     color = getPixelColor(device, 320, 240);
10049     ok(color_match(color, 0x00808080, 1), "texop Range > 1.0 returned 0x%08x, expected 0x00808080\n",
10050        color);
10051     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10052     ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
10053
10054     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
10055     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed with 0x%08x\n", hr);
10056     hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
10057     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
10058     *((DWORD *)locked_rect.pBits) = D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00);
10059     hr = IDirect3DTexture9_UnlockRect(texture, 0);
10060     ok(SUCCEEDED(hr), "UnlockRect failed with 0x%08x\n", hr);
10061     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
10062     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
10063
10064     /* Stage 1: result = texture(=0.0) - tfactor(= 0.5)
10065      * stage 2: result = result + diffuse(1.0)
10066      */
10067     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0x80808080);
10068     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
10069     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
10070     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10071     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10072     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10073     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SUBTRACT);
10074     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10075     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_CURRENT);
10076     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10077     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
10078     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10079     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_ADD);
10080     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10081
10082     hr = IDirect3DDevice9_BeginScene(device);
10083     ok(SUCCEEDED(hr), "BeginScene failed with 0x%08x\n", hr);
10084     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
10085     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10086     hr = IDirect3DDevice9_EndScene(device);
10087     ok(SUCCEEDED(hr), "EndScene failed with 0x%08x\n", hr);
10088
10089     color = getPixelColor(device, 320, 240);
10090     ok(color_match(color, 0x00ffffff, 1), "texop Range < 0.0 returned 0x%08x, expected 0x00ffffff\n",
10091        color);
10092     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10093     ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
10094
10095     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
10096     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10097     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
10098     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
10099     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
10100     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
10101     IDirect3DTexture9_Release(texture);
10102 }
10103
10104 static void alphareplicate_test(IDirect3DDevice9 *device) {
10105     struct vertex quad[] = {
10106         { -1.0,    -1.0,    0.1,    0x80ff00ff },
10107         {  1.0,    -1.0,    0.1,    0x80ff00ff },
10108         { -1.0,     1.0,    0.1,    0x80ff00ff },
10109         {  1.0,     1.0,    0.1,    0x80ff00ff },
10110     };
10111     HRESULT hr;
10112     DWORD color;
10113
10114     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
10115     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10116
10117     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
10118     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
10119
10120     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
10121     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10122     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE | D3DTA_ALPHAREPLICATE);
10123     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10124
10125     hr = IDirect3DDevice9_BeginScene(device);
10126     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
10127     if(SUCCEEDED(hr)) {
10128         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
10129         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10130         hr = IDirect3DDevice9_EndScene(device);
10131         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with 0x%08x\n", hr);
10132     }
10133
10134     color = getPixelColor(device, 320, 240);
10135     ok(color_match(color, 0x00808080, 1), "alphareplicate test 0x%08x, expected 0x00808080\n",
10136        color);
10137     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10138     ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
10139
10140     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
10141     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10142
10143 }
10144
10145 static void dp3_alpha_test(IDirect3DDevice9 *device) {
10146     HRESULT hr;
10147     D3DCAPS9 caps;
10148     DWORD color;
10149     struct vertex quad[] = {
10150         { -1.0,    -1.0,    0.1,    0x408080c0 },
10151         {  1.0,    -1.0,    0.1,    0x408080c0 },
10152         { -1.0,     1.0,    0.1,    0x408080c0 },
10153         {  1.0,     1.0,    0.1,    0x408080c0 },
10154     };
10155
10156     memset(&caps, 0, sizeof(caps));
10157     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10158     ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x\n", hr);
10159     if (!(caps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3)) {
10160         skip("D3DTOP_DOTPRODUCT3 not supported\n");
10161         return;
10162     }
10163
10164     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
10165     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10166
10167     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
10168     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
10169
10170     /* dp3_x4 r0, diffuse_bias, tfactor_bias
10171      * mov r0.a, diffuse.a
10172      * mov r0, r0.a
10173      *
10174      * It turns out that the 2nd line is ignored, and the dp3 result written into r0.a instead
10175      * 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
10176      * (0.0 * 0.5 + 0.0 * 0.5 + 0.25 * 0.5) * 4 = 0.125 * 4 = 0.5, with a bunch of inprecision.
10177      */
10178     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DOTPRODUCT3);
10179     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10180     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
10181     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10182     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
10183     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10184     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
10185     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10186     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
10187     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10188     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
10189     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10190     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_CURRENT | D3DTA_ALPHAREPLICATE);
10191     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10192     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
10193     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10194     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0xffffffff);
10195     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10196
10197     hr = IDirect3DDevice9_BeginScene(device);
10198     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
10199     if(SUCCEEDED(hr)) {
10200         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
10201         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10202         hr = IDirect3DDevice9_EndScene(device);
10203         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with 0x%08x\n", hr);
10204     }
10205
10206     color = getPixelColor(device, 320, 240);
10207     ok(color_match(color, 0x00808080, 4), "dp3 alpha test 0x%08x, expected 0x00808080\n",
10208        color);
10209     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10210     ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
10211
10212     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
10213     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10214     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
10215     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10216     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
10217     ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed with 0x%08x\n", hr);
10218 }
10219
10220 static void zwriteenable_test(IDirect3DDevice9 *device) {
10221     HRESULT hr;
10222     DWORD color;
10223     struct vertex quad1[] = {
10224         { -1.0,  -1.0,  0.1,    0x00ff0000},
10225         { -1.0,   1.0,  0.1,    0x00ff0000},
10226         {  1.0,  -1.0,  0.1,    0x00ff0000},
10227         {  1.0,   1.0,  0.1,    0x00ff0000},
10228     };
10229     struct vertex quad2[] = {
10230         { -1.0,  -1.0,  0.9,    0x0000ff00},
10231         { -1.0,   1.0,  0.9,    0x0000ff00},
10232         {  1.0,  -1.0,  0.9,    0x0000ff00},
10233         {  1.0,   1.0,  0.9,    0x0000ff00},
10234     };
10235
10236     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0);
10237     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10238
10239     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
10240     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
10241     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
10242     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10243     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
10244     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10245     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
10246     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10247
10248     hr = IDirect3DDevice9_BeginScene(device);
10249     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
10250     if(SUCCEEDED(hr)) {
10251         /* The Z buffer is filled with 1.0. Draw a red quad with z = 0.1, zenable = D3DZB_FALSE, zwriteenable = TRUE.
10252          * The red color is written because the z test is disabled. The question is whether the z = 0.1 values
10253          * are written into the Z buffer. After the draw, set zenable = TRUE and draw a green quad at z = 0.9.
10254          * If the values are written, the z test will fail(0.9 > 0.1) and the red color remains. If the values
10255          * are not written, the z test succeeds(0.9 < 1.0) and the green color is written. It turns out that
10256          * the screen is green, so zenable = D3DZB_FALSE and zwriteenable  = TRUE does NOT write to the z buffer.
10257          */
10258         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
10259         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10260         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
10261         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10262         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
10263         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10264
10265         hr = IDirect3DDevice9_EndScene(device);
10266         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
10267     }
10268
10269     color = getPixelColor(device, 320, 240);
10270     ok(color_match(color, 0x0000ff00, 1), "zwriteenable test returned 0x%08x, expected 0x0000ff00\n",
10271        color);
10272     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10273     ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
10274
10275     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
10276     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10277 }
10278
10279 static void alphatest_test(IDirect3DDevice9 *device) {
10280 #define ALPHATEST_PASSED 0x0000ff00
10281 #define ALPHATEST_FAILED 0x00ff0000
10282     struct {
10283         D3DCMPFUNC  func;
10284         DWORD       color_less;
10285         DWORD       color_equal;
10286         DWORD       color_greater;
10287     } testdata[] = {
10288         {   D3DCMP_NEVER,           ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_FAILED },
10289         {   D3DCMP_LESS,            ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_FAILED },
10290         {   D3DCMP_EQUAL,           ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_FAILED },
10291         {   D3DCMP_LESSEQUAL,       ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_FAILED },
10292         {   D3DCMP_GREATER,         ALPHATEST_FAILED, ALPHATEST_FAILED, ALPHATEST_PASSED },
10293         {   D3DCMP_NOTEQUAL,        ALPHATEST_PASSED, ALPHATEST_FAILED, ALPHATEST_PASSED },
10294         {   D3DCMP_GREATEREQUAL,    ALPHATEST_FAILED, ALPHATEST_PASSED, ALPHATEST_PASSED },
10295         {   D3DCMP_ALWAYS,          ALPHATEST_PASSED, ALPHATEST_PASSED, ALPHATEST_PASSED },
10296     };
10297     unsigned int i, j;
10298     HRESULT hr;
10299     DWORD color;
10300     struct vertex quad[] = {
10301         {   -1.0,    -1.0,   0.1,    ALPHATEST_PASSED | 0x80000000  },
10302         {    1.0,    -1.0,   0.1,    ALPHATEST_PASSED | 0x80000000  },
10303         {   -1.0,     1.0,   0.1,    ALPHATEST_PASSED | 0x80000000  },
10304         {    1.0,     1.0,   0.1,    ALPHATEST_PASSED | 0x80000000  },
10305     };
10306     D3DCAPS9 caps;
10307
10308     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, TRUE);
10309     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10310     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
10311     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
10312
10313     for(j = 0; j < 2; j++) {
10314         if(j == 1) {
10315             /* Try a pixel shader instead of fixed function. The wined3d code may emulate
10316              * the alpha test either for performance reasons(floating point RTs) or to work
10317              * around driver bugs(Geforce 7x00 cards on MacOS). There may be a different
10318              * codepath for ffp and shader in this case, and the test should cover both
10319              */
10320             IDirect3DPixelShader9 *ps;
10321             DWORD shader_code[] = {
10322                 0xffff0101,                                 /* ps_1_1           */
10323                 0x00000001, 0x800f0000, 0x90e40000,         /* mov r0, v0       */
10324                 0x0000ffff                                  /* end              */
10325             };
10326             memset(&caps, 0, sizeof(caps));
10327             IDirect3DDevice9_GetDeviceCaps(device, &caps);
10328             ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with 0x%08x\n", hr);
10329             if(caps.PixelShaderVersion < D3DPS_VERSION(1, 1)) {
10330                 break;
10331             }
10332
10333             hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &ps);
10334             ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed with 0x%08x\n", hr);
10335             IDirect3DDevice9_SetPixelShader(device, ps);
10336             ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with 0x%08x\n", hr);
10337             IDirect3DPixelShader9_Release(ps);
10338         }
10339
10340         for(i = 0; i < (sizeof(testdata)/sizeof(testdata[0])); i++) {
10341             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAFUNC, testdata[i].func);
10342             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10343
10344             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0, 0);
10345             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10346             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAREF, 0x90);
10347             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10348             hr = IDirect3DDevice9_BeginScene(device);
10349             ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
10350             if(SUCCEEDED(hr)) {
10351                 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
10352                 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10353                 hr = IDirect3DDevice9_EndScene(device);
10354                 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with 0x%08x\n", hr);
10355             }
10356             color = getPixelColor(device, 320, 240);
10357             ok(color_match(color, testdata[i].color_less, 1), "Alphatest failed. Got color 0x%08x, expected 0x%08x. alpha < ref, func %u\n",
10358             color, testdata[i].color_less, testdata[i].func);
10359             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10360             ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
10361
10362             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0, 0);
10363             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10364             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAREF, 0x80);
10365             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10366             hr = IDirect3DDevice9_BeginScene(device);
10367             ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
10368             if(SUCCEEDED(hr)) {
10369                 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
10370                 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10371                 hr = IDirect3DDevice9_EndScene(device);
10372                 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with 0x%08x\n", hr);
10373             }
10374             color = getPixelColor(device, 320, 240);
10375             ok(color_match(color, testdata[i].color_equal, 1), "Alphatest failed. Got color 0x%08x, expected 0x%08x. alpha == ref, func %u\n",
10376             color, testdata[i].color_equal, testdata[i].func);
10377             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10378             ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
10379
10380             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, ALPHATEST_FAILED, 0.0, 0);
10381             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10382             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHAREF, 0x70);
10383             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10384             hr = IDirect3DDevice9_BeginScene(device);
10385             ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with 0x%08x\n", hr);
10386             if(SUCCEEDED(hr)) {
10387                 hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
10388                 ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
10389                 hr = IDirect3DDevice9_EndScene(device);
10390                 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with 0x%08x\n", hr);
10391             }
10392             color = getPixelColor(device, 320, 240);
10393             ok(color_match(color, testdata[i].color_greater, 1), "Alphatest failed. Got color 0x%08x, expected 0x%08x. alpha > ref, func %u\n",
10394             color, testdata[i].color_greater, testdata[i].func);
10395             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10396             ok(SUCCEEDED(hr), "IDirect3DDevice9_Present failed with 0x%08x\n", hr);
10397         }
10398     }
10399
10400     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, FALSE);
10401     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with 0x%08x\n", hr);
10402     IDirect3DDevice9_SetPixelShader(device, NULL);
10403     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with 0x%08x\n", hr);
10404 }
10405
10406 static void sincos_test(IDirect3DDevice9 *device) {
10407     const DWORD sin_shader_code[] = {
10408         0xfffe0200,                                                                 /* vs_2_0                       */
10409         0x0200001f, 0x80000000, 0x900f0000,                                         /* dcl_position v0              */
10410         0x05000051, 0xa00f0002, 0x40490fdb, 0x3f800000, 0x00000000, 0x3f59999a,     /* def c2, 3.14159, 1, 0, 0.85  */
10411         0x03000005, 0x80010001, 0x90000000, 0xa0000002,                             /* mul r1.x, v0.x, c2.x         */
10412         0x04000025, 0x80020000, 0x80000001, 0xa0e40000, 0xa0e40001,                 /* sincos r0.y, r1.x, c0, c1    */
10413         0x02000001, 0xc00d0000, 0x90e40000,                                         /* mov oPos.xzw, v0             */
10414         0x03000005, 0xc0020000, 0x80550000, 0xa0ff0002,                             /* mul oPos.y, r0.y, c2.w       */
10415         0x02000001, 0xd00f0000, 0xa0a60002,                                         /* mov oD0, c2.zyzz             */
10416         0x0000ffff                                                                  /* end                          */
10417     };
10418     const DWORD cos_shader_code[] = {
10419         0xfffe0200,                                                                 /* vs_2_0                       */
10420         0x0200001f, 0x80000000, 0x900f0000,                                         /* dcl_position v0              */
10421         0x05000051, 0xa00f0002, 0x40490fdb, 0x3f800000, 0x00000000, 0x3f59999a,     /* def c2, 3.14159, 1, 0, 0.85  */
10422         0x03000005, 0x80010001, 0x90000000, 0xa0000002,                             /* mul r1.x, v0.x, c2.x         */
10423         0x04000025, 0x80010000, 0x80000001, 0xa0e40000, 0xa0e40001,                 /* sincos r0.x, r1.x, c0, c1    */
10424         0x02000001, 0xc00d0000, 0x90e40000,                                         /* mov oPos.xzw, v0             */
10425         0x03000005, 0xc0020000, 0x80000000, 0xa0ff0002,                             /* mul oPos.y, r0.x, c2.w       */
10426         0x02000001, 0xd00f0000, 0xa0a90002,                                         /* mov oD0, c2.yzzz             */
10427         0x0000ffff                                                                  /* end                          */
10428     };
10429     IDirect3DVertexShader9 *sin_shader, *cos_shader;
10430     HRESULT hr;
10431     struct {
10432         float x, y, z;
10433     } data[1280];
10434     unsigned int i;
10435     float sincosc1[4] = {D3DSINCOSCONST1};
10436     float sincosc2[4] = {D3DSINCOSCONST2};
10437
10438     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
10439     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10440
10441     hr = IDirect3DDevice9_CreateVertexShader(device, sin_shader_code, &sin_shader);
10442     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10443     hr = IDirect3DDevice9_CreateVertexShader(device, cos_shader_code, &cos_shader);
10444     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
10445     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10446     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with 0x%08x\n", hr);
10447     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, sincosc1, 1);
10448     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF failed with 0x%08x\n", hr);
10449     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, sincosc2, 1);
10450     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF failed with 0x%08x\n", hr);
10451
10452     /* Generate a point from -1 to 1 every 0.5 pixels */
10453     for(i = 0; i < 1280; i++) {
10454         data[i].x = (-640.0 + i) / 640.0;
10455         data[i].y = 0.0;
10456         data[i].z = 0.1;
10457     }
10458
10459     hr = IDirect3DDevice9_BeginScene(device);
10460     if(SUCCEEDED(hr)) {
10461         hr = IDirect3DDevice9_SetVertexShader(device, sin_shader);
10462         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with 0x%08x\n", hr);
10463         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1280, data, sizeof(*data));
10464         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed with 0x%08x\n", hr);
10465
10466         hr = IDirect3DDevice9_SetVertexShader(device, cos_shader);
10467         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with 0x%08x\n", hr);
10468         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1280, data, sizeof(*data));
10469         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed with 0x%08x\n", hr);
10470
10471         hr = IDirect3DDevice9_EndScene(device);
10472         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with 0x%08x\n", hr);
10473     }
10474     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10475     ok(SUCCEEDED(hr), "IDirect3DDevice9_Present returned %#x.\n", hr);
10476     /* TODO: Find a way to properly validate the lines. Precicion issues make this a kinda nasty task */
10477
10478     IDirect3DDevice9_SetVertexShader(device, NULL);
10479     IDirect3DVertexShader9_Release(sin_shader);
10480     IDirect3DVertexShader9_Release(cos_shader);
10481 }
10482
10483 static void loop_index_test(IDirect3DDevice9 *device) {
10484     const DWORD shader_code[] = {
10485         0xfffe0200,                                                 /* vs_2_0                   */
10486         0x0200001f, 0x80000000, 0x900f0000,                         /* dcl_position v0          */
10487         0x02000001, 0x800f0000, 0xa0e40000,                         /* mov r0, c0               */
10488         0x0200001b, 0xf0e40800, 0xf0e40000,                         /* loop aL, i0              */
10489         0x04000002, 0x800f0000, 0x80e40000, 0xa0e42001, 0xf0e40800, /* add r0, r0, c[aL + 1]    */
10490         0x0000001d,                                                 /* endloop                  */
10491         0x02000001, 0xc00f0000, 0x90e40000,                         /* mov oPos, v0             */
10492         0x02000001, 0xd00f0000, 0x80e40000,                         /* mov oD0, r0              */
10493         0x0000ffff                                                  /* END                      */
10494     };
10495     IDirect3DVertexShader9 *shader;
10496     HRESULT hr;
10497     DWORD color;
10498     const float quad[] = {
10499         -1.0,   -1.0,   0.1,
10500          1.0,   -1.0,   0.1,
10501         -1.0,    1.0,   0.1,
10502          1.0,    1.0,   0.1
10503     };
10504     const float zero[4] = {0, 0, 0, 0};
10505     const float one[4] = {1, 1, 1, 1};
10506     int i0[4] = {2, 10, -3, 0};
10507     float values[4];
10508
10509     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
10510     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader failed with %08x\n", hr);
10511     hr = IDirect3DDevice9_SetVertexShader(device, shader);
10512     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with %08x\n", hr);
10513     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10514     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
10515     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ff0000, 0.0, 0);
10516     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
10517
10518     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, zero, 1);
10519     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10520     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, one, 1);
10521     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10522     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 2, one, 1);
10523     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10524     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 3, one, 1);
10525     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10526     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 4, one, 1);
10527     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10528     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 5, one, 1);
10529     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10530     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 6, one, 1);
10531     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10532     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 7, one, 1);
10533     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10534     values[0] = 1.0;
10535     values[1] = 1.0;
10536     values[2] = 0.0;
10537     values[3] = 0.0;
10538     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 8, values, 1);
10539     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10540     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 9, one, 1);
10541     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10542     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 10, one, 1);
10543     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10544     values[0] = -1.0;
10545     values[1] = 0.0;
10546     values[2] = 0.0;
10547     values[3] = 0.0;
10548     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 11, values, 1);
10549     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10550     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 12, one, 1);
10551     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10552     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 13, one, 1);
10553     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10554     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 14, one, 1);
10555     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10556     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 15, one, 1);
10557     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantF returned %#x.\n", hr);
10558
10559     hr = IDirect3DDevice9_SetVertexShaderConstantI(device, 0, i0, 1);
10560     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShaderConstantI returned %#x.\n", hr);
10561
10562     hr = IDirect3DDevice9_BeginScene(device);
10563     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
10564     if(SUCCEEDED(hr))
10565     {
10566         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
10567         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
10568         hr = IDirect3DDevice9_EndScene(device);
10569         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
10570     }
10571     color = getPixelColor(device, 320, 240);
10572     ok(color_match(color, 0x0000ff00, 1),
10573        "aL indexing test returned color 0x%08x, expected 0x0000ff00\n", color);
10574     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10575     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
10576
10577     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
10578     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with %08x\n", hr);
10579     IDirect3DVertexShader9_Release(shader);
10580 }
10581
10582 static void sgn_test(IDirect3DDevice9 *device) {
10583     const DWORD shader_code[] = {
10584         0xfffe0200,                                                             /* vs_2_0                       */
10585         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position o0              */
10586         0x05000051, 0xa00f0000, 0xbf000000, 0x00000000, 0x3f000000, 0x41400000, /* def c0, -0.5, 0.0, 0.5, 12.0 */
10587         0x05000051, 0xa00f0001, 0x3fc00000, 0x00000000, 0x00000000, 0x00000000, /* def c1, 1.5, 0.0, 0.0, 0.0   */
10588         0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
10589         0x04000022, 0x800f0000, 0xa0e40000, 0x80e40001, 0x80e40002,             /* sgn r0, c0, r1, r2           */
10590         0x03000002, 0xd00f0000, 0x80e40000, 0xa0e40001,                         /* add oD0, r0, c1              */
10591         0x0000ffff                                                              /* end                          */
10592     };
10593     IDirect3DVertexShader9 *shader;
10594     HRESULT hr;
10595     DWORD color;
10596     const float quad[] = {
10597         -1.0,   -1.0,   0.1,
10598          1.0,   -1.0,   0.1,
10599         -1.0,    1.0,   0.1,
10600          1.0,    1.0,   0.1
10601     };
10602
10603     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
10604     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader failed with %08x\n", hr);
10605     hr = IDirect3DDevice9_SetVertexShader(device, shader);
10606     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with %08x\n", hr);
10607     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10608     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
10609     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ff0000, 0.0, 0);
10610     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
10611
10612     hr = IDirect3DDevice9_BeginScene(device);
10613     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
10614     if(SUCCEEDED(hr))
10615     {
10616         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
10617         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
10618         hr = IDirect3DDevice9_EndScene(device);
10619         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
10620     }
10621     color = getPixelColor(device, 320, 240);
10622     ok(color_match(color, 0x008000ff, 1),
10623        "sgn test returned color 0x%08x, expected 0x008000ff\n", color);
10624     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10625     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
10626
10627     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
10628     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed with %08x\n", hr);
10629     IDirect3DVertexShader9_Release(shader);
10630 }
10631
10632 static void viewport_test(IDirect3DDevice9 *device) {
10633     HRESULT hr;
10634     DWORD color;
10635     D3DVIEWPORT9 vp, old_vp;
10636     BOOL draw_failed = TRUE;
10637     const float quad[] =
10638     {
10639         -0.5,   -0.5,   0.1,
10640          0.5,   -0.5,   0.1,
10641         -0.5,    0.5,   0.1,
10642          0.5,    0.5,   0.1
10643     };
10644
10645     memset(&old_vp, 0, sizeof(old_vp));
10646     hr = IDirect3DDevice9_GetViewport(device, &old_vp);
10647     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %08x\n", hr);
10648
10649     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ff0000, 0.0, 0);
10650     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %08x\n", hr);
10651
10652     /* Test a viewport with Width and Height bigger than the surface dimensions
10653      *
10654      * TODO: Test Width < surface.width, but X + Width > surface.width
10655      * TODO: Test Width < surface.width, what happens with the height?
10656      *
10657      * The expected behavior is that the viewport behaves like the "default"
10658      * viewport with X = Y = 0, Width = surface_width, Height = surface_height,
10659      * MinZ = 0.0, MaxZ = 1.0.
10660      *
10661      * Starting with Windows 7 the behavior among driver versions is not
10662      * consistent. The SetViewport call is accepted on all drivers. Some
10663      * drivers(older nvidia ones) refuse to draw and return an error. Newer
10664      * nvidia drivers draw, but use the actual values in the viewport and only
10665      * display the upper left part on the surface.
10666      */
10667     memset(&vp, 0, sizeof(vp));
10668     vp.X = 0;
10669     vp.Y = 0;
10670     vp.Width = 10000;
10671     vp.Height = 10000;
10672     vp.MinZ = 0.0;
10673     vp.MaxZ = 0.0;
10674     hr = IDirect3DDevice9_SetViewport(device, &vp);
10675     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
10676
10677     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
10678     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %08x\n", hr);
10679     hr = IDirect3DDevice9_BeginScene(device);
10680     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %08x\n", hr);
10681     if(SUCCEEDED(hr))
10682     {
10683         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
10684         ok(hr == D3D_OK || broken(hr == D3DERR_INVALIDCALL), "DrawPrimitiveUP failed (%08x)\n", hr);
10685         draw_failed = FAILED(hr);
10686         hr = IDirect3DDevice9_EndScene(device);
10687         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %08x\n", hr);
10688     }
10689
10690     if(!draw_failed)
10691     {
10692         color = getPixelColor(device, 158, 118);
10693         ok(color == 0x00ff0000, "viewport test: (158,118) has color %08x\n", color);
10694         color = getPixelColor(device, 162, 118);
10695         ok(color == 0x00ff0000, "viewport test: (162,118) has color %08x\n", color);
10696         color = getPixelColor(device, 158, 122);
10697         ok(color == 0x00ff0000, "viewport test: (158,122) has color %08x\n", color);
10698         color = getPixelColor(device, 162, 122);
10699         ok(color == 0x00ffffff || broken(color == 0x00ff0000), "viewport test: (162,122) has color %08x\n", color);
10700
10701         color = getPixelColor(device, 478, 358);
10702         ok(color == 0x00ffffff || broken(color == 0x00ff0000), "viewport test: (478,358 has color %08x\n", color);
10703         color = getPixelColor(device, 482, 358);
10704         ok(color == 0x00ff0000, "viewport test: (482,358) has color %08x\n", color);
10705         color = getPixelColor(device, 478, 362);
10706         ok(color == 0x00ff0000, "viewport test: (478,362) has color %08x\n", color);
10707         color = getPixelColor(device, 482, 362);
10708         ok(color == 0x00ff0000, "viewport test: (482,362) has color %08x\n", color);
10709     }
10710
10711     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10712     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
10713
10714     hr = IDirect3DDevice9_SetViewport(device, &old_vp);
10715     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %08x\n", hr);
10716 }
10717
10718 /* This test tests depth clamping / clipping behaviour:
10719  *   - With software vertex processing, depth values are clamped to the
10720  *     minimum / maximum z value when D3DRS_CLIPPING is disabled, and clipped
10721  *     when D3DRS_CLIPPING is enabled. Pretransformed vertices behave the
10722  *     same as regular vertices here.
10723  *   - With hardware vertex processing, D3DRS_CLIPPING seems to be ignored.
10724  *     Normal vertices are always clipped. Pretransformed vertices are
10725  *     clipped when D3DPMISCCAPS_CLIPTLVERTS is set, clamped when it isn't.
10726  *   - The viewport's MinZ/MaxZ is irrelevant for this.
10727  */
10728 static void depth_clamp_test(IDirect3DDevice9 *device)
10729 {
10730     const struct tvertex quad1[] =
10731     {
10732         {  0.0f,   0.0f,  5.0f, 1.0f, 0xff002b7f},
10733         {640.0f,   0.0f,  5.0f, 1.0f, 0xff002b7f},
10734         {  0.0f, 480.0f,  5.0f, 1.0f, 0xff002b7f},
10735         {640.0f, 480.0f,  5.0f, 1.0f, 0xff002b7f},
10736     };
10737     const struct tvertex quad2[] =
10738     {
10739         {  0.0f, 300.0f, 10.0f, 1.0f, 0xfff9e814},
10740         {640.0f, 300.0f, 10.0f, 1.0f, 0xfff9e814},
10741         {  0.0f, 360.0f, 10.0f, 1.0f, 0xfff9e814},
10742         {640.0f, 360.0f, 10.0f, 1.0f, 0xfff9e814},
10743     };
10744     const struct tvertex quad3[] =
10745     {
10746         {112.0f, 108.0f,  5.0f, 1.0f, 0xffffffff},
10747         {208.0f, 108.0f,  5.0f, 1.0f, 0xffffffff},
10748         {112.0f, 204.0f,  5.0f, 1.0f, 0xffffffff},
10749         {208.0f, 204.0f,  5.0f, 1.0f, 0xffffffff},
10750     };
10751     const struct tvertex quad4[] =
10752     {
10753         { 42.0f,  41.0f, 10.0f, 1.0f, 0xffffffff},
10754         {112.0f,  41.0f, 10.0f, 1.0f, 0xffffffff},
10755         { 42.0f, 108.0f, 10.0f, 1.0f, 0xffffffff},
10756         {112.0f, 108.0f, 10.0f, 1.0f, 0xffffffff},
10757     };
10758     const struct vertex quad5[] =
10759     {
10760         { -0.5f,   0.5f, 10.0f,       0xff14f914},
10761         {  0.5f,   0.5f, 10.0f,       0xff14f914},
10762         { -0.5f,  -0.5f, 10.0f,       0xff14f914},
10763         {  0.5f,  -0.5f, 10.0f,       0xff14f914},
10764     };
10765     const struct vertex quad6[] =
10766     {
10767         { -1.0f,   0.5f, 10.0f,      0xfff91414},
10768         {  1.0f,   0.5f, 10.0f,      0xfff91414},
10769         { -1.0f,  0.25f, 10.0f,      0xfff91414},
10770         {  1.0f,  0.25f, 10.0f,      0xfff91414},
10771     };
10772
10773     D3DVIEWPORT9 vp;
10774     D3DCOLOR color;
10775     D3DCAPS9 caps;
10776     HRESULT hr;
10777
10778     vp.X = 0;
10779     vp.Y = 0;
10780     vp.Width = 640;
10781     vp.Height = 480;
10782     vp.MinZ = 0.0;
10783     vp.MaxZ = 7.5;
10784
10785     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
10786     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
10787
10788     hr = IDirect3DDevice9_SetViewport(device, &vp);
10789     if(FAILED(hr))
10790     {
10791         /* Windows 7 rejects MaxZ > 1.0, Windows XP allows it. This doesn't break
10792          * the tests because the 7.5 is just intended to show that it doesn't have
10793          * any influence on the drawing or D3DRS_CLIPPING = FALSE. Set an accepted
10794          * viewport and continue.
10795          */
10796         ok(broken(hr == D3DERR_INVALIDCALL), "D3D rejected maxZ > 1.0\n");
10797         vp.MaxZ = 1.0;
10798         hr = IDirect3DDevice9_SetViewport(device, &vp);
10799     }
10800     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
10801
10802     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ff00, 1.0, 0);
10803     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
10804
10805     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
10806     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10807     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
10808     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10809     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
10810     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10811     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
10812     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10813
10814     hr = IDirect3DDevice9_BeginScene(device);
10815     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
10816
10817     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
10818     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
10819
10820     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
10821     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10822     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
10823     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10824
10825     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, TRUE);
10826     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10827
10828     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(*quad3));
10829     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10830     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(*quad4));
10831     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10832
10833     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
10834     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10835
10836     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
10837     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
10838
10839     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad5, sizeof(*quad5));
10840     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10841
10842     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, TRUE);
10843     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10844
10845     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad6, sizeof(*quad6));
10846     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10847
10848     hr = IDirect3DDevice9_EndScene(device);
10849     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
10850
10851     if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_CLIPTLVERTS)
10852     {
10853         color = getPixelColor(device, 75, 75);
10854         ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
10855         color = getPixelColor(device, 150, 150);
10856         ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
10857         color = getPixelColor(device, 320, 240);
10858         ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
10859         color = getPixelColor(device, 320, 330);
10860         ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
10861         color = getPixelColor(device, 320, 330);
10862         ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
10863     }
10864     else
10865     {
10866         color = getPixelColor(device, 75, 75);
10867         ok(color_match(color, 0x00ffffff, 1), "color 0x%08x.\n", color);
10868         color = getPixelColor(device, 150, 150);
10869         ok(color_match(color, 0x00ffffff, 1), "color 0x%08x.\n", color);
10870         color = getPixelColor(device, 320, 240);
10871         ok(color_match(color, 0x00002b7f, 1), "color 0x%08x.\n", color);
10872         color = getPixelColor(device, 320, 330);
10873         ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
10874         color = getPixelColor(device, 320, 330);
10875         ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
10876     }
10877
10878     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
10879     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
10880
10881     vp.MinZ = 0.0;
10882     vp.MaxZ = 1.0;
10883     hr = IDirect3DDevice9_SetViewport(device, &vp);
10884     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
10885 }
10886
10887 static void depth_bounds_test(IDirect3DDevice9 *device)
10888 {
10889     const struct tvertex quad1[] =
10890     {
10891         {    0,    0, 0.0f, 1, 0xfff9e814},
10892         {  640,    0, 0.0f, 1, 0xfff9e814},
10893         {    0,  480, 1.0f, 1, 0xfff9e814},
10894         {  640,  480, 1.0f, 1, 0xfff9e814},
10895     };
10896     const struct tvertex quad2[] =
10897     {
10898         {    0,    0,  0.6f, 1, 0xff002b7f},
10899         {  640,    0,  0.6f, 1, 0xff002b7f},
10900         {    0,  480,  0.6f, 1, 0xff002b7f},
10901         {  640,  480,  0.6f, 1, 0xff002b7f},
10902     };
10903     const struct tvertex quad3[] =
10904     {
10905         {    0,  100, 0.6f, 1, 0xfff91414},
10906         {  640,  100, 0.6f, 1, 0xfff91414},
10907         {    0,  160, 0.6f, 1, 0xfff91414},
10908         {  640,  160, 0.6f, 1, 0xfff91414},
10909     };
10910
10911     union {
10912         DWORD d;
10913         float f;
10914     } tmpvalue;
10915
10916     IDirect3D9 *d3d = NULL;
10917     IDirect3DSurface9 *offscreen_surface = NULL;
10918     D3DCOLOR color;
10919     HRESULT hr;
10920
10921     IDirect3DDevice9_GetDirect3D(device, &d3d);
10922     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
10923             0,  D3DRTYPE_SURFACE, MAKEFOURCC('N','V','D','B')) != D3D_OK) {
10924         skip("No NVDB (depth bounds test) support\n");
10925         IDirect3D9_Release(d3d);
10926         return;
10927     }
10928     IDirect3D9_Release(d3d);
10929
10930     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32,
10931             MAKEFOURCC('N','V','D','B'), D3DPOOL_DEFAULT, &offscreen_surface, NULL);
10932     ok(FAILED(hr), "Able to create surface, hr %#x.\n", hr);
10933     if (offscreen_surface) IDirect3DSurface9_Release(offscreen_surface);
10934
10935     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0, 0);
10936     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
10937
10938     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
10939     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10940     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, TRUE);
10941     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10942     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
10943     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10944     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
10945     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10946
10947
10948     hr = IDirect3DDevice9_BeginScene(device);
10949     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
10950
10951     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
10952     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
10953
10954     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
10955     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10956
10957     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ADAPTIVETESS_X, MAKEFOURCC('N','V','D','B'));
10958     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10959
10960     tmpvalue.f = 0.625;
10961     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ADAPTIVETESS_Z, tmpvalue.d);
10962     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10963
10964     tmpvalue.f = 0.75;
10965     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ADAPTIVETESS_W, tmpvalue.d);
10966     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10967
10968     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
10969     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10970
10971     tmpvalue.f = 0.75;
10972     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ADAPTIVETESS_Z, tmpvalue.d);
10973     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10974
10975     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(*quad3));
10976     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
10977
10978     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ADAPTIVETESS_X, 0);
10979     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
10980
10981     hr = IDirect3DDevice9_EndScene(device);
10982     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
10983
10984     color = getPixelColor(device, 150, 130);
10985     ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
10986     color = getPixelColor(device, 150, 200);
10987     ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
10988     color = getPixelColor(device, 150, 300-5);
10989     ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
10990     color = getPixelColor(device, 150, 300+5);
10991     ok(color_match(color, 0x00002b7f, 1), "color 0x%08x.\n", color);/**/
10992     color = getPixelColor(device, 150, 330);
10993     ok(color_match(color, 0x00002b7f, 1), "color 0x%08x.\n", color);
10994     color = getPixelColor(device, 150, 360-5);
10995     ok(color_match(color, 0x00002b7f, 1), "color 0x%08x.\n", color);/**/
10996     color = getPixelColor(device, 150, 360+5);
10997     ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
10998
10999     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11000     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
11001 }
11002
11003 static void depth_buffer_test(IDirect3DDevice9 *device)
11004 {
11005     static const struct vertex quad1[] =
11006     {
11007         { -1.0,  1.0, 0.33f, 0xff00ff00},
11008         {  1.0,  1.0, 0.33f, 0xff00ff00},
11009         { -1.0, -1.0, 0.33f, 0xff00ff00},
11010         {  1.0, -1.0, 0.33f, 0xff00ff00},
11011     };
11012     static const struct vertex quad2[] =
11013     {
11014         { -1.0,  1.0, 0.50f, 0xffff00ff},
11015         {  1.0,  1.0, 0.50f, 0xffff00ff},
11016         { -1.0, -1.0, 0.50f, 0xffff00ff},
11017         {  1.0, -1.0, 0.50f, 0xffff00ff},
11018     };
11019     static const struct vertex quad3[] =
11020     {
11021         { -1.0,  1.0, 0.66f, 0xffff0000},
11022         {  1.0,  1.0, 0.66f, 0xffff0000},
11023         { -1.0, -1.0, 0.66f, 0xffff0000},
11024         {  1.0, -1.0, 0.66f, 0xffff0000},
11025     };
11026     static const DWORD expected_colors[4][4] =
11027     {
11028         {0x000000ff, 0x000000ff, 0x0000ff00, 0x00ff0000},
11029         {0x000000ff, 0x000000ff, 0x0000ff00, 0x00ff0000},
11030         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x00ff0000},
11031         {0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000},
11032     };
11033
11034     IDirect3DSurface9 *backbuffer, *rt1, *rt2, *rt3;
11035     unsigned int i, j;
11036     D3DVIEWPORT9 vp;
11037     D3DCOLOR color;
11038     HRESULT hr;
11039
11040     vp.X = 0;
11041     vp.Y = 0;
11042     vp.Width = 640;
11043     vp.Height = 480;
11044     vp.MinZ = 0.0;
11045     vp.MaxZ = 1.0;
11046
11047     hr = IDirect3DDevice9_SetViewport(device, &vp);
11048     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
11049
11050     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
11051     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11052     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
11053     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11054     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
11055     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11056     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
11057     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11058     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
11059     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
11060
11061     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
11062     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
11063     hr = IDirect3DDevice9_CreateRenderTarget(device, 320, 240, D3DFMT_A8R8G8B8,
11064             D3DMULTISAMPLE_NONE, 0, FALSE, &rt1, NULL);
11065     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
11066     hr = IDirect3DDevice9_CreateRenderTarget(device, 480, 360, D3DFMT_A8R8G8B8,
11067             D3DMULTISAMPLE_NONE, 0, FALSE, &rt2, NULL);
11068     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
11069     hr = IDirect3DDevice9_CreateRenderTarget(device, 640, 480, D3DFMT_A8R8G8B8,
11070             D3DMULTISAMPLE_NONE, 0, FALSE, &rt3, NULL);
11071     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
11072
11073     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt3);
11074     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11075     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 0.0f, 0);
11076     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11077
11078     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
11079     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11080     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
11081     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11082
11083     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt1);
11084     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11085     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0f, 0);
11086     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11087
11088     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt2);
11089     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11090     hr = IDirect3DDevice9_BeginScene(device);
11091     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11092     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
11093     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11094     hr = IDirect3DDevice9_EndScene(device);
11095     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11096
11097     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
11098     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11099     IDirect3DSurface9_Release(backbuffer);
11100     IDirect3DSurface9_Release(rt3);
11101     IDirect3DSurface9_Release(rt2);
11102     IDirect3DSurface9_Release(rt1);
11103
11104     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
11105     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11106
11107     hr = IDirect3DDevice9_BeginScene(device);
11108     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11109     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
11110     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11111     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(*quad3));
11112     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11113     hr = IDirect3DDevice9_EndScene(device);
11114     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11115
11116     for (i = 0; i < 4; ++i)
11117     {
11118         for (j = 0; j < 4; ++j)
11119         {
11120             unsigned int x = 80 * ((2 * j) + 1);
11121             unsigned int y = 60 * ((2 * i) + 1);
11122             color = getPixelColor(device, x, y);
11123             ok(color_match(color, expected_colors[i][j], 0),
11124                     "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
11125         }
11126     }
11127
11128     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11129     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
11130 }
11131
11132 /* Test that partial depth copies work the way they're supposed to. The clear
11133  * on rt2 only needs a partial copy of the onscreen depth/stencil buffer, and
11134  * the following draw should only copy back the part that was modified. */
11135 static void depth_buffer2_test(IDirect3DDevice9 *device)
11136 {
11137     static const struct vertex quad[] =
11138     {
11139         { -1.0,  1.0, 0.66f, 0xffff0000},
11140         {  1.0,  1.0, 0.66f, 0xffff0000},
11141         { -1.0, -1.0, 0.66f, 0xffff0000},
11142         {  1.0, -1.0, 0.66f, 0xffff0000},
11143     };
11144
11145     IDirect3DSurface9 *backbuffer, *rt1, *rt2;
11146     unsigned int i, j;
11147     D3DVIEWPORT9 vp;
11148     D3DCOLOR color;
11149     HRESULT hr;
11150
11151     vp.X = 0;
11152     vp.Y = 0;
11153     vp.Width = 640;
11154     vp.Height = 480;
11155     vp.MinZ = 0.0;
11156     vp.MaxZ = 1.0;
11157
11158     hr = IDirect3DDevice9_SetViewport(device, &vp);
11159     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
11160
11161     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
11162     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11163     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
11164     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11165     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
11166     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11167     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
11168     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11169     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
11170     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
11171
11172     hr = IDirect3DDevice9_CreateRenderTarget(device, 640, 480, D3DFMT_A8R8G8B8,
11173             D3DMULTISAMPLE_NONE, 0, FALSE, &rt1, NULL);
11174     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
11175     hr = IDirect3DDevice9_CreateRenderTarget(device, 480, 360, D3DFMT_A8R8G8B8,
11176             D3DMULTISAMPLE_NONE, 0, FALSE, &rt2, NULL);
11177     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
11178     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
11179     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
11180
11181     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt1);
11182     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11183     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
11184     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11185
11186     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
11187     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11188     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ff00, 0.5f, 0);
11189     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11190
11191     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt2);
11192     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11193     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0f, 0);
11194     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11195
11196     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
11197     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11198     IDirect3DSurface9_Release(backbuffer);
11199     IDirect3DSurface9_Release(rt2);
11200     IDirect3DSurface9_Release(rt1);
11201
11202     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
11203     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11204
11205     hr = IDirect3DDevice9_BeginScene(device);
11206     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11207     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
11208     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11209     hr = IDirect3DDevice9_EndScene(device);
11210     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11211
11212     for (i = 0; i < 4; ++i)
11213     {
11214         for (j = 0; j < 4; ++j)
11215         {
11216             unsigned int x = 80 * ((2 * j) + 1);
11217             unsigned int y = 60 * ((2 * i) + 1);
11218             color = getPixelColor(device, x, y);
11219             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 0),
11220                     "Expected color 0x0000ff00 at %u,%u, got 0x%08x.\n", x, y, color);
11221         }
11222     }
11223
11224     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11225     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
11226 }
11227
11228 static void depth_blit_test(IDirect3DDevice9 *device)
11229 {
11230     static const struct vertex quad1[] =
11231     {
11232         { -1.0,  1.0, 0.50f, 0xff00ff00},
11233         {  1.0,  1.0, 0.50f, 0xff00ff00},
11234         { -1.0, -1.0, 0.50f, 0xff00ff00},
11235         {  1.0, -1.0, 0.50f, 0xff00ff00},
11236     };
11237     static const struct vertex quad2[] =
11238     {
11239         { -1.0,  1.0, 0.66f, 0xff0000ff},
11240         {  1.0,  1.0, 0.66f, 0xff0000ff},
11241         { -1.0, -1.0, 0.66f, 0xff0000ff},
11242         {  1.0, -1.0, 0.66f, 0xff0000ff},
11243     };
11244     static const DWORD expected_colors[4][4] =
11245     {
11246         {0x000000ff, 0x000000ff, 0x0000ff00, 0x00ff0000},
11247         {0x000000ff, 0x000000ff, 0x0000ff00, 0x00ff0000},
11248         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x00ff0000},
11249         {0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000},
11250     };
11251
11252     IDirect3DSurface9 *backbuffer, *ds1, *ds2;
11253     RECT src_rect, dst_rect;
11254     unsigned int i, j;
11255     D3DVIEWPORT9 vp;
11256     D3DCOLOR color;
11257     HRESULT hr;
11258
11259     vp.X = 0;
11260     vp.Y = 0;
11261     vp.Width = 640;
11262     vp.Height = 480;
11263     vp.MinZ = 0.0;
11264     vp.MaxZ = 1.0;
11265
11266     hr = IDirect3DDevice9_SetViewport(device, &vp);
11267     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
11268
11269     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuffer);
11270     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
11271     hr = IDirect3DDevice9_GetDepthStencilSurface(device, &ds1);
11272     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
11273     hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8, 0, 0, FALSE, &ds2, NULL);
11274     ok(SUCCEEDED(hr), "CreateDepthStencilSurface failed, hr %#x.\n", hr);
11275     hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds2);
11276     ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11277
11278     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
11279     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11280     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
11281     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11282     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
11283     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11284     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
11285     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
11286
11287     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
11288     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11289     SetRect(&dst_rect, 0, 0, 480, 360);
11290     hr = IDirect3DDevice9_Clear(device, 1, (D3DRECT *)&dst_rect, D3DCLEAR_ZBUFFER, 0, 0.5f, 0);
11291     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11292     SetRect(&dst_rect, 0, 0, 320, 240);
11293     hr = IDirect3DDevice9_Clear(device, 1, (D3DRECT *)&dst_rect, D3DCLEAR_ZBUFFER, 0, 1.0f, 0);
11294     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11295
11296     /* Partial blit. */
11297     SetRect(&src_rect, 0, 0, 320, 240);
11298     SetRect(&dst_rect, 0, 0, 320, 240);
11299     hr = IDirect3DDevice9_StretchRect(device, ds2, &src_rect, ds1, &dst_rect, D3DTEXF_POINT);
11300     ok(hr == D3DERR_INVALIDCALL, "StretchRect returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
11301     /* Flipped. */
11302     SetRect(&src_rect, 0, 0, 640, 480);
11303     SetRect(&dst_rect, 0, 480, 640, 0);
11304     hr = IDirect3DDevice9_StretchRect(device, ds2, &src_rect, ds1, &dst_rect, D3DTEXF_POINT);
11305     ok(hr == D3DERR_INVALIDCALL, "StretchRect returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
11306     /* Full, explicit. */
11307     SetRect(&src_rect, 0, 0, 640, 480);
11308     SetRect(&dst_rect, 0, 0, 640, 480);
11309     hr = IDirect3DDevice9_StretchRect(device, ds2, &src_rect, ds1, &dst_rect, D3DTEXF_POINT);
11310     ok(SUCCEEDED(hr), "StretchRect failed, hr %#x.\n", hr);
11311     /* Filtered blit. */
11312     hr = IDirect3DDevice9_StretchRect(device, ds2, NULL, ds1, NULL, D3DTEXF_LINEAR);
11313     ok(SUCCEEDED(hr), "StretchRect failed, hr %#x.\n", hr);
11314     /* Depth -> color blit.*/
11315     hr = IDirect3DDevice9_StretchRect(device, ds2, NULL, backbuffer, NULL, D3DTEXF_POINT);
11316     ok(hr == D3DERR_INVALIDCALL, "StretchRect returned %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
11317     IDirect3DSurface9_Release(backbuffer);
11318
11319     hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds1);
11320     ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11321     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, 0xffff0000, 1.0f, 0);
11322     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11323     hr = IDirect3DDevice9_StretchRect(device, ds2, NULL, ds1, NULL, D3DTEXF_POINT);
11324     ok(SUCCEEDED(hr), "StretchRect failed, hr %#x.\n", hr);
11325     IDirect3DSurface9_Release(ds2);
11326     IDirect3DSurface9_Release(ds1);
11327
11328     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
11329     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11330     hr = IDirect3DDevice9_BeginScene(device);
11331     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11332     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
11333     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11334     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
11335     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11336     hr = IDirect3DDevice9_EndScene(device);
11337     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11338
11339     for (i = 0; i < 4; ++i)
11340     {
11341         for (j = 0; j < 4; ++j)
11342         {
11343             unsigned int x = 80 * ((2 * j) + 1);
11344             unsigned int y = 60 * ((2 * i) + 1);
11345             color = getPixelColor(device, x, y);
11346             ok(color_match(color, expected_colors[i][j], 0),
11347                     "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
11348         }
11349     }
11350
11351     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11352     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
11353 }
11354
11355 static void intz_test(IDirect3DDevice9 *device)
11356 {
11357     static const DWORD ps_code[] =
11358     {
11359         0xffff0200,                                                             /* ps_2_0                       */
11360         0x0200001f, 0x90000000, 0xa00f0800,                                     /* dcl_2d s0                    */
11361         0x0200001f, 0x80000000, 0xb00f0000,                                     /* dcl t0                       */
11362         0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0.0, 0.0, 0.0, 1.0   */
11363         0x02000001, 0x800f0001, 0xa0e40000,                                     /* mov r1, c0                   */
11364         0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800,                         /* texld r0, t0, s0             */
11365         0x02000001, 0x80010001, 0x80e40000,                                     /* mov r1.x, r0                 */
11366         0x03010042, 0x800f0000, 0xb0e40000, 0xa0e40800,                         /* texldp r0, t0, s0            */
11367         0x02000001, 0x80020001, 0x80000000,                                     /* mov r1.y, r0.x               */
11368         0x02000001, 0x800f0800, 0x80e40001,                                     /* mov oC0, r1                  */
11369         0x0000ffff,                                                             /* end                          */
11370     };
11371     struct
11372     {
11373         float x, y, z;
11374         float s, t, p, q;
11375     }
11376     quad[] =
11377     {
11378         { -1.0f,  1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.5f},
11379         {  1.0f,  1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.5f},
11380         { -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f},
11381         {  1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.5f},
11382     };
11383     struct
11384     {
11385         UINT x, y;
11386         D3DCOLOR color;
11387     }
11388     expected_colors[] =
11389     {
11390         { 80, 100, D3DCOLOR_ARGB(0x00, 0x20, 0x40, 0x00)},
11391         {240, 100, D3DCOLOR_ARGB(0x00, 0x60, 0xbf, 0x00)},
11392         {400, 100, D3DCOLOR_ARGB(0x00, 0x9f, 0x40, 0x00)},
11393         {560, 100, D3DCOLOR_ARGB(0x00, 0xdf, 0xbf, 0x00)},
11394         { 80, 450, D3DCOLOR_ARGB(0x00, 0x20, 0x40, 0x00)},
11395         {240, 450, D3DCOLOR_ARGB(0x00, 0x60, 0xbf, 0x00)},
11396         {400, 450, D3DCOLOR_ARGB(0x00, 0x9f, 0x40, 0x00)},
11397         {560, 450, D3DCOLOR_ARGB(0x00, 0xdf, 0xbf, 0x00)},
11398     };
11399
11400     IDirect3DSurface9 *original_ds, *original_rt, *rt;
11401     IDirect3DTexture9 *texture;
11402     IDirect3DPixelShader9 *ps;
11403     IDirect3DSurface9 *ds;
11404     IDirect3D9 *d3d9;
11405     D3DCAPS9 caps;
11406     HRESULT hr;
11407     UINT i;
11408
11409     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11410     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
11411     if (caps.PixelShaderVersion < D3DPS_VERSION(2, 0))
11412     {
11413         skip("No pixel shader 2.0 support, skipping INTZ test.\n");
11414         return;
11415     }
11416
11417     hr = IDirect3DDevice9_GetDirect3D(device, &d3d9);
11418     ok(SUCCEEDED(hr), "GetDirect3D failed, hr %#x.\n", hr);
11419
11420     hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11421             D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, MAKEFOURCC('I','N','T','Z'));
11422     if (FAILED(hr))
11423     {
11424         skip("No INTZ support, skipping INTZ test.\n");
11425         return;
11426     }
11427
11428     IDirect3D9_Release(d3d9);
11429
11430     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &original_rt);
11431     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
11432     hr = IDirect3DDevice9_GetDepthStencilSurface(device, &original_ds);
11433     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
11434
11435     hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1,
11436             D3DUSAGE_DEPTHSTENCIL, MAKEFOURCC('I','N','T','Z'), D3DPOOL_DEFAULT, &texture, NULL);
11437     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
11438     hr = IDirect3DDevice9_CreateRenderTarget(device, 1024, 1024, D3DFMT_A8R8G8B8,
11439             D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
11440     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
11441     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code, &ps);
11442     ok(SUCCEEDED(hr), "CreatePixelShader failed, hr %#x.\n", hr);
11443
11444     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE4(0));
11445     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
11446     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
11447     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11448     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
11449     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11450     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
11451     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11452     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
11453     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11454
11455     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
11456     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11457     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
11458     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11459     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
11460     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11461     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
11462     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11463     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
11464     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11465
11466     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &ds);
11467     ok(SUCCEEDED(hr), "GetSurfaceLevel failed, hr %#x.\n", hr);
11468     hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
11469     ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11470     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
11471     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11472     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
11473     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
11474
11475     /* Setup the depth/stencil surface. */
11476     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
11477     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11478
11479     hr = IDirect3DDevice9_BeginScene(device);
11480     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11481     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
11482     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11483     hr = IDirect3DDevice9_EndScene(device);
11484     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11485
11486     hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
11487     ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11488     IDirect3DSurface9_Release(ds);
11489     hr = IDirect3DDevice9_SetRenderTarget(device, 0, original_rt);
11490     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11491     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
11492     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
11493     hr = IDirect3DDevice9_SetPixelShader(device, ps);
11494     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
11495
11496     /* Read the depth values back. */
11497     hr = IDirect3DDevice9_BeginScene(device);
11498     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11499     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
11500     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11501     hr = IDirect3DDevice9_EndScene(device);
11502     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11503
11504     for (i = 0; i < sizeof(expected_colors) / sizeof(*expected_colors); ++i)
11505     {
11506         D3DCOLOR color = getPixelColor(device, expected_colors[i].x, expected_colors[i].y);
11507         ok(color_match(color, expected_colors[i].color, 1),
11508                 "Expected color 0x%08x at (%u, %u), got 0x%08x.\n",
11509                 expected_colors[i].color, expected_colors[i].x, expected_colors[i].y, color);
11510     }
11511
11512     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11513     ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
11514
11515     hr = IDirect3DDevice9_SetDepthStencilSurface(device, original_ds);
11516     ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11517     IDirect3DSurface9_Release(original_ds);
11518     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
11519     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
11520     IDirect3DTexture9_Release(texture);
11521     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
11522     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
11523     IDirect3DPixelShader9_Release(ps);
11524
11525     IDirect3DSurface9_Release(original_rt);
11526     IDirect3DSurface9_Release(rt);
11527 }
11528
11529 static void shadow_test(IDirect3DDevice9 *device)
11530 {
11531     static const DWORD ps_code[] =
11532     {
11533         0xffff0200,                                                             /* ps_2_0                       */
11534         0x0200001f, 0x90000000, 0xa00f0800,                                     /* dcl_2d s0                    */
11535         0x0200001f, 0x80000000, 0xb00f0000,                                     /* dcl t0                       */
11536         0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0.0, 0.0, 0.0, 1.0   */
11537         0x02000001, 0x800f0001, 0xa0e40000,                                     /* mov r1, c0                   */
11538         0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800,                         /* texld r0, t0, s0             */
11539         0x02000001, 0x80010001, 0x80e40000,                                     /* mov r1.x, r0                 */
11540         0x03010042, 0x800f0000, 0xb0e40000, 0xa0e40800,                         /* texldp r0, t0, s0            */
11541         0x02000001, 0x80020001, 0x80000000,                                     /* mov r1.y, r0.x               */
11542         0x02000001, 0x800f0800, 0x80e40001,                                     /* mov 0C0, r1                  */
11543         0x0000ffff,                                                             /* end                          */
11544     };
11545     struct
11546     {
11547         D3DFORMAT format;
11548         const char *name;
11549     }
11550     formats[] =
11551     {
11552         {D3DFMT_D16_LOCKABLE,   "D3DFMT_D16_LOCKABLE"},
11553         {D3DFMT_D32,            "D3DFMT_D32"},
11554         {D3DFMT_D15S1,          "D3DFMT_D15S1"},
11555         {D3DFMT_D24S8,          "D3DFMT_D24S8"},
11556         {D3DFMT_D24X8,          "D3DFMT_D24X8"},
11557         {D3DFMT_D24X4S4,        "D3DFMT_D24X4S4"},
11558         {D3DFMT_D16,            "D3DFMT_D16"},
11559         {D3DFMT_D32F_LOCKABLE,  "D3DFMT_D32F_LOCKABLE"},
11560         {D3DFMT_D24FS8,         "D3DFMT_D24FS8"},
11561     };
11562     struct
11563     {
11564         float x, y, z;
11565         float s, t, p, q;
11566     }
11567     quad[] =
11568     {
11569         { -1.0f,  1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f},
11570         {  1.0f,  1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f},
11571         { -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
11572         {  1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f},
11573     };
11574     struct
11575     {
11576         UINT x, y;
11577         D3DCOLOR color;
11578     }
11579     expected_colors[] =
11580     {
11581         {400,  60, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
11582         {560, 180, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00)},
11583         {560, 300, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00)},
11584         {400, 420, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00)},
11585         {240, 420, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00)},
11586         { 80, 300, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
11587         { 80, 180, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
11588         {240,  60, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
11589     };
11590
11591     IDirect3DSurface9 *original_ds, *original_rt, *rt;
11592     IDirect3DPixelShader9 *ps;
11593     IDirect3D9 *d3d9;
11594     D3DCAPS9 caps;
11595     HRESULT hr;
11596     UINT i;
11597
11598     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11599     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
11600     if (caps.PixelShaderVersion < D3DPS_VERSION(2, 0))
11601     {
11602         skip("No pixel shader 2.0 support, skipping shadow test.\n");
11603         return;
11604     }
11605
11606     hr = IDirect3DDevice9_GetDirect3D(device, &d3d9);
11607     ok(SUCCEEDED(hr), "GetDirect3D failed, hr %#x.\n", hr);
11608     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &original_rt);
11609     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
11610     hr = IDirect3DDevice9_GetDepthStencilSurface(device, &original_ds);
11611     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
11612
11613     hr = IDirect3DDevice9_CreateRenderTarget(device, 1024, 1024, D3DFMT_A8R8G8B8,
11614             D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
11615     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
11616     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code, &ps);
11617     ok(SUCCEEDED(hr), "CreatePixelShader failed, hr %#x.\n", hr);
11618
11619     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE4(0));
11620     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
11621     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
11622     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11623     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
11624     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11625     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
11626     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11627     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
11628     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11629
11630     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
11631     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11632     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
11633     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11634     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
11635     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11636     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
11637     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11638     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
11639     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
11640
11641     for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i)
11642     {
11643         D3DFORMAT format = formats[i].format;
11644         IDirect3DTexture9 *texture;
11645         IDirect3DSurface9 *ds;
11646         unsigned int j;
11647
11648         hr = IDirect3D9_CheckDeviceFormat(d3d9, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
11649                 D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, format);
11650         if (FAILED(hr)) continue;
11651
11652         hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 1,
11653                 D3DUSAGE_DEPTHSTENCIL, format, D3DPOOL_DEFAULT, &texture, NULL);
11654         ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
11655
11656         hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &ds);
11657         ok(SUCCEEDED(hr), "GetSurfaceLevel failed, hr %#x.\n", hr);
11658
11659         hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
11660         ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11661
11662         hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
11663         ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11664
11665         IDirect3DDevice9_SetPixelShader(device, NULL);
11666         ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
11667
11668         /* Setup the depth/stencil surface. */
11669         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
11670         ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11671
11672         hr = IDirect3DDevice9_BeginScene(device);
11673         ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11674         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
11675         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11676         hr = IDirect3DDevice9_EndScene(device);
11677         ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11678
11679         hr = IDirect3DDevice9_SetDepthStencilSurface(device, NULL);
11680         ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11681         IDirect3DSurface9_Release(ds);
11682
11683         hr = IDirect3DDevice9_SetRenderTarget(device, 0, original_rt);
11684         ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
11685
11686         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
11687         ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
11688
11689         hr = IDirect3DDevice9_SetPixelShader(device, ps);
11690         ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
11691
11692         /* Do the actual shadow mapping. */
11693         hr = IDirect3DDevice9_BeginScene(device);
11694         ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11695         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
11696         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11697         hr = IDirect3DDevice9_EndScene(device);
11698         ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11699
11700         hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
11701         ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
11702         IDirect3DTexture9_Release(texture);
11703
11704         for (j = 0; j < sizeof(expected_colors) / sizeof(*expected_colors); ++j)
11705         {
11706             D3DCOLOR color = getPixelColor(device, expected_colors[j].x, expected_colors[j].y);
11707             ok(color_match(color, expected_colors[j].color, 0),
11708                     "Expected color 0x%08x at (%u, %u) for format %s, got 0x%08x.\n",
11709                     expected_colors[j].color, expected_colors[j].x, expected_colors[j].y,
11710                     formats[i].name, color);
11711         }
11712
11713         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11714         ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
11715     }
11716
11717     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
11718     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
11719     IDirect3DPixelShader9_Release(ps);
11720
11721     hr = IDirect3DDevice9_SetDepthStencilSurface(device, original_ds);
11722     ok(SUCCEEDED(hr), "SetDepthStencilSurface failed, hr %#x.\n", hr);
11723     IDirect3DSurface9_Release(original_ds);
11724
11725     IDirect3DSurface9_Release(original_rt);
11726     IDirect3DSurface9_Release(rt);
11727
11728     IDirect3D9_Release(d3d9);
11729 }
11730
11731 static void clip_planes(IDirect3DDevice9 *device, const char *test_name)
11732 {
11733     const struct vertex quad1[] =
11734     {
11735         {-1.0f, -1.0f, 0.0f, 0xfff9e814},
11736         { 1.0f, -1.0f, 0.0f, 0xfff9e814},
11737         {-1.0f,  1.0f, 0.0f, 0xfff9e814},
11738         { 1.0f,  1.0f, 0.0f, 0xfff9e814},
11739     };
11740     const struct vertex quad2[] =
11741     {
11742         {-1.0f, -1.0f, 0.0f, 0xff002b7f},
11743         { 1.0f, -1.0f, 0.0f, 0xff002b7f},
11744         {-1.0f,  1.0f, 0.0f, 0xff002b7f},
11745         { 1.0f,  1.0f, 0.0f, 0xff002b7f},
11746     };
11747     D3DCOLOR color;
11748     HRESULT hr;
11749
11750     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 1.0, 0);
11751     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
11752
11753     hr = IDirect3DDevice9_BeginScene(device);
11754     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
11755
11756     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
11757     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
11758
11759     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0);
11760     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11761     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
11762     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11763
11764     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0x1);
11765     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11766     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
11767     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
11768
11769     hr = IDirect3DDevice9_EndScene(device);
11770     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
11771
11772     color = getPixelColor(device, 1, 240);
11773     ok(color_match(color, 0x00002b7f, 1), "%s test: color 0x%08x.\n", test_name, color);
11774     color = getPixelColor(device, 638, 240);
11775     ok(color_match(color, 0x00002b7f, 1), "%s test: color 0x%08x.\n", test_name, color);
11776
11777     color = getPixelColor(device, 1, 241);
11778     ok(color_match(color, 0x00f9e814, 1), "%s test: color 0x%08x.\n", test_name, color);
11779     color = getPixelColor(device, 638, 241);
11780     ok(color_match(color, 0x00f9e814, 1), "%s test: color 0x%08x.\n", test_name, color);
11781 }
11782
11783 static void clip_planes_test(IDirect3DDevice9 *device)
11784 {
11785     const float plane0[4] = {0.0f, 1.0f, 0.0f, 0.5f / 480.0f}; /* a quarter-pixel offset */
11786
11787     const DWORD shader_code[] = {
11788         0xfffe0200, /* vs_2_0 */
11789         0x0200001f, 0x80000000, 0x900f0000, /* dcl_position v0 */
11790         0x0200001f, 0x8000000a, 0x900f0001, /* dcl_color0 v1 */
11791         0x02000001, 0xc00f0000, 0x90e40000, /* mov oPos, v0 */
11792         0x02000001, 0xd00f0000, 0x90e40001, /* mov oD0, v1 */
11793         0x0000ffff /* end */
11794     };
11795     IDirect3DVertexShader9 *shader;
11796
11797     IDirect3DTexture9 *offscreen = NULL;
11798     IDirect3DSurface9 *offscreen_surface, *original_rt;
11799     HRESULT hr;
11800
11801     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &original_rt);
11802     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
11803
11804     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
11805     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11806     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
11807     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11808     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
11809     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11810     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, TRUE);
11811     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
11812
11813     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
11814     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed, hr=%08x\n", hr);
11815     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
11816     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed, hr=%08x\n", hr);
11817
11818     IDirect3DDevice9_SetClipPlane(device, 0, plane0);
11819
11820     clip_planes(device, "Onscreen FFP");
11821
11822     hr = IDirect3DDevice9_CreateTexture(device, 640, 480, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &offscreen, NULL);
11823     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
11824     hr = IDirect3DTexture9_GetSurfaceLevel(offscreen, 0, &offscreen_surface);
11825     ok(SUCCEEDED(hr), "GetSurfaceLevel failed, hr %#x.\n", hr);
11826     hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen_surface);
11827     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
11828
11829     clip_planes(device, "Offscreen FFP");
11830
11831     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11832     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
11833
11834     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
11835     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %08x\n", hr);
11836     IDirect3DDevice9_SetVertexShader(device, shader);
11837     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %08x\n", hr);
11838
11839     hr = IDirect3DDevice9_SetRenderTarget(device, 0, original_rt);
11840     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
11841
11842     clip_planes(device, "Onscreen vertex shader");
11843
11844     hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen_surface);
11845     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
11846
11847     clip_planes(device, "Offscreen vertex shader");
11848
11849     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
11850     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
11851
11852     IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPLANEENABLE, 0);
11853     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
11854     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader failed, hr=%08x\n", hr);
11855     IDirect3DVertexShader9_Release(shader);
11856     hr = IDirect3DDevice9_SetRenderTarget(device, 0, original_rt);
11857     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%08x\n", hr);
11858     IDirect3DSurface9_Release(original_rt);
11859     IDirect3DSurface9_Release(offscreen_surface);
11860     IDirect3DTexture9_Release(offscreen);
11861 }
11862
11863 static void fp_special_test(IDirect3DDevice9 *device)
11864 {
11865     static const DWORD vs_header[] =
11866     {
11867         0xfffe0200,                                                             /* vs_2_0                       */
11868         0x05000051, 0xa00f0000, 0x00000000, 0x3f000000, 0x3f800000, 0x40000000, /* def c0, 0.0, 0.5, 1.0, 2.0   */
11869         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
11870         0x0200001f, 0x80000005, 0x900f0001,                                     /* dcl_texcoord0 v1             */
11871     };
11872
11873     static const DWORD vs_log[] = {0x0200000f, 0x80010000, 0x90000001};         /* log r0.x, v1.x               */
11874     static const DWORD vs_pow[] =
11875             {0x03000020, 0x80010000, 0x90000001, 0x90000001};                   /* pow r0.x, v1.x, v1.x         */
11876     static const DWORD vs_nrm[] = {0x02000024, 0x80070000, 0x90000001};         /* nrm r0.xyz, v1.x             */
11877     static const DWORD vs_rcp1[] = {0x02000006, 0x80010000, 0x90000001};        /* rcp r0.x, v1.x               */
11878     static const DWORD vs_rcp2[] = {0x02000006, 0x80010000, 0x91000001};        /* rcp r0.x, -v1.x              */
11879     static const DWORD vs_rsq1[] = {0x02000007, 0x80010000, 0x90000001};        /* rsq r0.x, v1.x               */
11880     static const DWORD vs_rsq2[] = {0x02000007, 0x80010000, 0x91000001};        /* rsq r0.x, -v1.x              */
11881     static const DWORD vs_lit[] = {0x02000010, 0x800f0000, 0x90000001,          /* lit r0, v1.xxxx              */
11882             0x02000001, 0x80010000, 0x80aa0000};                                /* mov r0.x, v0.z               */
11883
11884     static const DWORD vs_footer[] =
11885     {
11886         0x03000005, 0x80020000, 0x80000000, 0xa0ff0000,                         /* mul r0.y, r0.x, c0.w         */
11887         0x0300000d, 0x80040000, 0x80000000, 0x80550000,                         /* sge r0.z, r0.x, r0.y         */
11888         0x0300000d, 0x80020000, 0x80e40000, 0x80000000,                         /* sge r0.y, r0, r0.x           */
11889         0x03000005, 0x80040000, 0x80550000, 0x80e40000,                         /* mul r0.z, r0.y, r0           */
11890         0x0300000b, 0x80080000, 0x81aa0000, 0x80aa0000,                         /* max r0.w, -r0.z, r0.z        */
11891         0x0300000c, 0x80020000, 0x80000000, 0x80000000,                         /* slt r0.y, r0.x, r0.x         */
11892         0x03000002, 0x80040000, 0x80550000, 0x80550000,                         /* add r0.z, r0.y, r0.y         */
11893         0x0300000c, 0x80020000, 0xa0000000, 0x80ff0000,                         /* slt r0.y, c0.x, r0.w         */
11894         0x0300000b, 0x80080000, 0x81aa0000, 0x80aa0000,                         /* max r0.w, -r0.z, r0.z        */
11895         0x03000002, 0x80040000, 0x81550000, 0xa0e40000,                         /* add r0.z, -r0.y, c0          */
11896         0x0300000c, 0x80080000, 0xa0000000, 0x80e40000,                         /* slt r0.w, c0.x, r0           */
11897         0x03000005, 0x80040000, 0x80ff0000, 0x80e40000,                         /* mul r0.z, r0.w, r0           */
11898         0x04000004, 0x80020000, 0x80aa0000, 0xa0e40000, 0x80e40000,             /* mad r0.y, r0.z, c0, r0       */
11899         0x02000001, 0xe0030000, 0x80e40000,                                     /* mov oT0.xy, r0               */
11900         0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
11901         0x0000ffff,                                                             /* end                          */
11902     };
11903
11904     static const struct
11905     {
11906         const char *name;
11907         const DWORD *ops;
11908         DWORD size;
11909         D3DCOLOR r600;
11910         D3DCOLOR nv40;
11911         D3DCOLOR nv50;
11912     }
11913     vs_body[] =
11914     {
11915         /* The basic ideas here are:
11916          *     2.0 * +/-INF == +/-INF
11917          *     NAN != NAN
11918          *
11919          * The vertex shader value is written to the red component, with 0.0
11920          * and +/-INF mapping to 0xff, and NAN to 0x7f. Anything else should
11921          * result in 0x00. The pixel shader value is written to the green
11922          * component, but here 0.0 also results in 0x00. The actual value is
11923          * written to the blue component.
11924          *
11925          * There are considerable differences between graphics cards in how
11926          * these are handled, but pow and nrm never generate INF or NAN. */
11927         {"log",     vs_log,     sizeof(vs_log),     0x00000000, 0x00ff0000, 0x00ff7f00},
11928         {"pow",     vs_pow,     sizeof(vs_pow),     0x000000ff, 0x0000ff00, 0x000000ff},
11929         {"nrm",     vs_nrm,     sizeof(vs_nrm),     0x00ff0000, 0x0000ff00, 0x00ff0000},
11930         {"rcp1",    vs_rcp1,    sizeof(vs_rcp1),    0x000000ff, 0x00ff00ff, 0x00ff7f00},
11931         {"rcp2",    vs_rcp2,    sizeof(vs_rcp2),    0x00000000, 0x00ff0000, 0x00ff7f00},
11932         {"rsq1",    vs_rsq1,    sizeof(vs_rsq1),    0x000000ff, 0x00ff00ff, 0x00ff7f00},
11933         {"rsq2",    vs_rsq2,    sizeof(vs_rsq2),    0x000000ff, 0x00ff00ff, 0x00ff7f00},
11934         {"lit",     vs_lit,     sizeof(vs_lit),     0x00ff0000, 0x00ff0000, 0x00ff0000},
11935     };
11936
11937     static const DWORD ps_code[] =
11938     {
11939         0xffff0200,                                                             /* ps_2_0                       */
11940         0x05000051, 0xa00f0000, 0x00000000, 0x3f000000, 0x3f800000, 0x40000000, /* def c0, 0.0, 0.5, 1.0, 2.0   */
11941         0x0200001f, 0x80000000, 0xb0030000,                                     /* dcl t0.xy                    */
11942         0x0300000b, 0x80010001, 0xb0e40000, 0xa0e40000,                         /* max r1.x, t0, c0             */
11943         0x0300000a, 0x80010000, 0xb0e40000, 0xa0e40000,                         /* min r0.x, t0, c0             */
11944         0x03000002, 0x80010000, 0x80e40000, 0x81e40001,                         /* add r0.x, r0, -r1            */
11945         0x04000004, 0x80010001, 0xb0e40000, 0xa0ff0000, 0xb1e40000,             /* mad r1.x, t0, c0.w. -t0      */
11946         0x02000023, 0x80010002, 0x80e40001,                                     /* abs r2.x, r1                 */
11947         0x02000023, 0x80010000, 0x80e40000,                                     /* abs r0.x, r0                 */
11948         0x02000023, 0x80010001, 0xb0e40000,                                     /* abs r1.x, t0                 */
11949         0x04000058, 0x80010002, 0x81e40002, 0xa0aa0000, 0xa0e40000,             /* cmp r2.x, -r2, c0.z, c0      */
11950         0x02000023, 0x80010002, 0x80e40002,                                     /* abs r2.x, r2                 */
11951         0x04000058, 0x80010001, 0x81e40001, 0xa0aa0000, 0xa0e40000,             /* cmp r1.x, -r1, c0.z, c0      */
11952         0x02000023, 0x80010001, 0x80e40001,                                     /* abs r1.x, r1                 */
11953         0x04000058, 0x80010003, 0x81e40002, 0xa0aa0000, 0xa0e40000,             /* cmp r3.x, -r2, c0.z, c0      */
11954         0x04000058, 0x80010002, 0x81e40001, 0xa0aa0000, 0xa0e40000,             /* cmp r2.x, -r1, c0.z, c0      */
11955         0x04000058, 0x80010000, 0x81e40000, 0xa0550000, 0xa0e40000,             /* cmp r0.x, -r0, c0.y, c0      */
11956         0x03000005, 0x80010002, 0x80e40002, 0x80e40003,                         /* mul r2.x, r2, r3             */
11957         0x04000058, 0x80010000, 0x81e40002, 0xa0aa0000, 0x80e40000,             /* cmp r0.x, -r2, c0.z, r0      */
11958         0x04000058, 0x80020000, 0x81000001, 0x80000000, 0xa0000000,             /* cmp r0.y, -r1.x, r0.x, c0.x  */
11959         0x02000001, 0x80050000, 0xb0c90000,                                     /* mov r0.xz, t0.yzxw           */
11960         0x02000001, 0x80080000, 0xa0aa0000,                                     /* mov r0.w, c0.z               */
11961         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
11962         0x0000ffff,                                                             /* end                          */
11963     };
11964
11965     struct
11966     {
11967         float x, y, z;
11968         float s;
11969     }
11970     quad[] =
11971     {
11972         { -1.0f,  1.0f, 0.0f, 0.0f},
11973         {  1.0f,  1.0f, 1.0f, 0.0f},
11974         { -1.0f, -1.0f, 0.0f, 0.0f},
11975         {  1.0f, -1.0f, 1.0f, 0.0f},
11976     };
11977
11978     IDirect3DPixelShader9 *ps;
11979     UINT body_size = 0;
11980     DWORD *vs_code;
11981     D3DCAPS9 caps;
11982     HRESULT hr;
11983     UINT i;
11984
11985     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
11986     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
11987     if (caps.PixelShaderVersion < D3DPS_VERSION(2, 0) || caps.VertexShaderVersion < D3DVS_VERSION(2, 0))
11988     {
11989         skip("No shader model 2.0 support, skipping floating point specials test.\n");
11990         return;
11991     }
11992
11993     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE1(0));
11994     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
11995
11996     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code, &ps);
11997     ok(SUCCEEDED(hr), "CreatePixelShader failed, hr %#x.\n", hr);
11998     IDirect3DDevice9_SetPixelShader(device, ps);
11999     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
12000
12001     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
12002     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
12003
12004     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0f, 0);
12005     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
12006
12007     for (i = 0; i < sizeof(vs_body) / sizeof(*vs_body); ++i)
12008     {
12009         if (vs_body[i].size > body_size) body_size = vs_body[i].size;
12010     }
12011
12012     vs_code = HeapAlloc(GetProcessHeap(), 0, sizeof(vs_header) + body_size + sizeof(vs_footer));
12013     memcpy(vs_code, vs_header, sizeof(vs_header));
12014
12015     for (i = 0; i < sizeof(vs_body) / sizeof(*vs_body); ++i)
12016     {
12017         DWORD offset = sizeof(vs_header) / sizeof(*vs_header);
12018         IDirect3DVertexShader9 *vs;
12019         D3DCOLOR color;
12020
12021         memcpy(vs_code + offset, vs_body[i].ops, vs_body[i].size);
12022         offset += vs_body[i].size / sizeof(*vs_body[i].ops);
12023         memcpy(vs_code + offset, vs_footer, sizeof(vs_footer));
12024
12025         hr = IDirect3DDevice9_CreateVertexShader(device, vs_code, &vs);
12026         ok(SUCCEEDED(hr), "CreateVertexShader failed, hr %#x.\n", hr);
12027         IDirect3DDevice9_SetVertexShader(device, vs);
12028         ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
12029
12030         hr = IDirect3DDevice9_BeginScene(device);
12031         ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
12032         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
12033         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
12034         hr = IDirect3DDevice9_EndScene(device);
12035         ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
12036
12037         color = getPixelColor(device, 320, 240);
12038         ok(color_match(color, vs_body[i].r600, 1)
12039                 || color_match(color, vs_body[i].nv40, 1)
12040                 || color_match(color, vs_body[i].nv50, 1),
12041                 "Expected color 0x%08x, 0x%08x or 0x%08x for instruction \"%s\", got 0x%08x.\n",
12042                 vs_body[i].r600, vs_body[i].nv40, vs_body[i].nv50, vs_body[i].name, color);
12043
12044         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
12045         ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
12046
12047         hr = IDirect3DDevice9_SetVertexShader(device, NULL);
12048         ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
12049         IDirect3DVertexShader9_Release(vs);
12050     }
12051
12052     HeapFree(GetProcessHeap(), 0, vs_code);
12053
12054     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
12055     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
12056     IDirect3DPixelShader9_Release(ps);
12057 }
12058
12059 static void srgbwrite_format_test(IDirect3DDevice9 *device)
12060 {
12061     IDirect3D9 *d3d;
12062     IDirect3DSurface9 *rt, *backbuffer;
12063     IDirect3DTexture9 *texture;
12064     HRESULT hr;
12065     int i;
12066     DWORD color_rgb = 0x00808080, color_srgb = 0x00bcbcbc, color;
12067     static const struct
12068     {
12069         D3DFORMAT fmt;
12070         const char *name;
12071     }
12072     formats[] =
12073     {
12074         { D3DFMT_R5G6B5, "D3DFMT_R5G6B5" },
12075         { D3DFMT_X8R8G8B8, "D3DFMT_X8R8G8B8" },
12076         { D3DFMT_A8R8G8B8, "D3DFMT_A8R8G8B8" },
12077         { D3DFMT_A16B16G16R16F, "D3DFMT_A16B16G16R16F" },
12078         { D3DFMT_A32B32G32R32F, "D3DFMT_A32B32G32R32F" },
12079     };
12080     static const struct
12081     {
12082         float x, y, z;
12083         float u, v;
12084     }
12085     quad[] =
12086     {
12087         {-1.0f,  -1.0f,  0.1f,   0.0f,   0.0f},
12088         {-1.0f,   1.0f,  0.1f,   1.0f,   0.0f},
12089         { 1.0f,  -1.0f,  0.1f,   0.0f,   1.0f},
12090         { 1.0f,   1.0f,  0.1f,   1.0f,   1.0f}
12091     };
12092
12093     hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
12094     ok(SUCCEEDED(hr), "GetDirect3D failed, hr %#x.\n", hr);
12095     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
12096     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
12097     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
12098     ok(SUCCEEDED(hr), "GetBackBuffer failed, hr %#x.\n", hr);
12099     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
12100     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
12101     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0x80808080);
12102     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
12103
12104     for(i = 0; i < (sizeof(formats) / sizeof(*formats)); i++)
12105     {
12106         if (FAILED(IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
12107                 D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, formats[i].fmt)))
12108         {
12109             skip("Format %s not supported as render target, skipping test.\n",
12110                     formats[i].name);
12111             continue;
12112         }
12113
12114         hr = IDirect3DDevice9_CreateTexture(device, 8, 8, 1, D3DUSAGE_RENDERTARGET, formats[i].fmt,
12115                                             D3DPOOL_DEFAULT, &texture, NULL);
12116         ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
12117         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ff0000, 0.0f, 0);
12118         ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
12119
12120         hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &rt);
12121         ok(SUCCEEDED(hr), "GetSurfaceLevel failed, hr %#x.\n", hr);
12122         hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
12123         ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
12124         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0);
12125         ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
12126
12127         hr = IDirect3DDevice9_BeginScene(device);
12128         ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
12129         if(SUCCEEDED(hr))
12130         {
12131             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, TRUE);
12132             ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
12133             hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
12134             ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
12135             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
12136             ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
12137
12138             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, FALSE);
12139             ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
12140             hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
12141             ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
12142             hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
12143             ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
12144             hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
12145             ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
12146             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
12147             ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
12148             hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
12149             ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
12150
12151             hr = IDirect3DDevice9_EndScene(device);
12152             ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
12153         }
12154
12155         IDirect3DSurface9_Release(rt);
12156         IDirect3DTexture9_Release(texture);
12157
12158         color = getPixelColor(device, 360, 240);
12159         if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
12160                                     D3DUSAGE_QUERY_SRGBWRITE,
12161                                     D3DRTYPE_TEXTURE, formats[i].fmt) == D3D_OK)
12162         {
12163             /* Big slop for R5G6B5 */
12164             ok(color_match(color, color_srgb, 5), "Format %s supports srgb, expected color 0x%08x, got 0x%08x\n",
12165                 formats[i].name, color_srgb, color);
12166         }
12167         else
12168         {
12169             /* Big slop for R5G6B5 */
12170             ok(color_match(color, color_rgb, 5), "Format %s does not support srgb, expected color 0x%08x, got 0x%08x\n",
12171                 formats[i].name, color_rgb, color);
12172         }
12173
12174         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
12175         ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
12176     }
12177
12178     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
12179     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
12180
12181     IDirect3D9_Release(d3d);
12182     IDirect3DSurface9_Release(backbuffer);
12183 }
12184
12185 static void ds_size_test(IDirect3DDevice9 *device)
12186 {
12187     IDirect3DSurface9 *ds, *rt, *old_rt, *old_ds, *readback;
12188     HRESULT hr;
12189     DWORD num_passes;
12190     struct
12191     {
12192         float x, y, z;
12193     }
12194     quad[] =
12195     {
12196         {-1.0,  -1.0,   0.0 },
12197         {-1.0,   1.0,   0.0 },
12198         { 1.0,  -1.0,   0.0 },
12199         { 1.0,   1.0,   0.0 }
12200     };
12201
12202     hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &rt, NULL);
12203     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateRenderTarget failed, hr %#x.\n", hr);
12204     hr = IDirect3DDevice9_CreateDepthStencilSurface(device, 32, 32, D3DFMT_D24X8, D3DMULTISAMPLE_NONE, 0, TRUE, &ds, NULL);
12205     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateDepthStencilSurface failed, hr %#x.\n", hr);
12206     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &readback, NULL);
12207     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateOffscreenPlainSurface failed, hr %#x.\n", hr);
12208
12209     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
12210     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
12211     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
12212     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
12213     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
12214     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
12215     hr = IDirect3DDevice9_ValidateDevice(device, &num_passes);
12216     ok(SUCCEEDED(hr), "IDirect3DDevice9_ValidateDevice failed, hr %#x.\n", hr);
12217     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &old_rt);
12218     ok(SUCCEEDED(hr), "IDirect3DDevice9_GetRenderTarget failed, hr %#x.\n", hr);
12219     hr = IDirect3DDevice9_GetDepthStencilSurface(device, &old_ds);
12220     ok(SUCCEEDED(hr), "IDirect3DDevice9_GetDepthStencilSurface failed, hr %#x.\n", hr);
12221     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
12222     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderTarget failed, hr %#x.\n", hr);
12223     hr = IDirect3DDevice9_SetDepthStencilSurface(device, ds);
12224     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetDepthStencilSurface failed, hr %#x.\n", hr);
12225     hr = IDirect3DDevice9_ValidateDevice(device, &num_passes);
12226     ok(SUCCEEDED(hr), "IDirect3DDevice9_ValidateDevice failed, hr %#x.\n", hr);
12227
12228     /* The D3DCLEAR_TARGET clear works. D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER returns OK,
12229      * but does not change the surface's contents. */
12230     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000FF, 0.0f, 0);
12231     ok(SUCCEEDED(hr), "Target clear failed, hr %#x.\n", hr);
12232     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 0.2f, 0);
12233     ok(SUCCEEDED(hr), "Z Buffer clear failed, hr %#x.\n", hr);
12234     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00ff0000, 0.5f, 0);
12235     ok(SUCCEEDED(hr), "Target and Z Buffer clear failed, hr %#x.\n", hr);
12236
12237     /* Nvidia does not clear the surface(The color is still 0x000000ff), AMD does(the color is 0x00ff0000) */
12238
12239     /* Turning on any depth-related state results in a ValidateDevice failure */
12240     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
12241     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
12242     hr = IDirect3DDevice9_ValidateDevice(device, &num_passes);
12243     ok(hr == D3DERR_CONFLICTINGRENDERSTATE || hr == D3D_OK, "IDirect3DDevice9_ValidateDevice returned %#x, expected "
12244         "D3DERR_CONFLICTINGRENDERSTATE.\n", hr);
12245     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
12246     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
12247     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
12248     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderState failed, hr %#x.\n", hr);
12249     hr = IDirect3DDevice9_ValidateDevice(device, &num_passes);
12250     ok(hr == D3DERR_CONFLICTINGRENDERSTATE || hr == D3D_OK, "IDirect3DDevice9_ValidateDevice returned %#x, expected "
12251         "D3DERR_CONFLICTINGRENDERSTATE.\n", hr);
12252
12253     /* Try to draw with the device in an invalid state */
12254     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
12255     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetFVF failed, hr %#x.\n", hr);
12256     hr = IDirect3DDevice9_BeginScene(device);
12257     ok(SUCCEEDED(hr), "IDirect3DDevice9_BeginScene failed, hr %#x.\n", hr);
12258     if(SUCCEEDED(hr))
12259     {
12260         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
12261         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitiveUP failed, hr %#x.\n", hr);
12262         hr = IDirect3DDevice9_EndScene(device);
12263         ok(SUCCEEDED(hr), "IDirect3DDevice9_EndScene failed, hr %#x.\n", hr);
12264
12265         /* Don't check the resulting draw unless we find an app that needs it. On nvidia ValidateDevice
12266          * returns CONFLICTINGRENDERSTATE, so the result is undefined. On AMD d3d seems to assume the
12267          * stored Z buffer value is 0.0 for all pixels, even those that are covered by the depth buffer */
12268     }
12269
12270     hr = IDirect3DDevice9_SetRenderTarget(device, 0, old_rt);
12271     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderTarget failed, hr %#x.\n", hr);
12272     hr = IDirect3DDevice9_SetDepthStencilSurface(device, old_ds);
12273     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetDepthStencilSurface failed, hr %#x.\n", hr);
12274     hr = IDirect3DDevice9_ValidateDevice(device, &num_passes);
12275     ok(SUCCEEDED(hr), "IDirect3DDevice9_ValidateDevice failed, hr %#x.\n", hr);
12276
12277     IDirect3DSurface9_Release(readback);
12278     IDirect3DSurface9_Release(ds);
12279     IDirect3DSurface9_Release(rt);
12280     IDirect3DSurface9_Release(old_rt);
12281     IDirect3DSurface9_Release(old_ds);
12282 }
12283
12284 static void unbound_sampler_test(IDirect3DDevice9 *device)
12285 {
12286     HRESULT hr;
12287     IDirect3DPixelShader9 *ps, *ps_cube, *ps_volume;
12288     IDirect3DSurface9 *rt, *old_rt;
12289     DWORD color;
12290
12291     static const DWORD ps_code[] =
12292     {
12293         0xffff0200,                                     /* ps_2_0           */
12294         0x0200001f, 0x90000000, 0xa00f0800,             /* dcl_2d s0        */
12295         0x0200001f, 0x80000000, 0xb00f0000,             /* dcl t0           */
12296         0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, /* texld r0, t0, s0 */
12297         0x02000001, 0x800f0800, 0x80e40000,             /* mov oC0, r0      */
12298         0x0000ffff,                                     /* end              */
12299     };
12300     static const DWORD ps_code_cube[] =
12301     {
12302         0xffff0200,                                     /* ps_2_0           */
12303         0x0200001f, 0x98000000, 0xa00f0800,             /* dcl_cube s0      */
12304         0x0200001f, 0x80000000, 0xb00f0000,             /* dcl t0           */
12305         0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, /* texld r0, t0, s0 */
12306         0x02000001, 0x800f0800, 0x80e40000,             /* mov oC0, r0      */
12307         0x0000ffff,                                     /* end              */
12308     };
12309     static const DWORD ps_code_volume[] =
12310     {
12311         0xffff0200,                                     /* ps_2_0           */
12312         0x0200001f, 0xa0000000, 0xa00f0800,             /* dcl_volume s0    */
12313         0x0200001f, 0x80000000, 0xb00f0000,             /* dcl t0           */
12314         0x03000042, 0x800f0000, 0xb0e40000, 0xa0e40800, /* texld r0, t0, s0 */
12315         0x02000001, 0x800f0800, 0x80e40000,             /* mov oC0, r0      */
12316         0x0000ffff,                                     /* end              */
12317     };
12318
12319     static const struct
12320     {
12321         float x, y, z;
12322         float u, v;
12323     }
12324     quad[] =
12325     {
12326         {-1.0f,  -1.0f,  0.1f,   0.0f,   0.0f},
12327         {-1.0f,   1.0f,  0.1f,   1.0f,   0.0f},
12328         { 1.0f,  -1.0f,  0.1f,   0.0f,   1.0f},
12329         { 1.0f,   1.0f,  0.1f,   1.0f,   1.0f}
12330     };
12331
12332     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
12333     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStage failed, %#x.\n", hr);
12334
12335     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code, &ps);
12336     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreatePixelShader failed, hr %#x.\n", hr);
12337     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code_cube, &ps_cube);
12338     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreatePixelShader failed, hr %#x.\n", hr);
12339     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code_volume, &ps_volume);
12340     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreatePixelShader failed, hr %#x.\n", hr);
12341
12342     hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &rt, NULL);
12343     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateRenderTarget failed, hr %#x.\n", hr);
12344
12345     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &old_rt);
12346     ok(SUCCEEDED(hr), "IDirect3DDevice9_GetRenderTarget failed, hr %#x.\n", hr);
12347
12348     hr = IDirect3DDevice9_SetRenderTarget(device, 0, rt);
12349     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderTarget failed, hr %#x.\n", hr);
12350
12351     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1 );
12352     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetFVF failed, hr %#x.\n", hr);
12353
12354     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x56ffffff, 0, 0);
12355     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed, hr %#x.\n", hr);
12356
12357     hr = IDirect3DDevice9_SetPixelShader(device, ps);
12358     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetPixelShader failed, hr %#x.\n", hr);
12359
12360     hr = IDirect3DDevice9_BeginScene(device);
12361     ok(SUCCEEDED(hr), "IDirect3DDevice9_BeginScene failed, hr %#x.\n", hr);
12362     if(SUCCEEDED(hr))
12363     {
12364         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
12365         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitiveUP failed, hr %#x.\n", hr);
12366
12367         hr = IDirect3DDevice9_EndScene(device);
12368         ok(SUCCEEDED(hr), "IDirect3DDevice9_EndScene failed, hr %#x.\n", hr);
12369     }
12370
12371     color = getPixelColorFromSurface(rt, 32, 32);
12372     ok(color == 0xff000000, "Unbound sampler color is %#x.\n", color);
12373
12374     /* Now try with a cube texture */
12375     hr = IDirect3DDevice9_SetPixelShader(device, ps_cube);
12376     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetPixelShader failed, hr %#x.\n", hr);
12377
12378     hr = IDirect3DDevice9_BeginScene(device);
12379     ok(SUCCEEDED(hr), "IDirect3DDevice9_BeginScene failed, hr %#x.\n", hr);
12380     if (SUCCEEDED(hr))
12381     {
12382         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
12383         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitiveUP failed, hr %#x.\n", hr);
12384
12385         hr = IDirect3DDevice9_EndScene(device);
12386         ok(SUCCEEDED(hr), "IDirect3DDevice9_EndScene failed, hr %#x.\n", hr);
12387     }
12388
12389     color = getPixelColorFromSurface(rt, 32, 32);
12390     ok(color == 0xff000000, "Unbound sampler color is %#x.\n", color);
12391
12392     /* And then with a volume texture */
12393     hr = IDirect3DDevice9_SetPixelShader(device, ps_volume);
12394     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetPixelShader failed, hr %#x.\n", hr);
12395
12396     hr = IDirect3DDevice9_BeginScene(device);
12397     ok(SUCCEEDED(hr), "IDirect3DDevice9_BeginScene failed, hr %#x.\n", hr);
12398     if (SUCCEEDED(hr))
12399     {
12400         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
12401         ok(SUCCEEDED(hr), "IDirect3DDevice9_DrawPrimitiveUP failed, hr %#x.\n", hr);
12402
12403         hr = IDirect3DDevice9_EndScene(device);
12404         ok(SUCCEEDED(hr), "IDirect3DDevice9_EndScene failed, hr %#x.\n", hr);
12405     }
12406
12407     color = getPixelColorFromSurface(rt, 32, 32);
12408     ok(color == 0xff000000, "Unbound sampler color is %#x.\n", color);
12409
12410     hr = IDirect3DDevice9_SetRenderTarget(device, 0, old_rt);
12411     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetRenderTarget failed, hr %#x.\n", hr);
12412
12413     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
12414     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetPixelShader failed, hr %#x.\n", hr);
12415
12416     IDirect3DSurface9_Release(rt);
12417     IDirect3DSurface9_Release(old_rt);
12418     IDirect3DPixelShader9_Release(ps);
12419     IDirect3DPixelShader9_Release(ps_cube);
12420     IDirect3DPixelShader9_Release(ps_volume);
12421 }
12422
12423 static void update_surface_test(IDirect3DDevice9 *device)
12424 {
12425     static const BYTE blocks[][8] =
12426     {
12427         {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00}, /* White */
12428         {0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00}, /* Red */
12429         {0xe0, 0xff, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00}, /* Yellow */
12430         {0xe0, 0x07, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00}, /* Green */
12431         {0xff, 0x07, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00}, /* Cyan */
12432         {0x1f, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00}, /* Blue */
12433         {0x1f, 0xf8, 0x1f, 0xf8, 0x00, 0x00, 0x00, 0x00}, /* Magenta */
12434     };
12435     static const struct
12436     {
12437         UINT x, y;
12438         D3DCOLOR color;
12439     }
12440     expected_colors[] =
12441     {
12442         { 18, 240, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0xff)},
12443         { 57, 240, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xff)},
12444         {109, 240, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0xff)},
12445         {184, 240, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
12446         {290, 240, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00)},
12447         {440, 240, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00)},
12448         {584, 240, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0xff)},
12449     };
12450     static const struct
12451     {
12452         float x, y, z, w;
12453         float u, v;
12454     }
12455     tri[] =
12456     {
12457         {  0.0f, 480.0f, 0.0f,  1.0f,   0.0f, 0.0f},
12458         {  0.0f,   0.0f, 0.0f,  1.0f,   0.0f, 1.0f},
12459         {640.0f, 240.0f, 0.0f, 10.0f, 100.0f, 0.5f},
12460     };
12461     static const RECT rect_2x2 = {0, 0, 2, 2};
12462     static const struct
12463     {
12464         UINT src_level;
12465         UINT dst_level;
12466         const RECT *r;
12467         HRESULT hr;
12468     }
12469     block_size_tests[] =
12470     {
12471         {1, 0, NULL,      D3D_OK},
12472         {0, 1, NULL,      D3DERR_INVALIDCALL},
12473         {5, 4, NULL,      D3DERR_INVALIDCALL},
12474         {4, 5, NULL,      D3DERR_INVALIDCALL},
12475         {4, 5, &rect_2x2, D3DERR_INVALIDCALL},
12476         {5, 5, &rect_2x2, D3D_OK},
12477     };
12478
12479     IDirect3DSurface9 *src_surface, *dst_surface;
12480     IDirect3DTexture9 *src_tex, *dst_tex;
12481     IDirect3D9 *d3d;
12482     UINT count, i;
12483     HRESULT hr;
12484
12485     hr = IDirect3DDevice9_GetDirect3D(device, &d3d);
12486     ok(SUCCEEDED(hr), "GetDirect3D failed, hr %#x.\n", hr);
12487
12488     hr = IDirect3D9_CheckDeviceFormat(d3d, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
12489             D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1);
12490     IDirect3D9_Release(d3d);
12491     if (FAILED(hr))
12492     {
12493         skip("DXT1 not supported, skipping test.\n");
12494         return;
12495     }
12496
12497     IDirect3D9_Release(d3d);
12498
12499     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0, D3DFMT_DXT1, D3DPOOL_SYSTEMMEM, &src_tex, NULL);
12500     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
12501     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 0, 0, D3DFMT_DXT1, D3DPOOL_DEFAULT, &dst_tex, NULL);
12502     ok(SUCCEEDED(hr), "Failed to create texture, hr %#x.\n", hr);
12503
12504     count = IDirect3DTexture9_GetLevelCount(src_tex);
12505     ok(count == 7, "Got level count %u, expected 7.\n", count);
12506
12507     for (i = 0; i < count; ++i)
12508     {
12509         UINT row_count, block_count, x, y;
12510         D3DSURFACE_DESC desc;
12511         BYTE *row, *block;
12512         D3DLOCKED_RECT r;
12513
12514         hr = IDirect3DTexture9_GetLevelDesc(src_tex, i, &desc);
12515         ok(SUCCEEDED(hr), "Failed to get level desc, hr %#x.\n", hr);
12516
12517         hr = IDirect3DTexture9_LockRect(src_tex, i, &r, NULL, 0);
12518         ok(SUCCEEDED(hr), "Failed to lock texture, hr %#x.\n", hr);
12519
12520         row_count = ((desc.Height + 3) & ~3) / 4;
12521         block_count = ((desc.Width + 3) & ~3) / 4;
12522         row = r.pBits;
12523
12524         for (y = 0; y < row_count; ++y)
12525         {
12526             block = row;
12527             for (x = 0; x < block_count; ++x)
12528             {
12529                 memcpy(block, blocks[i], sizeof(blocks[i]));
12530                 block += sizeof(blocks[i]);
12531             }
12532             row += r.Pitch;
12533         }
12534
12535         hr = IDirect3DTexture9_UnlockRect(src_tex, i);
12536         ok(SUCCEEDED(hr), "Failed to unlock texture, hr %#x.\n", hr);
12537     }
12538
12539     for (i = 0; i < sizeof(block_size_tests) / sizeof(*block_size_tests); ++i)
12540     {
12541         hr = IDirect3DTexture9_GetSurfaceLevel(src_tex, block_size_tests[i].src_level, &src_surface);
12542         ok(SUCCEEDED(hr), "Failed to get texture surface, hr %#x.\n", hr);
12543         hr = IDirect3DTexture9_GetSurfaceLevel(dst_tex, block_size_tests[i].dst_level, &dst_surface);
12544         ok(SUCCEEDED(hr), "Failed to get texture surface, hr %#x.\n", hr);
12545
12546         hr = IDirect3DDevice9_UpdateSurface(device, src_surface, block_size_tests[i].r, dst_surface, NULL);
12547         ok(hr == block_size_tests[i].hr, "Update surface returned %#x for test %u, expected %#x.\n",
12548                 hr, i, block_size_tests[i].hr);
12549
12550         IDirect3DSurface9_Release(dst_surface);
12551         IDirect3DSurface9_Release(src_surface);
12552     }
12553
12554     for (i = 0; i < count; ++i)
12555     {
12556         hr = IDirect3DTexture9_GetSurfaceLevel(src_tex, i, &src_surface);
12557         ok(SUCCEEDED(hr), "Failed to get texture surface, hr %#x.\n", hr);
12558         hr = IDirect3DTexture9_GetSurfaceLevel(dst_tex, i, &dst_surface);
12559         ok(SUCCEEDED(hr), "Failed to get texture surface, hr %#x.\n", hr);
12560
12561         hr = IDirect3DDevice9_UpdateSurface(device, src_surface, NULL, dst_surface, NULL);
12562         ok(SUCCEEDED(hr), "Failed to update surface at level %u, hr %#x.\n", i, hr);
12563
12564         IDirect3DSurface9_Release(dst_surface);
12565         IDirect3DSurface9_Release(src_surface);
12566     }
12567
12568     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
12569     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
12570     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
12571     ok(SUCCEEDED(hr), "SetSamplerState failed, hr %#x.\n", hr);
12572     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_TEX1);
12573     ok(SUCCEEDED(hr), "SetFVF failed, hr %#x.\n", hr);
12574     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)dst_tex);
12575     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
12576     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
12577     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
12578     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
12579     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
12580
12581     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0f, 0);
12582     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
12583
12584     hr = IDirect3DDevice9_BeginScene(device);
12585     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
12586     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 1, tri, sizeof(*tri));
12587     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
12588     hr = IDirect3DDevice9_EndScene(device);
12589     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
12590
12591     for (i = 0; i < sizeof(expected_colors) / sizeof(*expected_colors); ++i)
12592     {
12593         D3DCOLOR color = getPixelColor(device, expected_colors[i].x, expected_colors[i].y);
12594         ok(color_match(color, expected_colors[i].color, 0),
12595                 "Expected color 0x%08x at (%u, %u), got 0x%08x.\n",
12596                 expected_colors[i].color, expected_colors[i].x, expected_colors[i].y, color);
12597     }
12598
12599     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
12600     ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
12601
12602     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
12603     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
12604     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
12605     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
12606     IDirect3DTexture9_Release(dst_tex);
12607     IDirect3DTexture9_Release(src_tex);
12608 }
12609
12610 START_TEST(visual)
12611 {
12612     IDirect3DDevice9 *device_ptr;
12613     D3DCAPS9 caps;
12614     HRESULT hr;
12615     DWORD color;
12616
12617     d3d9_handle = LoadLibraryA("d3d9.dll");
12618     if (!d3d9_handle)
12619     {
12620         skip("Could not load d3d9.dll\n");
12621         return;
12622     }
12623
12624     device_ptr = init_d3d9();
12625     if (!device_ptr)
12626     {
12627         skip("Creating the device failed\n");
12628         return;
12629     }
12630
12631     IDirect3DDevice9_GetDeviceCaps(device_ptr, &caps);
12632
12633     /* Check for the reliability of the returned data */
12634     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
12635     if(FAILED(hr))
12636     {
12637         skip("Clear failed, can't assure correctness of the test results, skipping\n");
12638         goto cleanup;
12639     }
12640
12641     color = getPixelColor(device_ptr, 1, 1);
12642     if(color !=0x00ff0000)
12643     {
12644         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
12645         goto cleanup;
12646     }
12647     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
12648
12649     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xff00ddee, 0.0, 0);
12650     if(FAILED(hr))
12651     {
12652         skip("Clear failed, can't assure correctness of the test results, skipping\n");
12653         goto cleanup;
12654     }
12655
12656     color = getPixelColor(device_ptr, 639, 479);
12657     if(color != 0x0000ddee)
12658     {
12659         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
12660         goto cleanup;
12661     }
12662     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
12663
12664     /* Now execute the real tests */
12665     depth_clamp_test(device_ptr);
12666     stretchrect_test(device_ptr);
12667     lighting_test(device_ptr);
12668     clear_test(device_ptr);
12669     color_fill_test(device_ptr);
12670     fog_test(device_ptr);
12671     if(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
12672     {
12673         test_cube_wrap(device_ptr);
12674     } else {
12675         skip("No cube texture support\n");
12676     }
12677     z_range_test(device_ptr);
12678     if(caps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)
12679     {
12680         maxmip_test(device_ptr);
12681     }
12682     else
12683     {
12684         skip("No mipmap support\n");
12685     }
12686     offscreen_test(device_ptr);
12687     ds_size_test(device_ptr);
12688     alpha_test(device_ptr);
12689     shademode_test(device_ptr);
12690     srgbtexture_test(device_ptr);
12691     release_buffer_test(device_ptr);
12692     float_texture_test(device_ptr);
12693     g16r16_texture_test(device_ptr);
12694     pixelshader_blending_test(device_ptr);
12695     texture_transform_flags_test(device_ptr);
12696     autogen_mipmap_test(device_ptr);
12697     fixed_function_decl_test(device_ptr);
12698     conditional_np2_repeat_test(device_ptr);
12699     fixed_function_bumpmap_test(device_ptr);
12700     if(caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) {
12701         stencil_cull_test(device_ptr);
12702     } else {
12703         skip("No two sided stencil support\n");
12704     }
12705     pointsize_test(device_ptr);
12706     tssargtemp_test(device_ptr);
12707     np2_stretch_rect_test(device_ptr);
12708     yuv_color_test(device_ptr);
12709     zwriteenable_test(device_ptr);
12710     alphatest_test(device_ptr);
12711     viewport_test(device_ptr);
12712
12713     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1))
12714     {
12715         test_constant_clamp_vs(device_ptr);
12716         test_compare_instructions(device_ptr);
12717     }
12718     else skip("No vs_1_1 support\n");
12719
12720     if (caps.VertexShaderVersion >= D3DVS_VERSION(2, 0))
12721     {
12722         test_mova(device_ptr);
12723         loop_index_test(device_ptr);
12724         sincos_test(device_ptr);
12725         sgn_test(device_ptr);
12726         if (caps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) {
12727             test_vshader_input(device_ptr);
12728             test_vshader_float16(device_ptr);
12729             stream_test(device_ptr);
12730         } else {
12731             skip("No vs_3_0 support\n");
12732         }
12733     }
12734     else skip("No vs_2_0 support\n");
12735
12736     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1) && caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
12737     {
12738         fog_with_shader_test(device_ptr);
12739     }
12740     else skip("No vs_1_1 and ps_1_1 support\n");
12741
12742     if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
12743     {
12744         texbem_test(device_ptr);
12745         texdepth_test(device_ptr);
12746         texkill_test(device_ptr);
12747         x8l8v8u8_test(device_ptr);
12748         if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 4)) {
12749             constant_clamp_ps_test(device_ptr);
12750             cnd_test(device_ptr);
12751             if (caps.PixelShaderVersion >= D3DPS_VERSION(2, 0)) {
12752                 dp2add_ps_test(device_ptr);
12753                 unbound_sampler_test(device_ptr);
12754                 if (caps.PixelShaderVersion >= D3DPS_VERSION(3, 0) && caps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) {
12755                     nested_loop_test(device_ptr);
12756                     pretransformed_varying_test(device_ptr);
12757                     vFace_register_test(device_ptr);
12758                     vpos_register_test(device_ptr);
12759                     multiple_rendertargets_test(device_ptr);
12760                 } else {
12761                     skip("No ps_3_0 or vs_3_0 support\n");
12762                 }
12763             } else {
12764                 skip("No ps_2_0 support\n");
12765             }
12766         }
12767     }
12768     else skip("No ps_1_1 support\n");
12769
12770     texop_test(device_ptr);
12771     texop_range_test(device_ptr);
12772     alphareplicate_test(device_ptr);
12773     dp3_alpha_test(device_ptr);
12774     depth_buffer_test(device_ptr);
12775     depth_buffer2_test(device_ptr);
12776     depth_blit_test(device_ptr);
12777     intz_test(device_ptr);
12778     shadow_test(device_ptr);
12779     fp_special_test(device_ptr);
12780     depth_bounds_test(device_ptr);
12781     srgbwrite_format_test(device_ptr);
12782     clip_planes_test(device_ptr);
12783     update_surface_test(device_ptr);
12784
12785 cleanup:
12786     if(device_ptr) {
12787         D3DPRESENT_PARAMETERS present_parameters;
12788         IDirect3DSwapChain9 *swapchain;
12789         ULONG ref;
12790
12791         IDirect3DDevice9_GetSwapChain(device_ptr, 0, &swapchain);
12792         IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters);
12793         IDirect3DSwapChain9_Release(swapchain);
12794         ref = IDirect3DDevice9_Release(device_ptr);
12795         ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
12796         DestroyWindow(present_parameters.hDeviceWindow);
12797     }
12798 }