d3d9: Do not set NONE MIN and MAG filters.
[wine] / dlls / d3d9 / tests / visual.c
1 /*
2  * Copyright 2005, 2007 Henri Verbeet
3  * Copyright (C) 2007 Stefan Dösinger(for CodeWeavers)
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 /* This test framework allows limited testing of rendering results. Things are rendered, shown on
21  * the framebuffer, read back from there and compared to expected colors.
22  *
23  * However, neither d3d nor opengl is guaranteed to be pixel exact, and thus the capability of this test
24  * is rather limited. As a general guideline for adding tests, do not rely on corner pixels. Draw a big enough
25  * area which shows specific behavior(like a quad on the whole screen), and try to get resulting colors with
26  * all bits set or unset in all channels(like pure red, green, blue, white, black). Hopefully everything that
27  * causes visible results in games can be tested in a way that does not depend on pixel exactness
28  */
29
30 #define COBJMACROS
31 #include <d3d9.h>
32 #include <dxerr9.h>
33 #include "wine/test.h"
34
35 static HMODULE d3d9_handle = 0;
36
37 static HWND create_window(void)
38 {
39     WNDCLASS wc = {0};
40     HWND ret;
41     wc.lpfnWndProc = &DefWindowProc;
42     wc.lpszClassName = "d3d9_test_wc";
43     RegisterClass(&wc);
44
45     ret = CreateWindow("d3d9_test_wc", "d3d9_test",
46                         WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
47     return ret;
48 }
49
50 static DWORD getPixelColor(IDirect3DDevice9 *device, UINT x, UINT y)
51 {
52     DWORD ret;
53     IDirect3DSurface9 *surf;
54     HRESULT hr;
55     D3DLOCKED_RECT lockedRect;
56     RECT rectToLock = {x, y, x+1, y+1};
57
58     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 640, 480, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL);
59     if(FAILED(hr) || !surf )  /* This is not a test */
60     {
61         trace("Can't create an offscreen plain surface to read the render target data, hr=%s\n", DXGetErrorString9(hr));
62         return 0xdeadbeef;
63     }
64
65     hr = IDirect3DDevice9_GetFrontBufferData(device, 0, surf);
66     if(FAILED(hr))
67     {
68         trace("Can't read the front buffer data, hr=%s\n", DXGetErrorString9(hr));
69         ret = 0xdeadbeed;
70         goto out;
71     }
72
73     hr = IDirect3DSurface9_LockRect(surf, &lockedRect, &rectToLock, D3DLOCK_READONLY);
74     if(FAILED(hr))
75     {
76         trace("Can't lock the offscreen surface, hr=%s\n", DXGetErrorString9(hr));
77         ret = 0xdeadbeec;
78         goto out;
79     }
80
81     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
82      * really important for these tests
83      */
84     ret = ((DWORD *) lockedRect.pBits)[0] & 0x00ffffff;
85     hr = IDirect3DSurface9_UnlockRect(surf);
86     if(FAILED(hr))
87     {
88         trace("Can't unlock the offscreen surface, hr=%s\n", DXGetErrorString9(hr));
89     }
90
91 out:
92     if(surf) IDirect3DSurface9_Release(surf);
93     return ret;
94 }
95
96 static IDirect3DDevice9 *init_d3d9(void)
97 {
98     IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion) = 0;
99     IDirect3D9 *d3d9_ptr = 0;
100     IDirect3DDevice9 *device_ptr = 0;
101     D3DPRESENT_PARAMETERS present_parameters;
102     HRESULT hr;
103
104     d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
105     ok(d3d9_create != NULL, "Failed to get address of Direct3DCreate9\n");
106     if (!d3d9_create) return NULL;
107
108     d3d9_ptr = d3d9_create(D3D_SDK_VERSION);
109     ok(d3d9_ptr != NULL, "Failed to create IDirect3D9 object\n");
110     if (!d3d9_ptr) return NULL;
111
112     ZeroMemory(&present_parameters, sizeof(present_parameters));
113     present_parameters.Windowed = FALSE;
114     present_parameters.hDeviceWindow = create_window();
115     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
116     present_parameters.BackBufferWidth = 640;
117     present_parameters.BackBufferHeight = 480;
118     present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
119     present_parameters.EnableAutoDepthStencil = TRUE;
120     present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
121
122     hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
123     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D_CreateDevice returned: %s\n", DXGetErrorString9(hr));
124
125     return device_ptr;
126 }
127
128 struct vertex
129 {
130     float x, y, z;
131     DWORD diffuse;
132 };
133
134 struct tvertex
135 {
136     float x, y, z, rhw;
137     DWORD diffuse;
138 };
139
140 struct nvertex
141 {
142     float x, y, z;
143     float nx, ny, nz;
144     DWORD diffuse;
145 };
146
147 static void lighting_test(IDirect3DDevice9 *device)
148 {
149     HRESULT hr;
150     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
151     DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
152     DWORD color;
153
154     float mat[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
155                       0.0f, 1.0f, 0.0f, 0.0f,
156                       0.0f, 0.0f, 1.0f, 0.0f,
157                       0.0f, 0.0f, 0.0f, 1.0f };
158
159     struct vertex unlitquad[] =
160     {
161         {-1.0f, -1.0f,   0.1f,                          0xffff0000},
162         {-1.0f,  0.0f,   0.1f,                          0xffff0000},
163         { 0.0f,  0.0f,   0.1f,                          0xffff0000},
164         { 0.0f, -1.0f,   0.1f,                          0xffff0000},
165     };
166     struct vertex litquad[] =
167     {
168         {-1.0f,  0.0f,   0.1f,                          0xff00ff00},
169         {-1.0f,  1.0f,   0.1f,                          0xff00ff00},
170         { 0.0f,  1.0f,   0.1f,                          0xff00ff00},
171         { 0.0f,  0.0f,   0.1f,                          0xff00ff00},
172     };
173     struct nvertex unlitnquad[] =
174     {
175         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
176         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
177         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
178         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
179     };
180     struct nvertex litnquad[] =
181     {
182         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
183         { 0.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
184         { 1.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
185         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
186     };
187     WORD Indices[] = {0, 1, 2, 2, 3, 0};
188
189     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
190     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
191
192     /* Setup some states that may cause issues */
193     hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(0), (D3DMATRIX *) mat);
194     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %s\n", DXGetErrorString9(hr));
195     hr = IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, (D3DMATRIX *)mat);
196     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %s\n", DXGetErrorString9(hr));
197     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, (D3DMATRIX *) mat);
198     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %s\n", DXGetErrorString9(hr));
199     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
200     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
201     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
202     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
203     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
204     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
205     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
206     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
207     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, FALSE);
208     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
209     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
210     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
211     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, FALSE);
212     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
213     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
214     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %s\n", DXGetErrorString9(hr));
215     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
216     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %s\n", DXGetErrorString9(hr));
217
218     hr = IDirect3DDevice9_SetFVF(device, fvf);
219     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
220
221     hr = IDirect3DDevice9_BeginScene(device);
222     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
223     if(hr == D3D_OK)
224     {
225         /* No lights are defined... That means, lit vertices should be entirely black */
226         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
227         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
228         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
229                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitquad, sizeof(unlitquad[0]));
230         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
231
232         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
233         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
234         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
235                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litquad, sizeof(litquad[0]));
236         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
237
238         hr = IDirect3DDevice9_SetFVF(device, nfvf);
239         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
240
241         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
242         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
243         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
244                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitnquad, sizeof(unlitnquad[0]));
245         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
246
247         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
248         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
249         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
250                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litnquad, sizeof(litnquad[0]));
251         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
252
253         IDirect3DDevice9_EndScene(device);
254         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
255     }
256
257     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
258
259     color = getPixelColor(device, 160, 360); /* lower left quad - unlit without normals */
260     ok(color == 0x00ff0000, "Unlit quad without normals has color %08x\n", color);
261     color = getPixelColor(device, 160, 120); /* upper left quad - lit without normals */
262     ok(color == 0x00000000, "Lit quad without normals has color %08x\n", color);
263     color = getPixelColor(device, 480, 360); /* lower left quad - unlit width normals */
264     ok(color == 0x000000ff, "Unlit quad width normals has color %08x\n", color);
265     color = getPixelColor(device, 480, 120); /* upper left quad - lit width normals */
266     ok(color == 0x00000000, "Lit quad width normals has color %08x\n", color);
267
268     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
269     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
270 }
271
272 static void clear_test(IDirect3DDevice9 *device)
273 {
274     /* Tests the correctness of clearing parameters */
275     HRESULT hr;
276     D3DRECT rect[2];
277     D3DRECT rect_negneg;
278     DWORD color;
279     D3DVIEWPORT9 old_vp, vp;
280     RECT scissor;
281     DWORD oldColorWrite;
282     BOOL invalid_clear_failed = FALSE;
283
284     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
285     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
286
287     /* Positive x, negative y */
288     rect[0].x1 = 0;
289     rect[0].y1 = 480;
290     rect[0].x2 = 320;
291     rect[0].y2 = 240;
292
293     /* Positive x, positive y */
294     rect[1].x1 = 0;
295     rect[1].y1 = 0;
296     rect[1].x2 = 320;
297     rect[1].y2 = 240;
298     /* Clear 2 rectangles with one call. The refrast returns an error in this case, every real driver tested so far
299      * returns D3D_OK, but ignores the rectangle silently
300      */
301     hr = IDirect3DDevice9_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
302     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
303     if(hr == D3DERR_INVALIDCALL) invalid_clear_failed = TRUE;
304
305     /* negative x, negative y */
306     rect_negneg.x1 = 640;
307     rect_negneg.y1 = 240;
308     rect_negneg.x2 = 320;
309     rect_negneg.y2 = 0;
310     hr = IDirect3DDevice9_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
311     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
312     if(hr == D3DERR_INVALIDCALL) invalid_clear_failed = TRUE;
313
314     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
315
316     color = getPixelColor(device, 160, 360); /* lower left quad */
317     ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
318     color = getPixelColor(device, 160, 120); /* upper left quad */
319     if(invalid_clear_failed) {
320         /* If the negative rectangle was refused, the other rectangles in the list shouldn't be cleared either */
321         ok(color == 0x00ffffff, "Clear rectangle 1(pos, pos) has color %08x\n", color);
322     } else {
323         /* If the negative rectangle was dropped silently, the correct ones are cleared */
324         ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
325     }
326     color = getPixelColor(device, 480, 360); /* lower right quad  */
327     ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
328     color = getPixelColor(device, 480, 120); /* upper right quad */
329     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
330
331     /* Test how the viewport affects clears */
332     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
333     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
334     hr = IDirect3DDevice9_GetViewport(device, &old_vp);
335     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %s\n", DXGetErrorString9(hr));
336
337     vp.X = 160;
338     vp.Y = 120;
339     vp.Width = 160;
340     vp.Height = 120;
341     vp.MinZ = 0.0;
342     vp.MaxZ = 1.0;
343     hr = IDirect3DDevice9_SetViewport(device, &vp);
344     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %s\n", DXGetErrorString9(hr));
345     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
346     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
347
348     vp.X = 320;
349     vp.Y = 240;
350     vp.Width = 320;
351     vp.Height = 240;
352     vp.MinZ = 0.0;
353     vp.MaxZ = 1.0;
354     hr = IDirect3DDevice9_SetViewport(device, &vp);
355     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %s\n", DXGetErrorString9(hr));
356     rect[0].x1 = 160;
357     rect[0].y1 = 120;
358     rect[0].x2 = 480;
359     rect[0].y2 = 360;
360     hr = IDirect3DDevice9_Clear(device, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
361     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
362
363     hr = IDirect3DDevice9_SetViewport(device, &old_vp);
364     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %s\n", DXGetErrorString9(hr));
365
366     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
367     color = getPixelColor(device, 158, 118);
368     ok(color == 0x00ffffff, "(158,118) has color %08x\n", color);
369     color = getPixelColor(device, 162, 118);
370     ok(color == 0x00ffffff, "(162,118) has color %08x\n", color);
371     color = getPixelColor(device, 158, 122);
372     ok(color == 0x00ffffff, "(158,122) has color %08x\n", color);
373     color = getPixelColor(device, 162, 122);
374     ok(color == 0x000000ff, "(162,122) has color %08x\n", color);
375
376     color = getPixelColor(device, 318, 238);
377     ok(color == 0x000000ff, "(318,238) has color %08x\n", color);
378     color = getPixelColor(device, 322, 238);
379     ok(color == 0x00ffffff, "(322,328) has color %08x\n", color);
380     color = getPixelColor(device, 318, 242);
381     ok(color == 0x00ffffff, "(318,242) has color %08x\n", color);
382     color = getPixelColor(device, 322, 242);
383     ok(color == 0x0000ff00, "(322,242) has color %08x\n", color);
384
385     color = getPixelColor(device, 478, 358);
386     ok(color == 0x0000ff00, "(478,358 has color %08x\n", color);
387     color = getPixelColor(device, 482, 358);
388     ok(color == 0x00ffffff, "(482,358) has color %08x\n", color);
389     color = getPixelColor(device, 478, 362);
390     ok(color == 0x00ffffff, "(478,362) has color %08x\n", color);
391     color = getPixelColor(device, 482, 362);
392     ok(color == 0x00ffffff, "(482,362) has color %08x\n", color);
393
394     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
395     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
396
397     scissor.left = 160;
398     scissor.right = 480;
399     scissor.top = 120;
400     scissor.bottom = 360;
401     hr = IDirect3DDevice9_SetScissorRect(device, &scissor);
402     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %s\n", DXGetErrorString9(hr));
403     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, TRUE);
404     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %s\n", DXGetErrorString9(hr));
405
406     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
407     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
408     hr = IDirect3DDevice9_Clear(device, 1, &rect[1], D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
409     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
410
411     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, FALSE);
412     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %s\n", DXGetErrorString9(hr));
413
414     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
415     color = getPixelColor(device, 158, 118);
416     ok(color == 0x00ffffff, "Pixel 158/118 has color %08x\n", color);
417     color = getPixelColor(device, 162, 118);
418     ok(color == 0x00ffffff, "Pixel 162/118 has color %08x\n", color);
419     color = getPixelColor(device, 158, 122);
420     ok(color == 0x00ffffff, "Pixel 158/122 has color %08x\n", color);
421     color = getPixelColor(device, 162, 122);
422     ok(color == 0x00ff0000, "Pixel 162/122 has color %08x\n", color);
423
424     color = getPixelColor(device, 158, 358);
425     ok(color == 0x00ffffff, "Pixel 158/358 has color %08x\n", color);
426     color = getPixelColor(device, 162, 358);
427     ok(color == 0x0000ff00, "Pixel 162/358 has color %08x\n", color);
428     color = getPixelColor(device, 158, 358);
429     ok(color == 0x00ffffff, "Pixel 158/358 has color %08x\n", color);
430     color = getPixelColor(device, 162, 362);
431     ok(color == 0x00ffffff, "Pixel 162/362 has color %08x\n", color);
432
433     color = getPixelColor(device, 478, 118);
434     ok(color == 0x00ffffff, "Pixel 158/118 has color %08x\n", color);
435     color = getPixelColor(device, 478, 122);
436     ok(color == 0x0000ff00, "Pixel 162/118 has color %08x\n", color);
437     color = getPixelColor(device, 482, 122);
438     ok(color == 0x00ffffff, "Pixel 158/122 has color %08x\n", color);
439     color = getPixelColor(device, 482, 358);
440     ok(color == 0x00ffffff, "Pixel 162/122 has color %08x\n", color);
441
442     color = getPixelColor(device, 478, 358);
443     ok(color == 0x0000ff00, "Pixel 478/358 has color %08x\n", color);
444     color = getPixelColor(device, 478, 362);
445     ok(color == 0x00ffffff, "Pixel 478/118 has color %08x\n", color);
446     color = getPixelColor(device, 482, 358);
447     ok(color == 0x00ffffff, "Pixel 482/122 has color %08x\n", color);
448     color = getPixelColor(device, 482, 362);
449     ok(color == 0x00ffffff, "Pixel 482/122 has color %08x\n", color);
450
451     color = getPixelColor(device, 318, 238);
452     ok(color == 0x00ff0000, "Pixel 318/238 has color %08x\n", color);
453     color = getPixelColor(device, 318, 242);
454     ok(color == 0x0000ff00, "Pixel 318/242 has color %08x\n", color);
455     color = getPixelColor(device, 322, 238);
456     ok(color == 0x0000ff00, "Pixel 322/238 has color %08x\n", color);
457     color = getPixelColor(device, 322, 242);
458     ok(color == 0x0000ff00, "Pixel 322/242 has color %08x\n", color);
459
460     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_COLORWRITEENABLE, &oldColorWrite);
461     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %s\n", DXGetErrorString9(hr));
462     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED);
463     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %s\n", DXGetErrorString9(hr));
464
465     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
466     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
467
468     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, oldColorWrite);
469     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %s\n", DXGetErrorString9(hr));
470
471     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
472
473     /* Colorwriteenable does not affect the clear */
474     color = getPixelColor(device, 320, 240);
475     ok(color == 0x00ffffff, "Color write protected clear returned color %08x\n", color);
476 }
477
478 typedef struct {
479     float in[4];
480     DWORD out;
481 } test_data_t;
482
483 /*
484  *  c7      mova    ARGB            mov     ARGB
485  * -2.4     -2      0x00ffff00      -3      0x00ff0000
486  * -1.6     -2      0x00ffff00      -2      0x00ffff00
487  * -0.4      0      0x0000ffff      -1      0x0000ff00
488  *  0.4      0      0x0000ffff       0      0x0000ffff
489  *  1.6      2      0x00ff00ff       1      0x000000ff
490  *  2.4      2      0x00ff00ff       2      0x00ff00ff
491  */
492 static void test_mova(IDirect3DDevice9 *device)
493 {
494     static const DWORD mova_test[] = {
495         0xfffe0200,                                                             /* vs_2_0                       */
496         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
497         0x05000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0   */
498         0x05000051, 0xa00f0001, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, /* def c1, 1.0, 1.0, 0.0, 1.0   */
499         0x05000051, 0xa00f0002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, /* def c2, 0.0, 1.0, 0.0, 1.0   */
500         0x05000051, 0xa00f0003, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 0.0, 1.0, 1.0, 1.0   */
501         0x05000051, 0xa00f0004, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c4, 0.0, 0.0, 1.0, 1.0   */
502         0x05000051, 0xa00f0005, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, /* def c5, 1.0, 0.0, 1.0, 1.0   */
503         0x05000051, 0xa00f0006, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c6, 1.0, 1.0, 1.0, 1.0   */
504         0x0200002e, 0xb0010000, 0xa0000007,                                     /* mova a0.x, c7.x              */
505         0x03000001, 0xd00f0000, 0xa0e42003, 0xb0000000,                         /* mov oD0, c[a0.x + 3]         */
506         0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
507         0x0000ffff                                                              /* END                          */
508     };
509     static const DWORD mov_test[] = {
510         0xfffe0101,                                                             /* vs_1_1                       */
511         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
512         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0   */
513         0x00000051, 0xa00f0001, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, /* def c1, 1.0, 1.0, 0.0, 1.0   */
514         0x00000051, 0xa00f0002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, /* def c2, 0.0, 1.0, 0.0, 1.0   */
515         0x00000051, 0xa00f0003, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 0.0, 1.0, 1.0, 1.0   */
516         0x00000051, 0xa00f0004, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c4, 0.0, 0.0, 1.0, 1.0   */
517         0x00000051, 0xa00f0005, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, /* def c5, 1.0, 0.0, 1.0, 1.0   */
518         0x00000051, 0xa00f0006, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c6, 1.0, 1.0, 1.0, 1.0   */
519         0x00000001, 0xb0010000, 0xa0000007,                                     /* mov a0.x, c7.x               */
520         0x00000001, 0xd00f0000, 0xa0e42003,                                     /* mov oD0, c[a0.x + 3]         */
521         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
522         0x0000ffff                                                              /* END                          */
523     };
524
525     static const test_data_t test_data[2][6] = {
526         {
527             {{-2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff0000},
528             {{-1.6f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
529             {{-0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ff00},
530             {{ 0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
531             {{ 1.6f, 0.0f, 0.0f, 0.0f}, 0x000000ff},
532             {{ 2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff}
533         },
534         {
535             {{-2.4f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
536             {{-1.6f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
537             {{-0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
538             {{ 0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
539             {{ 1.6f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff},
540             {{ 2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff}
541         }
542     };
543
544     static const float quad[][3] = {
545         {-1.0f, -1.0f, 0.0f},
546         {-1.0f,  1.0f, 0.0f},
547         { 1.0f, -1.0f, 0.0f},
548         { 1.0f,  1.0f, 0.0f},
549     };
550
551     static const D3DVERTEXELEMENT9 decl_elements[] = {
552         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
553         D3DDECL_END()
554     };
555
556     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
557     IDirect3DVertexShader9 *mova_shader = NULL;
558     IDirect3DVertexShader9 *mov_shader = NULL;
559     HRESULT hr;
560     int i, j;
561
562     hr = IDirect3DDevice9_CreateVertexShader(device, mova_test, &mova_shader);
563     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
564     hr = IDirect3DDevice9_CreateVertexShader(device, mov_test, &mov_shader);
565     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
566     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
567     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
568     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
569     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
570
571     hr = IDirect3DDevice9_SetVertexShader(device, mov_shader);
572     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
573     for(j = 0; j < 2; ++j)
574     {
575         for (i = 0; i < (sizeof(test_data[0]) / sizeof(test_data_t)); ++i)
576         {
577             DWORD color;
578
579             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 7, test_data[j][i].in, 1);
580             ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
581
582             hr = IDirect3DDevice9_BeginScene(device);
583             ok(SUCCEEDED(hr), "BeginScene failed (%08x)\n", hr);
584
585             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], 3 * sizeof(float));
586             ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
587
588             hr = IDirect3DDevice9_EndScene(device);
589             ok(SUCCEEDED(hr), "EndScene failed (%08x)\n", hr);
590
591             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
592             ok(SUCCEEDED(hr), "Present failed (%08x)\n", hr);
593
594             color = getPixelColor(device, 320, 240);
595             ok(color == test_data[j][i].out, "Expected color %08x, got %08x (for input %f, instruction %s)\n",
596                test_data[j][i].out, color, test_data[j][i].in[0], j == 0 ? "mov" : "mova");
597
598             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
599             ok(SUCCEEDED(hr), "Clear failed (%08x)\n", hr);
600         }
601         hr = IDirect3DDevice9_SetVertexShader(device, mova_shader);
602         ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
603     }
604
605     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
606     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
607
608     IDirect3DVertexDeclaration9_Release(vertex_declaration);
609     IDirect3DVertexShader9_Release(mova_shader);
610     IDirect3DVertexShader9_Release(mov_shader);
611 }
612
613 struct sVertex {
614     float x, y, z;
615     DWORD diffuse;
616     DWORD specular;
617 };
618
619 struct sVertexT {
620     float x, y, z, rhw;
621     DWORD diffuse;
622     DWORD specular;
623 };
624
625 static void fog_test(IDirect3DDevice9 *device)
626 {
627     HRESULT hr;
628     DWORD color;
629     float start = 0.0f, end = 1.0f;
630     D3DCAPS9 caps;
631
632     /* Gets full z based fog with linear fog, no fog with specular color */
633     struct sVertex unstransformed_1[] = {
634         {-1,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
635         {-1,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
636         { 0,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
637         { 0,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
638     };
639     /* Ok, I am too lazy to deal with transform matrices */
640     struct sVertex unstransformed_2[] = {
641         {-1,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
642         {-1,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
643         { 0,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
644         { 0,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
645     };
646     /* Untransformed ones. Give them a different diffuse color to make the test look
647      * nicer. It also makes making sure that they are drawn correctly easier.
648      */
649     struct sVertexT transformed_1[] = {
650         {320,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
651         {640,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
652         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
653         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
654     };
655     struct sVertexT transformed_2[] = {
656         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
657         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
658         {640,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
659         {320,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
660     };
661     WORD Indices[] = {0, 1, 2, 2, 3, 0};
662
663     memset(&caps, 0, sizeof(caps));
664     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
665     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %s\n", DXGetErrorString9(hr));
666     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
667     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
668
669     /* Setup initial states: No lighting, fog on, fog color */
670     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
671     ok(hr == D3D_OK, "Turning off lighting returned %s\n", DXGetErrorString9(hr));
672     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
673     ok(hr == D3D_OK, "Turning on fog calculations returned %s\n", DXGetErrorString9(hr));
674     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
675     ok(hr == D3D_OK, "Turning on fog calculations returned %s\n", DXGetErrorString9(hr));
676
677     /* First test: Both table fog and vertex fog off */
678     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
679     ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString9(hr));
680     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
681     ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString9(hr));
682
683     /* Start = 0, end = 1. Should be default, but set them */
684     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
685     ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
686     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
687     ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
688
689     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
690     {
691         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
692         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
693         /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
694         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
695                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_1,
696                                                      sizeof(unstransformed_1[0]));
697         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
698
699         /* That makes it use the Z value */
700         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
701         ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString9(hr));
702         /* Untransformed, vertex fog != none (or table fog != none):
703          * Use the Z value as input into the equation
704          */
705         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
706                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_2,
707                                                      sizeof(unstransformed_1[0]));
708         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
709
710         /* transformed verts */
711         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
712         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
713         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
714         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
715                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
716                                                      sizeof(transformed_1[0]));
717         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
718
719         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
720         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %s\n", DXGetErrorString9(hr));
721         /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
722          * equation
723          */
724         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
725                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_2,
726                                                      sizeof(transformed_2[0]));
727
728         hr = IDirect3DDevice9_EndScene(device);
729         ok(hr == D3D_OK, "EndScene returned %s\n", DXGetErrorString9(hr));
730     }
731     else
732     {
733         ok(FALSE, "BeginScene failed\n");
734     }
735
736     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
737     color = getPixelColor(device, 160, 360);
738     ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color);
739     color = getPixelColor(device, 160, 120);
740     ok(color == 0x0000FF00, "Untransformed vertex with linear vertex fog has color %08x\n", color);
741     color = getPixelColor(device, 480, 120);
742     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
743     if(caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
744     {
745         color = getPixelColor(device, 480, 360);
746         ok(color == 0x0000FF00, "Transformed vertex with linear table fog has color %08x\n", color);
747     }
748     else
749     {
750         /* Without fog table support the vertex fog is still applied, even though table fog is turned on.
751          * The settings above result in no fogging with vertex fog
752          */
753         color = getPixelColor(device, 480, 120);
754         ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
755         trace("Info: Table fog not supported by this device\n");
756     }
757
758     /* Now test the special case fogstart == fogend */
759     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
760     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
761
762     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
763     {
764         start = 512;
765         end = 512;
766         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
767         ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
768         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
769         ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
770
771         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
772         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
773         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
774         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState %s\n", DXGetErrorString9(hr));
775         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
776         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %s\n", DXGetErrorString9(hr));
777
778         /* Untransformed vertex, z coord = 0.1, fogstart = 512, fogend = 512. Would result in
779          * a completely fog-free primitive because start > zcoord, but because start == end, the primitive
780          * is fully covered by fog. The same happens to the 2nd untransformed quad with z = 1.0.
781          * The third transformed quad remains unfogged because the fogcoords are read from the specular
782          * color and has fixed fogstart and fogend.
783          */
784         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
785                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_1,
786                 sizeof(unstransformed_1[0]));
787         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
788         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
789                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_2,
790                 sizeof(unstransformed_1[0]));
791         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
792
793         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
794         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
795         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
796         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
797                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
798                 sizeof(transformed_1[0]));
799         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
800
801         hr = IDirect3DDevice9_EndScene(device);
802         ok(hr == D3D_OK, "EndScene returned %s\n", DXGetErrorString9(hr));
803     }
804     else
805     {
806         ok(FALSE, "BeginScene failed\n");
807     }
808     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
809     color = getPixelColor(device, 160, 360);
810     ok(color == 0x0000FF00, "Untransformed vertex with vertex fog and z = 0.1 has color %08x\n", color);
811     color = getPixelColor(device, 160, 120);
812     ok(color == 0x0000FF00, "Untransformed vertex with vertex fog and z = 1.0 has color %08x\n", color);
813     color = getPixelColor(device, 480, 120);
814     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
815
816     /* Turn off the fog master switch to avoid confusing other tests */
817     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
818     ok(hr == D3D_OK, "Turning off fog calculations returned %s\n", DXGetErrorString9(hr));
819     start = 0.0;
820     end = 1.0;
821     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
822     ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
823     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
824     ok(hr == D3D_OK, "Setting fog end returned %s\n", DXGetErrorString9(hr));
825     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
826     ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState %s\n", DXGetErrorString9(hr));
827     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
828     ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %s\n", DXGetErrorString9(hr));
829 }
830
831 /* This test verifies the behaviour of cube maps wrt. texture wrapping.
832  * D3D cube map wrapping always behaves like GL_CLAMP_TO_EDGE,
833  * regardless of the actual addressing mode set. */
834 static void test_cube_wrap(IDirect3DDevice9 *device)
835 {
836     static const float quad[][6] = {
837         {-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
838         {-1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
839         { 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
840         { 1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
841     };
842
843     static const D3DVERTEXELEMENT9 decl_elements[] = {
844         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
845         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
846         D3DDECL_END()
847     };
848
849     static const struct {
850         D3DTEXTUREADDRESS mode;
851         const char *name;
852     } address_modes[] = {
853         {D3DTADDRESS_WRAP, "D3DTADDRESS_WRAP"},
854         {D3DTADDRESS_MIRROR, "D3DTADDRESS_MIRROR"},
855         {D3DTADDRESS_CLAMP, "D3DTADDRESS_CLAMP"},
856         {D3DTADDRESS_BORDER, "D3DTADDRESS_BORDER"},
857         {D3DTADDRESS_MIRRORONCE, "D3DTADDRESS_MIRRORONCE"},
858     };
859
860     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
861     IDirect3DCubeTexture9 *texture = NULL;
862     IDirect3DSurface9 *surface = NULL;
863     D3DLOCKED_RECT locked_rect;
864     HRESULT hr;
865     INT x, y, face;
866
867     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
868     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
869     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
870     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
871
872     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
873             D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL);
874     ok(SUCCEEDED(hr), "CreateOffscreenPlainSurface failed (0x%08x)\n", hr);
875
876     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, D3DLOCK_DISCARD);
877     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
878
879     for (y = 0; y < 128; ++y)
880     {
881         DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
882         for (x = 0; x < 64; ++x)
883         {
884             *ptr++ = 0xffff0000;
885         }
886         for (x = 64; x < 128; ++x)
887         {
888             *ptr++ = 0xff0000ff;
889         }
890     }
891
892     hr = IDirect3DSurface9_UnlockRect(surface);
893     ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
894
895     hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
896             D3DPOOL_DEFAULT, &texture, NULL);
897     ok(SUCCEEDED(hr), "CreateCubeTexture failed (0x%08x)\n", hr);
898
899     /* Create cube faces */
900     for (face = 0; face < 6; ++face)
901     {
902         IDirect3DSurface9 *face_surface = NULL;
903
904         hr= IDirect3DCubeTexture9_GetCubeMapSurface(texture, face, 0, &face_surface);
905         ok(SUCCEEDED(hr), "GetCubeMapSurface failed (0x%08x)\n", hr);
906
907         hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, face_surface, NULL);
908         ok(SUCCEEDED(hr), "UpdateSurface failed (0x%08x)\n", hr);
909
910         IDirect3DSurface9_Release(face_surface);
911     }
912
913     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
914     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
915
916     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
917     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
918     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
919     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
920     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_BORDERCOLOR, 0xff00ff00);
921     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_BORDERCOLOR failed (0x%08x)\n", hr);
922
923     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
924     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
925
926     for (x = 0; x < (sizeof(address_modes) / sizeof(*address_modes)); ++x)
927     {
928         DWORD color;
929
930         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, address_modes[x].mode);
931         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU (%s) failed (0x%08x)\n", address_modes[x].name, hr);
932         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, address_modes[x].mode);
933         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV (%s) failed (0x%08x)\n", address_modes[x].name, hr);
934
935         hr = IDirect3DDevice9_BeginScene(device);
936         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
937
938         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
939         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
940
941         hr = IDirect3DDevice9_EndScene(device);
942         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
943
944         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
945         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
946
947         /* Due to the nature of this test, we sample essentially at the edge
948          * between two faces. Because of this it's undefined from which face
949          * the driver will sample. Furtunately that's not important for this
950          * test, since all we care about is that it doesn't sample from the
951          * other side of the surface or from the border. */
952         color = getPixelColor(device, 320, 240);
953         ok(color == 0x00ff0000 || color == 0x000000ff,
954                 "Got color 0x%08x for addressing mode %s, expected 0x00ff0000 or 0x000000ff.\n",
955                 color, address_modes[x].name);
956
957         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
958         ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
959     }
960
961     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
962     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
963
964     IDirect3DVertexDeclaration9_Release(vertex_declaration);
965     IDirect3DCubeTexture9_Release(texture);
966     IDirect3DSurface9_Release(surface);
967 }
968
969 static void offscreen_test(IDirect3DDevice9 *device)
970 {
971     HRESULT hr;
972     IDirect3DTexture9 *offscreenTexture = NULL;
973     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
974     DWORD color;
975
976     static const float quad[][5] = {
977         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
978         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
979         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
980         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
981     };
982
983     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
984     ok(hr == D3D_OK, "Clear failed, hr = %s\n", DXGetErrorString9(hr));
985
986     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
987     ok(hr == D3D_OK || D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %s\n", DXGetErrorString9(hr));
988     if(!offscreenTexture) {
989         trace("Failed to create an X8R8G8B8 offscreen texture, trying R5G6B5\n");
990         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
991         ok(hr == D3D_OK || D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %s\n", DXGetErrorString9(hr));
992         if(!offscreenTexture) {
993             skip("Cannot create an offscreen render target\n");
994             goto out;
995         }
996     }
997
998     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
999     ok(hr == D3D_OK, "Can't get back buffer, hr = %s\n", DXGetErrorString9(hr));
1000     if(!backbuffer) {
1001         goto out;
1002     }
1003
1004     hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
1005     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %s\n", DXGetErrorString9(hr));
1006     if(!offscreen) {
1007         goto out;
1008     }
1009
1010     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
1011     ok(hr == D3D_OK, "SetFVF failed, hr = %s\n", DXGetErrorString9(hr));
1012
1013     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
1014     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
1015     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
1016     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
1017     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
1018     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1019     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
1020     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1021     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1022     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1023
1024     if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
1025         hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
1026         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %s\n", DXGetErrorString9(hr));
1027         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1028         ok(hr == D3D_OK, "Clear failed, hr = %s\n", DXGetErrorString9(hr));
1029
1030         /* Draw without textures - Should resut in a white quad */
1031         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
1032         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %s\n", DXGetErrorString9(hr));
1033
1034         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
1035         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %s\n", DXGetErrorString9(hr));
1036         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
1037         ok(hr == D3D_OK, "SetTexture failed, %s\n", DXGetErrorString9(hr));
1038
1039         /* This time with the texture */
1040         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
1041         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %s\n", DXGetErrorString9(hr));
1042
1043         IDirect3DDevice9_EndScene(device);
1044     }
1045
1046     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1047
1048     /* Center quad - should be white */
1049     color = getPixelColor(device, 320, 240);
1050     ok(color == 0x00ffffff, "Offscreen failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1051     /* Some quad in the cleared part of the texture */
1052     color = getPixelColor(device, 170, 240);
1053     ok(color == 0x00ff00ff, "Offscreen failed: Got color 0x%08x, expected 0x00ff00ff.\n", color);
1054     /* Part of the originally cleared back buffer */
1055     color = getPixelColor(device, 10, 10);
1056     ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1057     if(0) {
1058         /* Lower left corner of the screen, where back buffer offscreen rendering draws the offscreen texture.
1059          * It should be red, but the offscreen texture may leave some junk there. Not tested yet. Depending on
1060          * the offscreen rendering mode this test would succeed or fail
1061          */
1062         color = getPixelColor(device, 10, 470);
1063         ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1064     }
1065
1066 out:
1067     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1068
1069     /* restore things */
1070     if(backbuffer) {
1071         IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
1072         IDirect3DSurface9_Release(backbuffer);
1073     }
1074     if(offscreenTexture) {
1075         IDirect3DTexture9_Release(offscreenTexture);
1076     }
1077     if(offscreen) {
1078         IDirect3DSurface9_Release(offscreen);
1079     }
1080 }
1081
1082 /* This test tests fog in combination with shaders.
1083  * What's tested: linear fog (vertex and table) with pixel shader
1084  *                linear table fog with non foggy vertex shader
1085  *                vertex fog with foggy vertex shader
1086  * What's not tested: non linear fog with shader
1087  *                    table fog with foggy vertex shader
1088  */
1089 static void fog_with_shader_test(IDirect3DDevice9 *device)
1090 {
1091     HRESULT hr;
1092     DWORD color;
1093     union {
1094         float f;
1095         DWORD i;
1096     } start, end;
1097     unsigned int i, j;
1098
1099     /* basic vertex shader without fog computation ("non foggy") */
1100     static const DWORD vertex_shader_code1[] = {
1101         0xfffe0101,                                                             /* vs_1_1                       */
1102         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
1103         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                */
1104         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
1105         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                  */
1106         0x0000ffff
1107     };
1108     /* basic vertex shader with reversed fog computation ("foggy") */
1109     static const DWORD vertex_shader_code2[] = {
1110         0xfffe0101,                                                             /* vs_1_1                        */
1111         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0               */
1112         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                 */
1113         0x00000051, 0xa00f0000, 0xbfa00000, 0x00000000, 0xbf666666, 0x00000000, /* def c0, -1.25, 0.0, -0.9, 0.0 */
1114         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                  */
1115         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                   */
1116         0x00000002, 0x800f0000, 0x90aa0000, 0xa0aa0000,                         /* add r0, v0.z, c0.z            */
1117         0x00000005, 0xc00f0001, 0x80000000, 0xa0000000,                         /* mul oFog, r0.x, c0.x          */
1118         0x0000ffff
1119     };
1120     /* basic pixel shader */
1121     static const DWORD pixel_shader_code[] = {
1122         0xffff0101,                                                             /* ps_1_1     */
1123         0x00000001, 0x800f0000, 0x90e40000,                                     /* mov r0, vo */
1124         0x0000ffff
1125     };
1126
1127     static struct vertex quad[] = {
1128         {-1.0f, -1.0f,  0.0f,          0xFFFF0000  },
1129         {-1.0f,  1.0f,  0.0f,          0xFFFF0000  },
1130         { 1.0f, -1.0f,  0.0f,          0xFFFF0000  },
1131         { 1.0f,  1.0f,  0.0f,          0xFFFF0000  },
1132     };
1133
1134     static const D3DVERTEXELEMENT9 decl_elements[] = {
1135         {0,  0, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1136         {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
1137         D3DDECL_END()
1138     };
1139
1140     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1141     IDirect3DVertexShader9      *vertex_shader[3]   = {NULL, NULL, NULL};
1142     IDirect3DPixelShader9       *pixel_shader[2]    = {NULL, NULL};
1143
1144     /* This reference data was collected on a nVidia GeForce 7600GS driver version 84.19 DirectX version 9.0c on Windows XP */
1145     static const struct test_data_t {
1146         int vshader;
1147         int pshader;
1148         D3DFOGMODE vfog;
1149         D3DFOGMODE tfog;
1150         unsigned int color[11];
1151     } test_data[] = {
1152         /* only pixel shader: */
1153         {0, 1, 0, 3,
1154         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1155          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1156         {0, 1, 1, 3,
1157         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1158          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1159         {0, 1, 2, 3,
1160         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1161          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1162         {0, 1, 3, 0,
1163         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1164          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1165         {0, 1, 3, 3,
1166         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1167          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1168
1169         /* vertex shader */
1170         {1, 0, 0, 0,
1171         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1172          0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1173         {1, 0, 0, 3,
1174         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1175          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1176         {1, 0, 1, 3,
1177         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1178          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1179         {1, 0, 2, 3,
1180         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1181          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1182         {1, 0, 3, 3,
1183         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1184          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1185
1186         /* vertex shader and pixel shader */
1187         {1, 1, 0, 3,
1188         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1189          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1190         {1, 1, 1, 3,
1191         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1192          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1193         {1, 1, 2, 3,
1194         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1195          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1196         {1, 1, 3, 3,
1197         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1198          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1199
1200 #if 0  /* FIXME: these fail on GeForce 8500 */
1201         /* foggy vertex shader */
1202         {2, 0, 0, 0,
1203         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1204          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1205         {2, 0, 1, 0,
1206         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1207          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1208         {2, 0, 2, 0,
1209         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1210          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1211         {2, 0, 3, 0,
1212         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1213          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1214 #endif
1215
1216         /* foggy vertex shader and pixel shader */
1217         {2, 1, 0, 0,
1218         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1219          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1220         {2, 1, 1, 0,
1221         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1222          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1223         {2, 1, 2, 0,
1224         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1225          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1226         {2, 1, 3, 0,
1227         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1228          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1229
1230     };
1231
1232     /* NOTE: changing these values will not affect the tests with foggy vertex shader, as the values are hardcoded in the shader*/
1233     start.f=0.9f;
1234     end.f=0.1f;
1235
1236     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code1, &vertex_shader[1]);
1237     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1238     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code2, &vertex_shader[2]);
1239     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1240     hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader[1]);
1241     ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1242     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1243     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
1244
1245     /* Setup initial states: No lighting, fog on, fog color */
1246     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1247     ok(hr == D3D_OK, "Turning off lighting failed (%08x)\n", hr);
1248     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
1249     ok(hr == D3D_OK, "Turning on fog calculations failed (%08x)\n", hr);
1250     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
1251     ok(hr == D3D_OK, "Setting fog color failed (%08x)\n", hr);
1252     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1253     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1254
1255     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
1256     ok(hr == D3D_OK, "Turning off table fog failed (%08x)\n", hr);
1257     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
1258     ok(hr == D3D_OK, "Turning off vertex fog failed (%08x)\n", hr);
1259
1260     /* Use fogtart = 0.1 and end = 0.9 to test behavior outside the fog transition phase, too*/
1261     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, start.i);
1262     ok(hr == D3D_OK, "Setting fog start failed (%08x)\n", hr);
1263     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, end.i);
1264     ok(hr == D3D_OK, "Setting fog end failed (%08x)\n", hr);
1265
1266     for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++)
1267     {
1268         hr = IDirect3DDevice9_SetVertexShader(device, vertex_shader[test_data[i].vshader]);
1269         ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1270         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader[test_data[i].pshader]);
1271         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1272         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, test_data[i].vfog);
1273         ok( hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1274         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, test_data[i].tfog);
1275         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1276
1277         for(j=0; j < 11; j++)
1278         {
1279             /* Don't use the whole zrange to prevent rounding errors */
1280             quad[0].z = 0.001f + (float)j / 10.02f;
1281             quad[1].z = 0.001f + (float)j / 10.02f;
1282             quad[2].z = 0.001f + (float)j / 10.02f;
1283             quad[3].z = 0.001f + (float)j / 10.02f;
1284
1285             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1286             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
1287
1288             hr = IDirect3DDevice9_BeginScene(device);
1289             ok( hr == D3D_OK, "BeginScene returned failed (%08x)\n", hr);
1290
1291             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1292             ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1293
1294             hr = IDirect3DDevice9_EndScene(device);
1295             ok(hr == D3D_OK, "EndScene failed (%08x)\n", hr);
1296
1297             IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1298
1299             /* As the red and green component are the result of blending use 5% tolerance on the expected value */
1300             color = getPixelColor(device, 128, 240);
1301             ok((unsigned char)(color) == ((unsigned char)test_data[i].color[j])
1302                     && abs( ((unsigned char)(color>>8)) - (unsigned char)(test_data[i].color[j]>>8) ) < 13
1303                     && abs( ((unsigned char)(color>>16)) - (unsigned char)(test_data[i].color[j]>>16) ) < 13,
1304                     "fog ps%i vs%i fvm%i ftm%i %d: got color %08x, expected %08x +-5%%\n", test_data[i].vshader, test_data[i].pshader, test_data[i].vfog, test_data[i].tfog, j, color, test_data[i].color[j]);
1305         }
1306     }
1307
1308     /* reset states */
1309     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
1310     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1311     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1312     ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1313     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1314     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1315     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
1316     ok(hr == D3D_OK, "Turning off fog calculations failed (%08x)\n", hr);
1317
1318     IDirect3DVertexShader9_Release(vertex_shader[1]);
1319     IDirect3DVertexShader9_Release(vertex_shader[2]);
1320     IDirect3DPixelShader9_Release(pixel_shader[1]);
1321     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1322 }
1323
1324 /* test the behavior of the texbem instruction
1325  * with normal 2D and projective 2D textures
1326  */
1327 static void texbem_test(IDirect3DDevice9 *device)
1328 {
1329     HRESULT hr;
1330     DWORD color;
1331     unsigned int i, x, y;
1332
1333     static const DWORD pixel_shader_code[] = {
1334         0xffff0101,                         /* ps_1_1*/
1335         0x00000042, 0xb00f0000,             /* tex t0*/
1336         0x00000043, 0xb00f0001, 0xb0e40000, /* texbem t1, t0*/
1337         0x00000001, 0x800f0000, 0xb0e40001, /* mov r0, t1*/
1338         0x0000ffff
1339     };
1340
1341     static const float quad[][7] = {
1342         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f},
1343         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f},
1344         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 1.0f, 0.0f},
1345         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 1.0f, 1.0f},
1346     };
1347     static const float quad_proj[][9] = {
1348         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f,   0.0f,   0.0f, 0.0f, 128.0f},
1349         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f,   0.0f, 128.0f, 0.0f, 128.0f},
1350         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 128.0f,   0.0f, 0.0f, 128.0f},
1351         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 128.0f, 128.0f, 0.0f, 128.0f},
1352     };
1353
1354     static const D3DVERTEXELEMENT9 decl_elements[][4] = { {
1355         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1356         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1357         {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1358         D3DDECL_END()
1359     },{
1360         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1361         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1362         {0, 20, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1363         D3DDECL_END()
1364     } };
1365
1366     /* use assymetric matrix to test loading */
1367     float bumpenvmat[4] = {0.0,0.5,-0.5,0.0};
1368
1369     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1370     IDirect3DPixelShader9       *pixel_shader       = NULL;
1371     IDirect3DTexture9           *texture[2]         = {NULL, NULL};
1372     D3DLOCKED_RECT locked_rect;
1373
1374     /* Generate the textures */
1375     for(i=0; i<2; i++)
1376     {
1377         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, i?D3DFMT_A8R8G8B8:D3DFMT_V8U8,
1378                 D3DPOOL_MANAGED, &texture[i], NULL);
1379         ok(SUCCEEDED(hr), "CreateTexture failed (0x%08x)\n", hr);
1380
1381         hr = IDirect3DTexture9_LockRect(texture[i], 0, &locked_rect, NULL, D3DLOCK_DISCARD);
1382         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1383         for (y = 0; y < 128; ++y)
1384         {
1385             if(i)
1386             { /* Set up black texture with 2x2 texel white spot in the middle */
1387                 DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1388                 for (x = 0; x < 128; ++x)
1389                 {
1390                     if(y>62 && y<66 && x>62 && x<66)
1391                         *ptr++ = 0xffffffff;
1392                     else
1393                         *ptr++ = 0xff000000;
1394                 }
1395             }
1396             else
1397             { /* Set up a displacement map which points away from the center parallel to the closest axis.
1398               * (if multiplied with bumpenvmat)
1399               */
1400                 WORD *ptr = (WORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1401                 for (x = 0; x < 128; ++x)
1402                 {
1403                     if(abs(x-64)>abs(y-64))
1404                     {
1405                         if(x < 64)
1406                             *ptr++ = 0xc000;
1407                         else
1408                             *ptr++ = 0x4000;
1409                     }
1410                     else
1411                     {
1412                         if(y < 64)
1413                             *ptr++ = 0x0040;
1414                         else
1415                             *ptr++ = 0x00c0;
1416                     }
1417                 }
1418             }
1419         }
1420         hr = IDirect3DTexture9_UnlockRect(texture[i], 0);
1421         ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
1422
1423         hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture[i]);
1424         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1425
1426         /* Disable texture filtering */
1427         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MINFILTER, D3DTEXF_POINT);
1428         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1429         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
1430         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1431
1432         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1433         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU failed (0x%08x)\n", hr);
1434         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1435         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV failed (0x%08x)\n", hr);
1436     }
1437
1438     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
1439     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
1440     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
1441     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
1442     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
1443
1444     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
1445     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1446
1447     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1448     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
1449
1450     for(i=0; i<2; i++)
1451     {
1452         if(i)
1453         {
1454             hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4|D3DTTFF_PROJECTED);
1455             ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
1456         }
1457
1458         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements[i], &vertex_declaration);
1459         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1460         hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1461         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1462
1463         hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader);
1464         ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1465         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader);
1466         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1467
1468         hr = IDirect3DDevice9_BeginScene(device);
1469         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1470
1471         if(!i)
1472             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1473         else
1474             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad_proj[0], sizeof(quad_proj[0]));
1475         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
1476
1477         hr = IDirect3DDevice9_EndScene(device);
1478         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1479
1480         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1481         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1482
1483         color = getPixelColor(device, 320-32, 240);
1484         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1485         color = getPixelColor(device, 320+32, 240);
1486         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1487         color = getPixelColor(device, 320, 240-32);
1488         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1489         color = getPixelColor(device, 320, 240+32);
1490         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1491
1492         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1493         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1494         IDirect3DPixelShader9_Release(pixel_shader);
1495
1496         hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1497         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1498         IDirect3DVertexDeclaration9_Release(vertex_declaration);
1499     }
1500
1501     /* clean up */
1502     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
1503     ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
1504
1505     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
1506     ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
1507
1508     for(i=0; i<2; i++)
1509     {
1510         hr = IDirect3DDevice9_SetTexture(device, i, NULL);
1511         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1512         IDirect3DCubeTexture9_Release(texture[i]);
1513     }
1514 }
1515
1516 static void z_range_test(IDirect3DDevice9 *device)
1517 {
1518     const struct vertex quad[] =
1519     {
1520         {-1.0f,  0.0f,   1.1f,                          0xffff0000},
1521         {-1.0f,  1.0f,   1.1f,                          0xffff0000},
1522         { 1.0f,  0.0f,  -1.1f,                          0xffff0000},
1523         { 1.0f,  1.0f,  -1.1f,                          0xffff0000},
1524     };
1525     const struct vertex quad2[] =
1526     {
1527         {-1.0f,  0.0f,   1.1f,                          0xff0000ff},
1528         {-1.0f,  1.0f,   1.1f,                          0xff0000ff},
1529         { 1.0f,  0.0f,  -1.1f,                          0xff0000ff},
1530         { 1.0f,  1.0f,  -1.1f,                          0xff0000ff},
1531     };
1532
1533     const struct tvertex quad3[] =
1534     {
1535         {    0,   240,   1.1f,  1.0,                    0xffffff00},
1536         {    0,   480,   1.1f,  1.0,                    0xffffff00},
1537         {  640,   240,  -1.1f,  1.0,                    0xffffff00},
1538         {  640,   480,  -1.1f,  1.0,                    0xffffff00},
1539     };
1540     const struct tvertex quad4[] =
1541     {
1542         {    0,   240,   1.1f,  1.0,                    0xff00ff00},
1543         {    0,   480,   1.1f,  1.0,                    0xff00ff00},
1544         {  640,   240,  -1.1f,  1.0,                    0xff00ff00},
1545         {  640,   480,  -1.1f,  1.0,                    0xff00ff00},
1546     };
1547     HRESULT hr;
1548     DWORD color;
1549     IDirect3DVertexShader9 *shader;
1550     IDirect3DVertexDeclaration9 *decl;
1551     D3DCAPS9 caps;
1552     const DWORD shader_code[] = {
1553         0xfffe0101,                                     /* vs_1_1           */
1554         0x0000001f, 0x80000000, 0x900f0000,             /* dcl_position v0  */
1555         0x00000001, 0xc00f0000, 0x90e40000,             /* mov oPos, v0     */
1556         0x00000001, 0xd00f0000, 0xa0e40000,             /* mov oD0, c0      */
1557         0x0000ffff                                      /* end              */
1558     };
1559     static const D3DVERTEXELEMENT9 decl_elements[] = {
1560         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1561         D3DDECL_END()
1562     };
1563     /* Does the Present clear the depth stencil? Clear the depth buffer with some value != 0,
1564      * then call Present. Then clear the color buffer to make sure it has some defined content
1565      * after the Present with D3DSWAPEFFECT_DISCARD. After that draw a plane that is somewhere cut
1566      * by the depth value.
1567      */
1568     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.75, 0);
1569     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
1570     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1571     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4, 0);
1572
1573     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, TRUE);
1574     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1575     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
1576     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1577     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
1578     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1579     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
1580     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1581     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1582     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
1583
1584     hr = IDirect3DDevice9_BeginScene(device);
1585     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
1586     if(hr == D3D_OK)
1587     {
1588         /* Test the untransformed vertex path */
1589         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
1590         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1591         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS);
1592         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1593         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad2, sizeof(quad2[0]));
1594         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1595
1596         /* Test the transformed vertex path */
1597         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
1598         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
1599
1600         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad4, sizeof(quad4[0]));
1601         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1602         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
1603         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1604         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad3, sizeof(quad3[0]));
1605         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1606
1607         hr = IDirect3DDevice9_EndScene(device);
1608         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
1609     }
1610
1611     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1612     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1613
1614     /* Do not test the exact corner pixels, but go pretty close to them */
1615
1616     /* Clipped because z > 1.0 */
1617     color = getPixelColor(device, 28, 238);
1618     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1619     color = getPixelColor(device, 28, 241);
1620     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1621
1622     /* Not clipped, > z buffer clear value(0.75) */
1623     color = getPixelColor(device, 31, 238);
1624     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1625     color = getPixelColor(device, 31, 241);
1626     ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
1627     color = getPixelColor(device, 100, 238);
1628     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1629     color = getPixelColor(device, 100, 241);
1630     ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
1631
1632     /* Not clipped, < z buffer clear value */
1633     color = getPixelColor(device, 104, 238);
1634     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
1635     color = getPixelColor(device, 104, 241);
1636     ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color);
1637     color = getPixelColor(device, 318, 238);
1638     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
1639     color = getPixelColor(device, 318, 241);
1640     ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color);
1641
1642     /* Clipped because z < 0.0 */
1643     color = getPixelColor(device, 321, 238);
1644     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1645     color = getPixelColor(device, 321, 241);
1646     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1647
1648     /* Test the shader path */
1649     IDirect3DDevice9_GetDeviceCaps(device, &caps);
1650     if (caps.VertexShaderVersion < D3DVS_VERSION(1, 1)) {
1651         skip("Vertex shaders not supported\n");
1652         goto out;
1653     }
1654     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
1655     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
1656     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
1657     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
1658
1659     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4, 0);
1660
1661     IDirect3DDevice9_SetVertexDeclaration(device, decl);
1662     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
1663     IDirect3DDevice9_SetVertexShader(device, shader);
1664     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
1665
1666     hr = IDirect3DDevice9_BeginScene(device);
1667     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
1668     if(hr == D3D_OK)
1669     {
1670         float colorf[] = {1.0, 0.0, 0.0, 1.0};
1671         float colorf2[] = {0.0, 0.0, 1.0, 1.0};
1672         IDirect3DDevice9_SetVertexShaderConstantF(device, 0, colorf, 1);
1673         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
1674         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1675         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS);
1676         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1677         IDirect3DDevice9_SetVertexShaderConstantF(device, 0, colorf2, 1);
1678         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad2, sizeof(quad2[0]));
1679         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1680
1681         hr = IDirect3DDevice9_EndScene(device);
1682         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
1683     }
1684
1685     IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1686     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
1687     IDirect3DDevice9_SetVertexShader(device, NULL);
1688     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
1689
1690     IDirect3DVertexDeclaration9_Release(decl);
1691     IDirect3DVertexShader9_Release(shader);
1692
1693     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1694     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1695     /* Z < 1.0 */
1696     color = getPixelColor(device, 28, 238);
1697     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1698
1699     /* 1.0 < z < 0.75 */
1700     color = getPixelColor(device, 31, 238);
1701     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1702     color = getPixelColor(device, 100, 238);
1703     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1704
1705     /* 0.75 < z < 0.0 */
1706     color = getPixelColor(device, 104, 238);
1707     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
1708     color = getPixelColor(device, 318, 238);
1709     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
1710
1711     /* 0.0 < z */
1712     color = getPixelColor(device, 321, 238);
1713     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1714
1715     out:
1716     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
1717     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1718     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
1719     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1720     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
1721     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1722 }
1723
1724 static void fill_surface(IDirect3DSurface9 *surface, DWORD color)
1725 {
1726     D3DSURFACE_DESC desc;
1727     D3DLOCKED_RECT l;
1728     HRESULT hr;
1729     unsigned int x, y;
1730     DWORD *mem;
1731
1732     memset(&desc, 0, sizeof(desc));
1733     memset(&l, 0, sizeof(l));
1734     hr = IDirect3DSurface9_GetDesc(surface, &desc);
1735     ok(hr == D3D_OK, "IDirect3DSurface9_GetDesc failed with %s\n", DXGetErrorString9(hr));
1736     hr = IDirect3DSurface9_LockRect(surface, &l, NULL, 0);
1737     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed with %s\n", DXGetErrorString9(hr));
1738     if(FAILED(hr)) return;
1739
1740     for(y = 0; y < desc.Height; y++)
1741     {
1742         mem = (DWORD *) ((BYTE *) l.pBits + y * l.Pitch);
1743         for(x = 0; x < l.Pitch / sizeof(DWORD); x++)
1744         {
1745             mem[x] = color;
1746         }
1747     }
1748     hr = IDirect3DSurface9_UnlockRect(surface);
1749     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed with %s\n", DXGetErrorString9(hr));
1750 }
1751
1752 static void maxmip_test(IDirect3DDevice9 *device)
1753 {
1754     IDirect3DTexture9 *texture = NULL;
1755     IDirect3DSurface9 *surface = NULL;
1756     HRESULT hr;
1757     DWORD color;
1758     const float quads[] = {
1759         -1.0,   -1.0,   0.0,    0.0,    0.0,
1760         -1.0,    0.0,   0.0,    0.0,    1.0,
1761          0.0,   -1.0,   0.0,    1.0,    0.0,
1762          0.0,    0.0,   0.0,    1.0,    1.0,
1763
1764          0.0,   -1.0,   0.0,    0.0,    0.0,
1765          0.0,    0.0,   0.0,    0.0,    1.0,
1766          1.0,   -1.0,   0.0,    1.0,    0.0,
1767          1.0,    0.0,   0.0,    1.0,    1.0,
1768
1769          0.0,    0.0,   0.0,    0.0,    0.0,
1770          0.0,    1.0,   0.0,    0.0,    1.0,
1771          1.0,    0.0,   0.0,    1.0,    0.0,
1772          1.0,    1.0,   0.0,    1.0,    1.0,
1773
1774         -1.0,    0.0,   0.0,    0.0,    0.0,
1775         -1.0,    1.0,   0.0,    0.0,    1.0,
1776          0.0,    0.0,   0.0,    1.0,    0.0,
1777          0.0,    1.0,   0.0,    1.0,    1.0,
1778     };
1779
1780     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
1781     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
1782
1783     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
1784                                         &texture, NULL);
1785     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %s\n", DXGetErrorString9(hr));
1786     if(!texture)
1787     {
1788         skip("Failed to create test texture\n");
1789         return;
1790     }
1791
1792     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
1793     fill_surface(surface, 0xffff0000);
1794     IDirect3DSurface9_Release(surface);
1795     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface);
1796     fill_surface(surface, 0xff00ff00);
1797     IDirect3DSurface9_Release(surface);
1798     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
1799     fill_surface(surface, 0xff0000ff);
1800     IDirect3DSurface9_Release(surface);
1801
1802     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
1803     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
1804     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
1805     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
1806
1807     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
1808     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1809
1810     hr = IDirect3DDevice9_BeginScene(device);
1811     if(SUCCEEDED(hr))
1812     {
1813         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
1814         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1815         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[ 0], 5 * sizeof(float));
1816         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1817
1818         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
1819         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1820         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[20], 5 * sizeof(float));
1821         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1822
1823         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
1824         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1825         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[40], 5 * sizeof(float));
1826         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1827
1828         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
1829         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1830         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[60], 5 * sizeof(float));
1831         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1832         hr = IDirect3DDevice9_EndScene(device);
1833     }
1834
1835     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1836     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1837     /* With mipmapping disabled, the max mip level is ignored, only level 0 is used */
1838     color = getPixelColor(device, 160, 360);
1839     ok(color == 0x00FF0000, "MapMip 0, no mipfilter has color %08x\n", color);
1840     color = getPixelColor(device, 160, 120);
1841     ok(color == 0x00FF0000, "MapMip 3, no mipfilter has color %08x\n", color);
1842     color = getPixelColor(device, 480, 120);
1843     ok(color == 0x00FF0000, "MapMip 2, no mipfilter has color %08x\n", color);
1844     color = getPixelColor(device, 480, 360);
1845     ok(color == 0x00FF0000, "MapMip 1, no mipfilter has color %08x\n", color);
1846
1847     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
1848     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
1849
1850     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
1851     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1852
1853     hr = IDirect3DDevice9_BeginScene(device);
1854     if(SUCCEEDED(hr))
1855     {
1856         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
1857         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1858         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[ 0], 5 * sizeof(float));
1859         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1860
1861         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
1862         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1863         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[20], 5 * sizeof(float));
1864         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1865
1866         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
1867         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1868         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[40], 5 * sizeof(float));
1869         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1870
1871         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
1872         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1873         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[60], 5 * sizeof(float));
1874         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1875         hr = IDirect3DDevice9_EndScene(device);
1876     }
1877
1878     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
1879     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1880     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
1881     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1882
1883     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1884     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1885     /* Max Mip level 0-2 sample from the specified texture level, Max Mip level 3(> levels in texture)
1886      * samples from the highest level in the texture(level 2)
1887      */
1888     color = getPixelColor(device, 160, 360);
1889     ok(color == 0x00FF0000, "MapMip 0, point mipfilter has color %08x\n", color);
1890     color = getPixelColor(device, 160, 120);
1891     ok(color == 0x000000FF, "MapMip 3, point mipfilter has color %08x\n", color);
1892     color = getPixelColor(device, 480, 120);
1893     ok(color == 0x000000FF, "MapMip 2, point mipfilter has color %08x\n", color);
1894     color = getPixelColor(device, 480, 360);
1895     ok(color == 0x0000FF00, "MapMip 1, point mipfilter has color %08x\n", color);
1896
1897     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1898     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
1899     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
1900     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1901     IDirect3DTexture9_Release(texture);
1902 }
1903
1904 static void release_buffer_test(IDirect3DDevice9 *device)
1905 {
1906     IDirect3DVertexBuffer9 *vb = NULL;
1907     IDirect3DIndexBuffer9 *ib = NULL;
1908     HRESULT hr;
1909     BYTE *data;
1910     long ref;
1911
1912     static const struct vertex quad[] = {
1913         {-1.0,      -1.0,       0.1,        0xffff0000},
1914         {-1.0,       1.0,       0.1,        0xffff0000},
1915         { 1.0,       1.0,       0.1,        0xffff0000},
1916
1917         {-1.0,      -1.0,       0.1,        0xff00ff00},
1918         {-1.0,       1.0,       0.1,        0xff00ff00},
1919         { 1.0,       1.0,       0.1,        0xff00ff00}
1920     };
1921     short indices[] = {3, 4, 5};
1922
1923     /* Index and vertex buffers should always be creatable */
1924     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1925                                               D3DPOOL_MANAGED, &vb, NULL);
1926     ok(hr == D3D_OK, "CreateVertexBuffer failed with %s\n", DXGetErrorString9(hr));
1927     if(!vb) {
1928         skip("Failed to create a vertex buffer\n");
1929         return;
1930     }
1931     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, NULL);
1932     ok(hr == D3D_OK, "IDirect3DDevice9_CreateIndexBuffer failed with %s\n", DXGetErrorString9(hr));
1933     if(!ib) {
1934         skip("Failed to create an index buffer\n");
1935         return;
1936     }
1937
1938     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), (void **) &data, 0);
1939     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
1940     memcpy(data, quad, sizeof(quad));
1941     hr = IDirect3DVertexBuffer9_Unlock(vb);
1942     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr));
1943
1944     hr = IDirect3DIndexBuffer9_Lock(ib, 0, sizeof(indices), (void **) &data, 0);
1945     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
1946     memcpy(data, indices, sizeof(indices));
1947     hr = IDirect3DIndexBuffer9_Unlock(ib);
1948     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr));
1949
1950     hr = IDirect3DDevice9_SetIndices(device, ib);
1951     ok(hr == D3D_OK, "IDirect3DIndexBuffer8_Unlock failed with %s\n", DXGetErrorString9(hr));
1952     hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad[0]));
1953     ok(hr == D3D_OK, "IDirect3DIndexBuffer8_Unlock failed with %s\n", DXGetErrorString9(hr));
1954     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1955     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
1956
1957     /* Now destroy the bound index buffer and draw again */
1958     ref = IDirect3DIndexBuffer9_Release(ib);
1959     ok(ref == 0, "Index Buffer reference count is %08ld\n", ref);
1960
1961     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
1962     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1963
1964     hr = IDirect3DDevice9_BeginScene(device);
1965     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1966     if(SUCCEEDED(hr))
1967     {
1968         /* Deliberately using minvertexindex = 0 and numVertices = 6 to prevent d3d from
1969          * making assumptions about the indices or vertices
1970          */
1971         hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 3, 3, 0, 1);
1972         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitive failed with %08x\n", hr);
1973         hr = IDirect3DDevice9_EndScene(device);
1974         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1975     }
1976
1977     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1978     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
1979
1980     hr = IDirect3DDevice9_SetIndices(device, NULL);
1981     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
1982     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
1983     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
1984
1985     /* Index buffer was already destroyed as part of the test */
1986     IDirect3DVertexBuffer9_Release(vb);
1987 }
1988
1989 static void float_texture_test(IDirect3DDevice9 *device)
1990 {
1991     IDirect3D9 *d3d = NULL;
1992     HRESULT hr;
1993     IDirect3DTexture9 *texture = NULL;
1994     D3DLOCKED_RECT lr;
1995     float *data;
1996     DWORD color;
1997     float quad[] = {
1998         -1.0,      -1.0,       0.1,     0.0,    0.0,
1999         -1.0,       1.0,       0.1,     0.0,    1.0,
2000          1.0,      -1.0,       0.1,     1.0,    0.0,
2001          1.0,       1.0,       0.1,     1.0,    1.0,
2002     };
2003
2004     memset(&lr, 0, sizeof(lr));
2005     IDirect3DDevice9_GetDirect3D(device, &d3d);
2006     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
2007                                      D3DRTYPE_TEXTURE, D3DFMT_R32F) != D3D_OK) {
2008         skip("D3DFMT_R32F textures not supported\n");
2009         goto out;
2010     }
2011
2012     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_R32F,
2013                                         D3DPOOL_MANAGED, &texture, NULL);
2014     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %s\n", DXGetErrorString9(hr));
2015     if(!texture) {
2016         skip("Failed to create R32F texture\n");
2017         goto out;
2018     }
2019
2020     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
2021     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %s\n", DXGetErrorString9(hr));
2022     data = lr.pBits;
2023     *data = 0.0;
2024     hr = IDirect3DTexture9_UnlockRect(texture, 0);
2025     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %s\n", DXGetErrorString9(hr));
2026
2027     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
2028     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
2029
2030     hr = IDirect3DDevice9_BeginScene(device);
2031     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
2032     if(SUCCEEDED(hr))
2033     {
2034         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2035         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2036
2037         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
2038         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2039
2040         hr = IDirect3DDevice9_EndScene(device);
2041         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
2042     }
2043     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
2044     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
2045
2046     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2047     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2048
2049     color = getPixelColor(device, 240, 320);
2050     ok(color == 0x0000FFFF, "R32F with value 0.0 has color %08x, expected 0x0000FFFF\n", color);
2051
2052 out:
2053     if(texture) IDirect3DTexture9_Release(texture);
2054     IDirect3D9_Release(d3d);
2055 }
2056
2057 static void texture_transform_flags_test(IDirect3DDevice9 *device)
2058 {
2059     HRESULT hr;
2060     IDirect3D9 *d3d;
2061     D3DFORMAT fmt = D3DFMT_X8R8G8B8;
2062     D3DCAPS9 caps;
2063     IDirect3DTexture9 *texture = NULL;
2064     IDirect3DVolumeTexture9 *volume = NULL;
2065     unsigned int x, y, z;
2066     D3DLOCKED_RECT lr;
2067     D3DLOCKED_BOX lb;
2068     DWORD color;
2069     IDirect3DVertexDeclaration9 *decl, *decl2;
2070     float identity[16] = {1.0, 0.0, 0.0, 0.0,
2071                            0.0, 1.0, 0.0, 0.0,
2072                            0.0, 0.0, 1.0, 0.0,
2073                            0.0, 0.0, 0.0, 1.0};
2074     static const D3DVERTEXELEMENT9 decl_elements[] = {
2075         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2076         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
2077         D3DDECL_END()
2078     };
2079     static const D3DVERTEXELEMENT9 decl_elements2[] = {
2080         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2081         {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
2082         D3DDECL_END()
2083     };
2084
2085     memset(&lr, 0, sizeof(lr));
2086     memset(&lb, 0, sizeof(lb));
2087     IDirect3DDevice9_GetDirect3D(device, &d3d);
2088     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
2089                                      D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16) == D3D_OK) {
2090         fmt = D3DFMT_A16B16G16R16;
2091     }
2092     IDirect3D9_Release(d3d);
2093
2094     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
2095     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
2096     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements2, &decl2);
2097     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
2098     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, FALSE);
2099     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_SRGBTEXTURE) returned %s\n", DXGetErrorString9(hr));
2100     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
2101     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MAGFILTER) returned %s\n", DXGetErrorString9(hr));
2102     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
2103     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MINFILTER) returned %s\n", DXGetErrorString9(hr));
2104     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
2105     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MIPFILTER) returned %s\n", DXGetErrorString9(hr));
2106     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
2107     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSU) returned %s\n", DXGetErrorString9(hr));
2108     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
2109     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSV) returned %s\n", DXGetErrorString9(hr));
2110     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP);
2111     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSW) returned %s\n", DXGetErrorString9(hr));
2112     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
2113     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState(D3DRS_LIGHTING) returned %s\n", DXGetErrorString9(hr));
2114     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
2115     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
2116
2117     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
2118     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %s\n", DXGetErrorString9(hr));
2119     hr = IDirect3DDevice9_CreateTexture(device, caps.MaxTextureWidth, caps.MaxTextureHeight, 1,
2120                                         0, fmt, D3DPOOL_MANAGED, &texture, NULL);
2121     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %s\n", DXGetErrorString9(hr));
2122     if(!texture) {
2123         skip("Failed to create the test texture\n");
2124         return;
2125     }
2126
2127     /* Unfortunately there is no easy way to set up a texture coordinate passthrough
2128      * in d3d fixed function pipeline, so create a texture that has a gradient from 0.0 to
2129      * 1.0 in red and green for the x and y coords
2130      */
2131     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
2132     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %s\n", DXGetErrorString9(hr));
2133     for(y = 0; y < caps.MaxTextureHeight; y++) {
2134         for(x = 0; x < caps.MaxTextureWidth; x++) {
2135             double r_f = (double) y / (double) caps.MaxTextureHeight;
2136             double g_f = (double) x / (double) caps.MaxTextureWidth;
2137             if(fmt == D3DFMT_A16B16G16R16) {
2138                 unsigned short r, g;
2139                 unsigned short *dst = (unsigned short *) (((char *) lr.pBits) + y * lr.Pitch + x * 8);
2140                 r = (unsigned short) (r_f * 65536.0);
2141                 g = (unsigned short) (g_f * 65536.0);
2142                 dst[0] = r;
2143                 dst[1] = g;
2144                 dst[2] = 0;
2145                 dst[3] = 65535;
2146             } else {
2147                 unsigned char *dst = ((unsigned char *) lr.pBits) + y * lr.Pitch + x * 4;
2148                 unsigned char r = (unsigned char) (r_f * 255.0);
2149                 unsigned char g = (unsigned char) (g_f * 255.0);
2150                 dst[0] = 0;
2151                 dst[1] = g;
2152                 dst[2] = r;
2153                 dst[3] = 255;
2154             }
2155         }
2156     }
2157     hr = IDirect3DTexture9_UnlockRect(texture, 0);
2158     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect returned %s\n", DXGetErrorString9(hr));
2159     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
2160     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
2161
2162     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2163     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2164     hr = IDirect3DDevice9_BeginScene(device);
2165     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
2166     if(SUCCEEDED(hr))
2167     {
2168         float quad1[] = {
2169             -1.0,      -1.0,       0.1,     1.0,    1.0,
2170             -1.0,       0.0,       0.1,     1.0,    1.0,
2171              0.0,      -1.0,       0.1,     1.0,    1.0,
2172              0.0,       0.0,       0.1,     1.0,    1.0,
2173         };
2174         float quad2[] = {
2175             -1.0,       0.0,       0.1,     1.0,    1.0,
2176             -1.0,       1.0,       0.1,     1.0,    1.0,
2177              0.0,       0.0,       0.1,     1.0,    1.0,
2178              0.0,       1.0,       0.1,     1.0,    1.0,
2179         };
2180         float quad3[] = {
2181              0.0,       0.0,       0.1,     0.5,    0.5,
2182              0.0,       1.0,       0.1,     0.5,    0.5,
2183              1.0,       0.0,       0.1,     0.5,    0.5,
2184              1.0,       1.0,       0.1,     0.5,    0.5,
2185         };
2186         float quad4[] = {
2187              320,       480,       0.1,     1.0,    0.0,    1.0,
2188              320,       240,       0.1,     1.0,    0.0,    1.0,
2189              640,       480,       0.1,     1.0,    0.0,    1.0,
2190              640,       240,       0.1,     1.0,    0.0,    1.0,
2191         };
2192         float mat[16] = {0.0, 0.0, 0.0, 0.0,
2193                           0.0, 0.0, 0.0, 0.0,
2194                           0.0, 0.0, 0.0, 0.0,
2195                           0.0, 0.0, 0.0, 0.0};
2196
2197         /* What happens with the texture matrix if D3DTSS_TEXTURETRANSFORMFLAGS is disabled? */
2198         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
2199         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2200         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
2201         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2202
2203         /* What happens with transforms enabled? */
2204         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
2205         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2206         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
2207         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2208
2209         /* What happens if 4 coords are used, but only 2 given ?*/
2210         mat[8] = 1.0;
2211         mat[13] = 1.0;
2212         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
2213         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2214         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
2215         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2216         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
2217         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2218
2219         /* What happens with transformed geometry? This setup lead to 0/0 coords with untransformed
2220          * geometry. If the same applies to transformed vertices, the quad will be black, otherwise red,
2221          * due to the coords in the vertices. (turns out red, indeed)
2222          */
2223         memset(mat, 0, sizeof(mat));
2224         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
2225         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2226         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_TEX1);
2227         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
2228         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2229         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2230         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
2231         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2232
2233         hr = IDirect3DDevice9_EndScene(device);
2234         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
2235     }
2236     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2237     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2238     color = getPixelColor(device, 160, 360);
2239     ok(color == 0x00FFFF00 || color == 0x00FEFE00, "quad 1 has color %08x, expected 0x00FFFF00\n", color);
2240     color = getPixelColor(device, 160, 120);
2241     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
2242     color = getPixelColor(device, 480, 120);
2243     ok(color == 0x0000FF00 || color == 0x0000FE00, "quad 3 has color %08x, expected 0x0000FF00\n", color);
2244     color = getPixelColor(device, 480, 360);
2245     ok(color == 0x00FF0000 || 0x00FE0000, "quad 4 has color %08x, expected 0x00FF0000\n", color);
2246
2247     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
2248     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
2249
2250     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2251     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2252     hr = IDirect3DDevice9_BeginScene(device);
2253     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
2254     if(SUCCEEDED(hr))
2255     {
2256         float quad1[] = {
2257             -1.0,      -1.0,       0.1,     0.8,    0.2,
2258             -1.0,       0.0,       0.1,     0.8,    0.2,
2259              0.0,      -1.0,       0.1,     0.8,    0.2,
2260              0.0,       0.0,       0.1,     0.8,    0.2,
2261         };
2262         float quad2[] = {
2263             -1.0,       0.0,       0.1,     0.5,    1.0,
2264             -1.0,       1.0,       0.1,     0.5,    1.0,
2265              0.0,       0.0,       0.1,     0.5,    1.0,
2266              0.0,       1.0,       0.1,     0.5,    1.0,
2267         };
2268         float quad3[] = {
2269              0.0,       0.0,       0.1,     0.5,    1.0,
2270              0.0,       1.0,       0.1,     0.5,    1.0,
2271              1.0,       0.0,       0.1,     0.5,    1.0,
2272              1.0,       1.0,       0.1,     0.5,    1.0,
2273         };
2274         float quad4[] = {
2275              0.0,      -1.0,       0.1,     0.8,    0.2,
2276              0.0,       0.0,       0.1,     0.8,    0.2,
2277              1.0,      -1.0,       0.1,     0.8,    0.2,
2278              1.0,       0.0,       0.1,     0.8,    0.2,
2279         };
2280         float mat[16] = {0.0, 0.0, 0.0, 0.0,
2281                           0.0, 0.0, 0.0, 0.0,
2282                           0.0, 1.0, 0.0, 0.0,
2283                           0.0, 0.0, 0.0, 0.0};
2284
2285         /* What happens to the default 1 in the 3rd coordinate if it is disabled?
2286          */
2287         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
2288         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2289         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
2290         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2291
2292         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
2293         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2294
2295         /* What does this mean? Not sure... */
2296         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
2297         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2298         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 5 * sizeof(float));
2299         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2300
2301         /* Just to be sure, the same as quad2 above */
2302         memset(mat, 0, sizeof(mat));
2303         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
2304         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2305         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
2306         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2307         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
2308         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2309
2310         /* Now, what happens to the 2nd coordinate(that is disabled in the matrix) if it is not
2311          * used? And what happens to the first?
2312          */
2313         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
2314         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2315         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
2316         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2317
2318         hr = IDirect3DDevice9_EndScene(device);
2319         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
2320     }
2321     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2322     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2323     color = getPixelColor(device, 160, 360);
2324     ok(color == 0x00FF0000 || color == 0x00FE0000, "quad 1 has color %08x, expected 0x00FF0000\n", color);
2325     color = getPixelColor(device, 160, 120);
2326     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
2327     color = getPixelColor(device, 480, 120);
2328     ok(color == 0x00ff8000 || color == 0x00fe7f00, "quad 3 has color %08x, expected 0x00ff8000\n", color);
2329     color = getPixelColor(device, 480, 360);
2330     ok(color == 0x0033cc00 || color == 0x0032cb00, "quad 4 has color %08x, expected 0x0033cc00\n", color);
2331
2332     IDirect3DTexture9_Release(texture);
2333
2334     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff203040, 0.0, 0);
2335     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
2336     /* Use a smaller volume texture than the biggest possible size for memory and performance reasons
2337      * Thus watch out if sampling from texels between 0 and 1.
2338      */
2339     hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 32, 1, 0, fmt, D3DPOOL_MANAGED, &volume, 0);
2340     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
2341        "IDirect3DDevice9_CreateVolumeTexture failed with %s\n", DXGetErrorString9(hr));
2342     if(!volume) {
2343         skip("Failed to create a volume texture\n");
2344         goto out;
2345     }
2346
2347     hr = IDirect3DVolumeTexture9_LockBox(volume, 0, &lb, NULL, 0);
2348     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_LockBox failed with %s\n", DXGetErrorString9(hr));
2349     for(z = 0; z < 32; z++) {
2350         for(y = 0; y < 32; y++) {
2351             for(x = 0; x < 32; x++) {
2352                 char size = (fmt == D3DFMT_A16B16G16R16 ? 8 : 4);
2353                 void *mem = ((char *)  lb.pBits) + y * lb.RowPitch + z * lb.SlicePitch + x * size;
2354                 float r_f = (float) x / 31.0;
2355                 float g_f = (float) y / 31.0;
2356                 float b_f = (float) z / 31.0;
2357
2358                 if(fmt == D3DFMT_A16B16G16R16) {
2359                     unsigned short *mem_s = mem;
2360                     mem_s[0]  = r_f * 65535.0;
2361                     mem_s[1]  = g_f * 65535.0;
2362                     mem_s[2]  = b_f * 65535.0;
2363                     mem_s[3]  = 65535;
2364                 } else {
2365                     unsigned char *mem_c = mem;
2366                     mem_c[0]  = b_f * 255.0;
2367                     mem_c[1]  = g_f * 255.0;
2368                     mem_c[2]  = r_f * 255.0;
2369                     mem_c[3]  = 255;
2370                 }
2371             }
2372         }
2373     }
2374     hr = IDirect3DVolumeTexture9_UnlockBox(volume, 0);
2375     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %s\n", DXGetErrorString9(hr));
2376
2377     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) volume);
2378     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %s\n", DXGetErrorString9(hr));
2379
2380     hr = IDirect3DDevice9_BeginScene(device);
2381     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
2382     if(SUCCEEDED(hr))
2383     {
2384         float quad1[] = {
2385             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2386             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
2387              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2388              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
2389         };
2390         float quad2[] = {
2391             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
2392             -1.0,       1.0,       0.1,     1.0,    1.0,    1.0,
2393              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
2394              0.0,       1.0,       0.1,     1.0,    1.0,    1.0
2395         };
2396         float quad3[] = {
2397              0.0,       0.0,       0.1,     0.0,    0.0,
2398              0.0,       1.0,       0.1,     0.0,    0.0,
2399              1.0,       0.0,       0.1,     0.0,    0.0,
2400              1.0,       1.0,       0.1,     0.0,    0.0
2401         };
2402         float quad4[] = {
2403              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2404              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
2405              1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2406              1.0,       0.0,       0.1,     1.0,    1.0,    1.0
2407         };
2408         float mat[16] = {1.0, 0.0, 0.0, 0.0,
2409                           0.0, 0.0, 1.0, 0.0,
2410                           0.0, 1.0, 0.0, 0.0,
2411                           0.0, 0.0, 0.0, 1.0};
2412         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2413         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
2414
2415         /* Draw a quad with all 3 coords enabled. Nothing fancy. v and w are swapped, but have the same
2416          * values
2417          */
2418         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
2419         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2420         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
2421         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2422         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
2423         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2424
2425         /* Now disable the w coordinate. Does that change the input, or the output. The coordinates
2426          * are swapped by the matrix. If it changes the input, the v coord will be missing(green),
2427          * otherwise the w will be missing(blue).
2428          * turns out that the blue color is missing, so it is an output modification
2429          */
2430         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
2431         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2432         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
2433         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2434
2435         /* default values? Set up the identity matrix, pass in 2 vertex coords, and enable 4 */
2436         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
2437         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2438         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
2439         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2440         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2441         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2442         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
2443         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2444
2445         /* D3DTTFF_COUNT1. Set a NULL matrix, and count1, pass in all values as 1.0 */
2446         memset(mat, 0, sizeof(mat));
2447         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
2448         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2449         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
2450         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2451         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2452         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
2453         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
2454         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2455
2456         hr = IDirect3DDevice9_EndScene(device);
2457         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
2458     }
2459     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2460     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2461
2462     color = getPixelColor(device, 160, 360);
2463     ok(color == 0x00ffffff, "quad 1 has color %08x, expected 0x00ffffff\n", color);
2464     color = getPixelColor(device, 160, 120);
2465     ok(color == 0x00ffff00, "quad 2 has color %08x, expected 0x00ffff00\n", color);
2466     color = getPixelColor(device, 480, 120);
2467     ok(color == 0x000000ff, "quad 3 has color %08x, expected 0x000000ff\n", color);
2468     color = getPixelColor(device, 480, 360);
2469     ok(color == 0x00ffffff, "quad 4 has color %08x, expected 0x00ffffff\n", color);
2470
2471     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff303030, 0.0, 0);
2472     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
2473     hr = IDirect3DDevice9_BeginScene(device);
2474     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
2475     if(SUCCEEDED(hr))
2476     {
2477         float quad1[] = {
2478             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2479             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
2480              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2481              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
2482         };
2483         float quad2[] = {
2484             -1.0,       0.0,       0.1,
2485             -1.0,       1.0,       0.1,
2486              0.0,       0.0,       0.1,
2487              0.0,       1.0,       0.1,
2488         };
2489         float quad3[] = {
2490              0.0,       0.0,       0.1,     1.0,
2491              0.0,       1.0,       0.1,     1.0,
2492              1.0,       0.0,       0.1,     1.0,
2493              1.0,       1.0,       0.1,     1.0
2494         };
2495         float mat[16] =  {0.0, 0.0, 0.0, 0.0,
2496                            0.0, 0.0, 0.0, 0.0,
2497                            0.0, 0.0, 0.0, 0.0,
2498                            0.0, 1.0, 0.0, 0.0};
2499         float mat2[16] = {0.0, 0.0, 0.0, 1.0,
2500                            1.0, 0.0, 0.0, 0.0,
2501                            0.0, 1.0, 0.0, 0.0,
2502                            0.0, 0.0, 1.0, 0.0};
2503         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2504         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
2505
2506         /* Default values? 4 coords used, 3 passed. What happens to the 4th?
2507          */
2508         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
2509         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2510         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
2511         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2512         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
2513         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2514
2515         /* None passed */
2516         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
2517         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2518         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
2519         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2520         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
2521         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2522
2523         /* 4 used, 1 passed */
2524         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl2);
2525         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
2526         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat2);
2527         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2528         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 4 * sizeof(float));
2529         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2530
2531         hr = IDirect3DDevice9_EndScene(device);
2532         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
2533     }
2534     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2535     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2536     color = getPixelColor(device, 160, 360);
2537     ok(color == 0x0000ff00, "quad 1 has color %08x, expected 0x0000ff00\n", color);
2538     color = getPixelColor(device, 160, 120);
2539     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x00000000\n", color);
2540     color = getPixelColor(device, 480, 120);
2541     ok(color == 0x00ff0000, "quad 3 has color %08x, expected 0x00ff0000\n", color);
2542     /* Quad4: unused */
2543
2544     IDirect3DVolumeTexture9_Release(volume);
2545
2546     out:
2547     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2548     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
2549     IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
2550     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2551     hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &identity);
2552     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2553     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
2554     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
2555     IDirect3DVertexDeclaration9_Release(decl);
2556     IDirect3DVertexDeclaration9_Release(decl2);
2557 }
2558
2559 static void texdepth_test(IDirect3DDevice9 *device)
2560 {
2561     IDirect3DPixelShader9 *shader;
2562     HRESULT hr;
2563     const float texdepth_test_data1[] = { 0.25,  2.0, 0.0, 0.0};
2564     const float texdepth_test_data2[] = { 0.25,  0.5, 0.0, 0.0};
2565     const float texdepth_test_data3[] = {-1.00,  0.1, 0.0, 0.0};
2566     const float texdepth_test_data4[] = {-0.25, -0.5, 0.0, 0.0};
2567     const float texdepth_test_data5[] = { 1.00, -0.1, 0.0, 0.0};
2568     const float texdepth_test_data6[] = { 1.00,  0.5, 0.0, 0.0};
2569     const float texdepth_test_data7[] = { 0.50,  0.0, 0.0, 0.0};
2570     DWORD shader_code[] = {
2571         0xffff0104,                                                                 /* ps_1_4               */
2572         0x00000051, 0xa00f0001, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000,     /* def c1, 0, 0, 1, 1   */
2573         0x00000001, 0x800f0005, 0xa0e40000,                                         /* mov r5, c0           */
2574         0x0000fffd,                                                                 /* phase                */
2575         0x00000057, 0x800f0005,                                                     /* texdepth r5          */
2576         0x00000001, 0x800f0000, 0xa0e40001,                                         /* mov r0, c1           */
2577         0x0000ffff                                                                  /* end                  */
2578     };
2579     DWORD color;
2580     float vertex[] = {
2581        -1.0,   -1.0,    0.0,
2582         1.0,   -1.0,    1.0,
2583        -1.0,    1.0,    0.0,
2584         1.0,    1.0,    1.0
2585     };
2586
2587     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
2588     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
2589
2590     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffff00, 0.0, 0);
2591     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
2592     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
2593     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2594     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
2595     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2596     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
2597     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2598     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
2599
2600     /* Fill the depth buffer with a gradient */
2601     hr = IDirect3DDevice9_BeginScene(device);
2602     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2603     if(SUCCEEDED(hr))
2604     {
2605         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2606         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2607         hr = IDirect3DDevice9_EndScene(device);
2608         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2609     }
2610
2611     /* Now perform the actual tests. Same geometry, but with the shader */
2612     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
2613     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2614     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
2615     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2616     hr = IDirect3DDevice9_SetPixelShader(device, shader);
2617     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
2618
2619     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data1, 1);
2620     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
2621     hr = IDirect3DDevice9_BeginScene(device);
2622     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2623     if(SUCCEEDED(hr))
2624     {
2625         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2626         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2627
2628         hr = IDirect3DDevice9_EndScene(device);
2629         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2630     }
2631
2632     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2633     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2634     color = getPixelColor(device, 158, 240);
2635     ok(color == 0x000000ff, "Pixel 158(25%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
2636     color = getPixelColor(device, 162, 240);
2637     ok(color == 0x00ffffff, "Pixel 158(25%% + 2 pixel) has color %08x, expected 0x00ffffff\n", color);
2638
2639     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
2640
2641     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data2, 1);
2642     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
2643     hr = IDirect3DDevice9_BeginScene(device);
2644     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2645     if(SUCCEEDED(hr))
2646     {
2647         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2648         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2649
2650         hr = IDirect3DDevice9_EndScene(device);
2651         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2652     }
2653
2654     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2655     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2656     color = getPixelColor(device, 318, 240);
2657     ok(color == 0x000000ff, "Pixel 318(50%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
2658     color = getPixelColor(device, 322, 240);
2659     ok(color == 0x00ffff00, "Pixel 322(50%% + 2 pixel) has color %08x, expected 0x00ffff00\n", color);
2660
2661     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
2662
2663     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data3, 1);
2664     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
2665     hr = IDirect3DDevice9_BeginScene(device);
2666     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2667     if(SUCCEEDED(hr))
2668     {
2669         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2670         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2671
2672         hr = IDirect3DDevice9_EndScene(device);
2673         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2674     }
2675     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2676     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2677
2678     color = getPixelColor(device, 1, 240);
2679     ok(color == 0x00ff0000, "Pixel 1(0%% + 2 pixel) has color %08x, expected 0x00ff0000\n", color);
2680
2681     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
2682
2683     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data4, 1);
2684     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
2685     hr = IDirect3DDevice9_BeginScene(device);
2686     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2687     if(SUCCEEDED(hr))
2688     {
2689         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2690         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2691
2692         hr = IDirect3DDevice9_EndScene(device);
2693         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2694     }
2695     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2696     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2697     color = getPixelColor(device, 318, 240);
2698     ok(color == 0x000000ff, "Pixel 318(50%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
2699     color = getPixelColor(device, 322, 240);
2700     ok(color == 0x0000ff00, "Pixel 322(50%% + 2 pixel) has color %08x, expected 0x0000ff00\n", color);
2701
2702     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
2703
2704     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data5, 1);
2705     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
2706     hr = IDirect3DDevice9_BeginScene(device);
2707     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2708     if(SUCCEEDED(hr))
2709     {
2710         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2711         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2712
2713         hr = IDirect3DDevice9_EndScene(device);
2714         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2715     }
2716     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2717     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2718
2719     color = getPixelColor(device, 1, 240);
2720     ok(color == 0x00ffff00, "Pixel 1(0%% + 2 pixel) has color %08x, expected 0x00ffff00\n", color);
2721
2722     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
2723
2724     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data6, 1);
2725     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
2726     hr = IDirect3DDevice9_BeginScene(device);
2727     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2728     if(SUCCEEDED(hr))
2729     {
2730         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2731         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2732
2733         hr = IDirect3DDevice9_EndScene(device);
2734         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2735     }
2736     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2737     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2738
2739     color = getPixelColor(device, 638, 240);
2740     ok(color == 0x000000ff, "Pixel 638(100%% + 2 pixel) has color %08x, expected 0x000000ff\n", color);
2741
2742     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
2743
2744     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data7, 1);
2745     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
2746     hr = IDirect3DDevice9_BeginScene(device);
2747     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2748     if(SUCCEEDED(hr))
2749     {
2750         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2751         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2752
2753         hr = IDirect3DDevice9_EndScene(device);
2754         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2755     }
2756     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2757     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2758
2759     color = getPixelColor(device, 638, 240);
2760     ok(color == 0x000000ff, "Pixel 638(100%% + 2 pixel) has color %08x, expected 0x000000ff\n", color);
2761
2762     /* Cleanup */
2763     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
2764     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
2765     IDirect3DPixelShader9_Release(shader);
2766
2767     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
2768     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2769     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
2770     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2771 }
2772
2773 static void texkill_test(IDirect3DDevice9 *device)
2774 {
2775     IDirect3DPixelShader9 *shader;
2776     HRESULT hr;
2777     DWORD color;
2778
2779     const float vertex[] = {
2780     /*                          bottom  top    right    left */
2781         -1.0,   -1.0,   1.0,   -0.1,    0.9,    0.9,   -0.1,
2782          1.0,   -1.0,   0.0,    0.9,   -0.1,    0.9,   -0.1,
2783         -1.0,    1.0,   1.0,   -0.1,    0.9,   -0.1,    0.9,
2784          1.0,    1.0,   0.0,    0.9,   -0.1,   -0.1,    0.9,
2785     };
2786
2787     DWORD shader_code_11[] = {
2788     0xffff0101,                                                             /* ps_1_1                     */
2789     0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0 */
2790     0x00000041, 0xb00f0000,                                                 /* texkill t0                 */
2791     0x00000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                 */
2792     0x0000ffff                                                              /* end                        */
2793     };
2794     DWORD shader_code_20[] = {
2795     0xffff0200,                                                             /* ps_2_0                     */
2796     0x0200001f, 0x80000000, 0xb00f0000,                                     /* dcl t0                     */
2797     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c0, 0.0, 0.0, 1.0, 1.0 */
2798     0x01000041, 0xb00f0000,                                                 /* texkill t0                 */
2799     0x02000001, 0x800f0800, 0xa0e40000,                                     /* mov oC0, c0                */
2800     0x0000ffff                                                              /* end                        */
2801     };
2802
2803     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
2804     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
2805     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader);
2806     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
2807
2808     hr = IDirect3DDevice9_SetPixelShader(device, shader);
2809     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
2810     hr = IDirect3DDevice9_BeginScene(device);
2811     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2812     if(SUCCEEDED(hr))
2813     {
2814         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1);
2815         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
2816         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 7 * sizeof(float));
2817         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2818         hr = IDirect3DDevice9_EndScene(device);
2819         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2820     }
2821     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2822     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2823     color = getPixelColor(device, 63, 46);
2824     ok(color == 0x0000ff00, "Pixel 63/46 has color %08x, expected 0x0000ff00\n", color);
2825     color = getPixelColor(device, 66, 46);
2826     ok(color == 0x0000ff00, "Pixel 66/64 has color %08x, expected 0x0000ff00\n", color);
2827     color = getPixelColor(device, 63, 49);
2828     ok(color == 0x0000ff00, "Pixel 63/49 has color %08x, expected 0x0000ff00\n", color);
2829     color = getPixelColor(device, 66, 49);
2830     ok(color == 0x00ff0000, "Pixel 66/49 has color %08x, expected 0x00ff0000\n", color);
2831
2832     color = getPixelColor(device, 578, 46);
2833     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
2834     color = getPixelColor(device, 575, 46);
2835     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
2836     color = getPixelColor(device, 578, 49);
2837     ok(color == 0x0000ff00, "Pixel 578/49 has color %08x, expected 0x0000ff00\n", color);
2838     color = getPixelColor(device, 575, 49);
2839     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
2840
2841     color = getPixelColor(device, 63, 430);
2842     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
2843     color = getPixelColor(device, 63, 433);
2844     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
2845     color = getPixelColor(device, 66, 433);
2846     ok(color == 0x00ff0000, "Pixel 578/49 has color %08x, expected 0x00ff0000\n", color);
2847     color = getPixelColor(device, 66, 430);
2848     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
2849
2850     color = getPixelColor(device, 578, 430);
2851     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
2852     color = getPixelColor(device, 578, 433);
2853     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
2854     color = getPixelColor(device, 575, 433);
2855     ok(color == 0x00ff0000, "Pixel 578/49 has color %08x, expected 0x00ff0000\n", color);
2856     color = getPixelColor(device, 575, 430);
2857     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
2858
2859     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
2860     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
2861     IDirect3DPixelShader9_Release(shader);
2862
2863     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
2864     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
2865     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_20, &shader);
2866     if(FAILED(hr)) {
2867         skip("Failed to create 2.0 test shader, most likely not supported\n");
2868         return;
2869     }
2870
2871     hr = IDirect3DDevice9_SetPixelShader(device, shader);
2872     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
2873     hr = IDirect3DDevice9_BeginScene(device);
2874     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2875     if(SUCCEEDED(hr))
2876     {
2877         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 7 * sizeof(float));
2878         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2879         hr = IDirect3DDevice9_EndScene(device);
2880         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2881     }
2882     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2883
2884     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2885     color = getPixelColor(device, 63, 46);
2886     ok(color == 0x00ffff00, "Pixel 63/46 has color %08x, expected 0x00ffff00\n", color);
2887     color = getPixelColor(device, 66, 46);
2888     ok(color == 0x00ffff00, "Pixel 66/64 has color %08x, expected 0x00ffff00\n", color);
2889     color = getPixelColor(device, 63, 49);
2890     ok(color == 0x00ffff00, "Pixel 63/49 has color %08x, expected 0x00ffff00\n", color);
2891     color = getPixelColor(device, 66, 49);
2892     ok(color == 0x000000ff, "Pixel 66/49 has color %08x, expected 0x000000ff\n", color);
2893
2894     color = getPixelColor(device, 578, 46);
2895     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
2896     color = getPixelColor(device, 575, 46);
2897     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
2898     color = getPixelColor(device, 578, 49);
2899     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
2900     color = getPixelColor(device, 575, 49);
2901     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
2902
2903     color = getPixelColor(device, 63, 430);
2904     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
2905     color = getPixelColor(device, 63, 433);
2906     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
2907     color = getPixelColor(device, 66, 433);
2908     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
2909     color = getPixelColor(device, 66, 430);
2910     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
2911
2912     color = getPixelColor(device, 578, 430);
2913     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
2914     color = getPixelColor(device, 578, 433);
2915     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
2916     color = getPixelColor(device, 575, 433);
2917     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
2918     color = getPixelColor(device, 575, 430);
2919     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
2920
2921     /* Cleanup */
2922     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
2923     ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
2924     IDirect3DPixelShader9_Release(shader);
2925 }
2926
2927 static void x8l8v8u8_test(IDirect3DDevice9 *device)
2928 {
2929     IDirect3D9 *d3d9;
2930     HRESULT hr;
2931     IDirect3DTexture9 *texture;
2932     IDirect3DPixelShader9 *shader;
2933     IDirect3DPixelShader9 *shader2;
2934     D3DLOCKED_RECT lr;
2935     DWORD color;
2936     DWORD shader_code[] = {
2937         0xffff0101,                             /* ps_1_1       */
2938         0x00000042, 0xb00f0000,                 /* tex t0       */
2939         0x00000001, 0x800f0000, 0xb0e40000,     /* mov r0, t0   */
2940         0x0000ffff                              /* end          */
2941     };
2942     DWORD shader_code2[] = {
2943         0xffff0101,                             /* ps_1_1       */
2944         0x00000042, 0xb00f0000,                 /* tex t0       */
2945         0x00000001, 0x800f0000, 0xb0ff0000,     /* mov r0, t0.w */
2946         0x0000ffff                              /* end          */
2947     };
2948
2949     float quad[] = {
2950        -1.0,   -1.0,   0.1,     0.5,    0.5,
2951         1.0,   -1.0,   0.1,     0.5,    0.5,
2952        -1.0,    1.0,   0.1,     0.5,    0.5,
2953         1.0,    1.0,   0.1,     0.5,    0.5,
2954     };
2955
2956     memset(&lr, 0, sizeof(lr));
2957     IDirect3DDevice9_GetDirect3D(device, &d3d9);
2958     hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
2959                                       0,  D3DRTYPE_TEXTURE, D3DFMT_X8L8V8U8);
2960     IDirect3D9_Release(d3d9);
2961     if(FAILED(hr)) {
2962         skip("No D3DFMT_X8L8V8U8 support\n");
2963     };
2964
2965     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
2966     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
2967
2968     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_X8L8V8U8, D3DPOOL_MANAGED, &texture, NULL);
2969     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed (%08x)\n", hr);
2970     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
2971     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed (%08x)\n", hr);
2972     *((DWORD *) lr.pBits) = 0x11ca3141;
2973     hr = IDirect3DTexture9_UnlockRect(texture, 0);
2974     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed (%08x)\n", hr);
2975
2976     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
2977     ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr);
2978     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code2, &shader2);
2979     ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr);
2980
2981     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2982     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed (%08x)\n", hr);
2983     hr = IDirect3DDevice9_SetPixelShader(device, shader);
2984     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
2985     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
2986     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
2987
2988     hr = IDirect3DDevice9_BeginScene(device);
2989     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
2990     if(SUCCEEDED(hr))
2991     {
2992         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
2993         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2994
2995         hr = IDirect3DDevice9_EndScene(device);
2996         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
2997     }
2998     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2999     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3000     color = getPixelColor(device, 578, 430);
3001     ok(color == 0x008262ca || color == 0x008363ca, "D3DFMT_X8L8V8U8 = 0x112131ca returns color %08x, expected 0x008262ca\n", color);
3002
3003     hr = IDirect3DDevice9_SetPixelShader(device, shader2);
3004     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
3005     hr = IDirect3DDevice9_BeginScene(device);
3006     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
3007     if(SUCCEEDED(hr))
3008     {
3009         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
3010         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3011
3012         hr = IDirect3DDevice9_EndScene(device);
3013         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
3014     }
3015     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3016     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3017     color = getPixelColor(device, 578, 430);
3018     ok(color == 0x00ffffff, "w component of D3DFMT_X8L8V8U8 = 0x11ca3141 returns color %08x\n", color);
3019
3020     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
3021     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
3022     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3023     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
3024     IDirect3DPixelShader9_Release(shader);
3025     IDirect3DPixelShader9_Release(shader2);
3026     IDirect3DTexture9_Release(texture);
3027 }
3028
3029 static void autogen_mipmap_test(IDirect3DDevice9 *device)
3030 {
3031     HRESULT hr;
3032     IDirect3D9 *d3d;
3033     IDirect3DTexture9 *texture = NULL;
3034     IDirect3DSurface9 *surface;
3035     DWORD color;
3036     const RECT r1 = {256, 256, 512, 512};
3037     const RECT r2 = {512, 256, 768, 512};
3038     const RECT r3 = {256, 512, 512, 768};
3039     const RECT r4 = {512, 512, 768, 768};
3040     unsigned int x, y;
3041     D3DLOCKED_RECT lr;
3042     memset(&lr, 0, sizeof(lr));
3043
3044     IDirect3DDevice9_GetDirect3D(device, &d3d);
3045     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
3046        D3DUSAGE_AUTOGENMIPMAP,  D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8) != D3D_OK) {
3047         skip("No autogenmipmap support\n");
3048         IDirect3D9_Release(d3d);
3049         return;
3050     }
3051     IDirect3D9_Release(d3d);
3052
3053     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
3054     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
3055
3056     /* Make the mipmap big, so that a smaller mipmap is used
3057      */
3058     hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 0, D3DUSAGE_AUTOGENMIPMAP,
3059                                         D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
3060     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %s\n", DXGetErrorString9(hr));
3061
3062     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
3063     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel returned %s\n", DXGetErrorString9(hr));
3064     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
3065     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %s\n", DXGetErrorString9(hr));
3066     for(y = 0; y < 1024; y++) {
3067         for(x = 0; x < 1024; x++) {
3068             DWORD *dst = (DWORD *) (((BYTE *) lr.pBits) + y * lr.Pitch + x * 4);
3069             POINT pt;
3070
3071             pt.x = x;
3072             pt.y = y;
3073             if(PtInRect(&r1, pt)) {
3074                 *dst = 0xffff0000;
3075             } else if(PtInRect(&r2, pt)) {
3076                 *dst = 0xff00ff00;
3077             } else if(PtInRect(&r3, pt)) {
3078                 *dst = 0xff0000ff;
3079             } else if(PtInRect(&r4, pt)) {
3080                 *dst = 0xff000000;
3081             } else {
3082                 *dst = 0xffffffff;
3083             }
3084         }
3085     }
3086     hr = IDirect3DSurface9_UnlockRect(surface);
3087     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect returned %s\n", DXGetErrorString9(hr));
3088     IDirect3DSurface9_Release(surface);
3089
3090     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3091     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
3092     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
3093     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
3094
3095     hr = IDirect3DDevice9_BeginScene(device);
3096     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
3097     if(SUCCEEDED(hr)) {
3098         const float quad[] =  {
3099            -0.5,   -0.5,    0.1,    0.0,    0.0,
3100            -0.5,    0.5,    0.1,    0.0,    1.0,
3101             0.5,   -0.5,    0.1,    1.0,    0.0,
3102             0.5,    0.5,    0.1,    1.0,    1.0
3103         };
3104
3105         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3106         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
3107         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
3108         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3109         hr = IDirect3DDevice9_EndScene(device);
3110         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3111     }
3112     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3113     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
3114     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
3115     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
3116     IDirect3DTexture9_Release(texture);
3117
3118     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3119     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3120     color = getPixelColor(device, 200, 200);
3121     ok(color == 0x00ffffff, "pixel 200/200 has color %08x, expected 0x00ffffff\n", color);
3122     color = getPixelColor(device, 280, 200);
3123     ok(color == 0x000000ff, "pixel 280/200 has color %08x, expected 0x000000ff\n", color);
3124     color = getPixelColor(device, 360, 200);
3125     ok(color == 0x00000000, "pixel 360/200 has color %08x, expected 0x00000000\n", color);
3126     color = getPixelColor(device, 440, 200);
3127     ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
3128     color = getPixelColor(device, 200, 270);
3129     ok(color == 0x00ffffff, "pixel 200/270 has color %08x, expected 0x00ffffff\n", color);
3130     color = getPixelColor(device, 280, 270);
3131     ok(color == 0x00ff0000, "pixel 280/270 has color %08x, expected 0x00ff0000\n", color);
3132     color = getPixelColor(device, 360, 270);
3133     ok(color == 0x0000ff00, "pixel 360/270 has color %08x, expected 0x0000ff00\n", color);
3134     color = getPixelColor(device, 440, 270);
3135     ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
3136 }
3137
3138 static void test_constant_clamp_vs(IDirect3DDevice9 *device)
3139 {
3140     IDirect3DVertexShader9 *shader_11, *shader_11_2, *shader_20, *shader_20_2;
3141     IDirect3DVertexDeclaration9 *decl;
3142     HRESULT hr;
3143     DWORD color;
3144     DWORD shader_code_11[] =  {
3145         0xfffe0101,                                         /* vs_1_1           */
3146         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
3147         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
3148         0x00000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
3149         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
3150         0x0000ffff                                          /* end              */
3151     };
3152     DWORD shader_code_11_2[] =  {
3153         0xfffe0101,                                         /* vs_1_1           */
3154         0x00000051, 0xa00f0001, 0x3fa00000, 0xbf000000, 0xbfc00000, 0x3f800000, /* dcl ... */
3155         0x00000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000, /* dcl ... */
3156         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
3157         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
3158         0x00000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
3159         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
3160         0x0000ffff                                          /* end              */
3161     };
3162     DWORD shader_code_20[] =  {
3163         0xfffe0200,                                         /* vs_2_0           */
3164         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
3165         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
3166         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
3167         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
3168         0x0000ffff                                          /* end              */
3169     };
3170     DWORD shader_code_20_2[] =  {
3171         0xfffe0200,                                         /* vs_2_0           */
3172         0x05000051, 0xa00f0001, 0x3fa00000, 0xbf000000, 0xbfc00000, 0x3f800000,
3173         0x05000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000,
3174         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
3175         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
3176         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
3177         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
3178         0x0000ffff                                          /* end              */
3179     };
3180     static const D3DVERTEXELEMENT9 decl_elements[] = {
3181         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3182         D3DDECL_END()
3183     };
3184     float quad1[] = {
3185         -1.0,   -1.0,   0.1,
3186          0.0,   -1.0,   0.1,
3187         -1.0,    0.0,   0.1,
3188          0.0,    0.0,   0.1
3189     };
3190     float quad2[] = {
3191          0.0,   -1.0,   0.1,
3192          1.0,   -1.0,   0.1,
3193          0.0,    0.0,   0.1,
3194          1.0,    0.0,   0.1
3195     };
3196     float quad3[] = {
3197          0.0,    0.0,   0.1,
3198          1.0,    0.0,   0.1,
3199          0.0,    1.0,   0.1,
3200          1.0,    1.0,   0.1
3201     };
3202     float quad4[] = {
3203         -1.0,    0.0,   0.1,
3204          0.0,    0.0,   0.1,
3205         -1.0,    1.0,   0.1,
3206          0.0,    1.0,   0.1
3207     };
3208     float test_data_c1[4] = {  1.25, -0.50, -1.50, 1.0};
3209     float test_data_c2[4] = { -0.50,  1.25,  2.00, 1.0};
3210
3211     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
3212     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
3213
3214     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_11, &shader_11);
3215     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
3216     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_11_2, &shader_11_2);
3217     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
3218     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_20, &shader_20);
3219     if(FAILED(hr)) shader_20 = NULL;
3220     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_20_2, &shader_20_2);
3221     if(FAILED(hr)) shader_20_2 = NULL;
3222     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
3223     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
3224
3225     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, test_data_c1, 1);
3226     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned %s\n", DXGetErrorString9(hr));
3227     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 2, test_data_c2, 1);
3228     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned %s\n", DXGetErrorString9(hr));
3229     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3230     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
3231
3232     hr = IDirect3DDevice9_BeginScene(device);
3233     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
3234     if(SUCCEEDED(hr))
3235     {
3236         hr = IDirect3DDevice9_SetVertexShader(device, shader_11);
3237         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
3238         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 3 * sizeof(float));
3239         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3240
3241         hr = IDirect3DDevice9_SetVertexShader(device, shader_11_2);
3242         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
3243         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
3244         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3245
3246         if(shader_20) {
3247             hr = IDirect3DDevice9_SetVertexShader(device, shader_20);
3248             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
3249             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 3 * sizeof(float));
3250             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3251         }
3252
3253         if(shader_20_2) {
3254             hr = IDirect3DDevice9_SetVertexShader(device, shader_20_2);
3255             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
3256             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 3 * sizeof(float));
3257             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3258         }
3259
3260         hr = IDirect3DDevice9_EndScene(device);
3261         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3262     }
3263     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3264     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3265
3266     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
3267     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
3268     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
3269     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
3270
3271     color = getPixelColor(device, 160, 360);
3272     ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
3273        "quad 1 has color %08x, expected 0x00bfbf80\n", color);
3274     color = getPixelColor(device, 480, 360);
3275     ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
3276        "quad 2 has color %08x, expected 0x00bfbf80\n", color);
3277     if(shader_20) {
3278         color = getPixelColor(device, 160, 120);
3279         ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
3280            "quad 3 has color %08x, expected 0x00bfbf80\n", color);
3281     }
3282     if(shader_20_2) {
3283         color = getPixelColor(device, 480, 120);
3284         ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
3285            "quad 4 has color %08x, expected 0x00bfbf80\n", color);
3286     }
3287
3288     IDirect3DVertexDeclaration9_Release(decl);
3289     if(shader_20_2) IDirect3DVertexShader9_Release(shader_20_2);
3290     if(shader_20) IDirect3DVertexShader9_Release(shader_20);
3291     IDirect3DVertexShader9_Release(shader_11_2);
3292     IDirect3DVertexShader9_Release(shader_11);
3293 }
3294
3295 static void constant_clamp_ps_test(IDirect3DDevice9 *device)
3296 {
3297     IDirect3DPixelShader9 *shader_11, *shader_12, *shader_14, *shader_20;
3298     HRESULT hr;
3299     DWORD color;
3300     DWORD shader_code_11[] =  {
3301         0xffff0101,                                         /* ps_1_1           */
3302         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
3303         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
3304         0x0000ffff                                          /* end              */
3305     };
3306     DWORD shader_code_12[] =  {
3307         0xffff0102,                                         /* ps_1_2           */
3308         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
3309         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
3310         0x0000ffff                                          /* end              */
3311     };
3312     /* Skip 1.3 shaders because we have only 4 quads(ok, could make them smaller if needed).
3313      * 1.2 and 1.4 shaders behave the same, so it's unlikely that 1.3 shaders are different.
3314      * During development of this test, 1.3 shaders were verified too
3315      */
3316     DWORD shader_code_14[] =  {
3317         0xffff0104,                                         /* ps_1_4           */
3318         /* Try to make one constant local. It gets clamped too, although the binary contains
3319          * the bigger numbers
3320          */
3321         0x00000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000, /* def c2, -0.5, 1.25, 2, 1 */
3322         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
3323         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
3324         0x0000ffff                                          /* end              */
3325     };
3326     DWORD shader_code_20[] =  {
3327         0xffff0200,                                         /* ps_2_0           */
3328         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
3329         0x03000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
3330         0x02000001, 0x800f0800, 0x80e40000,                 /* mov oC0, r0      */
3331         0x0000ffff                                          /* end              */
3332     };
3333     float quad1[] = {
3334         -1.0,   -1.0,   0.1,
3335          0.0,   -1.0,   0.1,
3336         -1.0,    0.0,   0.1,
3337          0.0,    0.0,   0.1
3338     };
3339     float quad2[] = {
3340          0.0,   -1.0,   0.1,
3341          1.0,   -1.0,   0.1,
3342          0.0,    0.0,   0.1,
3343          1.0,    0.0,   0.1
3344     };
3345     float quad3[] = {
3346          0.0,    0.0,   0.1,
3347          1.0,    0.0,   0.1,
3348          0.0,    1.0,   0.1,
3349          1.0,    1.0,   0.1
3350     };
3351     float quad4[] = {
3352         -1.0,    0.0,   0.1,
3353          0.0,    0.0,   0.1,
3354         -1.0,    1.0,   0.1,
3355          0.0,    1.0,   0.1
3356     };
3357     float test_data_c1[4] = {  1.25, -0.50, -1.50, 1.0};
3358     float test_data_c2[4] = { -0.50,  1.25,  2.00, 1.0};
3359
3360     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
3361     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
3362
3363     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader_11);
3364     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
3365     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12, &shader_12);
3366     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
3367     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14, &shader_14);
3368     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
3369     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_20, &shader_20);
3370     if(FAILED(hr)) shader_20 = NULL;
3371
3372     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1, 1);
3373     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
3374     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2, 1);
3375     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
3376     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
3377     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
3378
3379     hr = IDirect3DDevice9_BeginScene(device);
3380     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
3381     if(SUCCEEDED(hr))
3382     {
3383         hr = IDirect3DDevice9_SetPixelShader(device, shader_11);
3384         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
3385         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 3 * sizeof(float));
3386         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3387
3388         hr = IDirect3DDevice9_SetPixelShader(device, shader_12);
3389         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
3390         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
3391         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3392
3393         hr = IDirect3DDevice9_SetPixelShader(device, shader_14);
3394         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
3395         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 3 * sizeof(float));
3396         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3397
3398         if(shader_20) {
3399             hr = IDirect3DDevice9_SetPixelShader(device, shader_20);
3400             ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
3401             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 3 * sizeof(float));
3402             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3403         }
3404
3405         hr = IDirect3DDevice9_EndScene(device);
3406         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3407     }
3408     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3409     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3410
3411     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
3412     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
3413
3414     color = getPixelColor(device, 160, 360);
3415     ok(color == 0x00808000 || color == 0x007f7f00 || color == 0x00818100,
3416        "quad 1 has color %08x, expected 0x00808000\n", color);
3417     color = getPixelColor(device, 480, 360);
3418     ok(color == 0x00808000 || color == 0x007f7f00 || color == 0x00818100,
3419        "quad 2 has color %08x, expected 0x00808000\n", color);
3420     color = getPixelColor(device, 480, 120);
3421     ok(color == 0x00808000 || color == 0x007f7f00 || color == 0x00818100,
3422        "quad 3 has color %08x, expected 0x00808000\n", color);
3423     if(shader_20) {
3424         color = getPixelColor(device, 160, 120);
3425         ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
3426            "quad 4 has color %08x, expected 0x00bfbf80\n", color);
3427     }
3428
3429     if(shader_20) IDirect3DPixelShader9_Release(shader_20);
3430     IDirect3DPixelShader9_Release(shader_14);
3431     IDirect3DPixelShader9_Release(shader_12);
3432     IDirect3DPixelShader9_Release(shader_11);
3433 }
3434
3435 static void cnd_test(IDirect3DDevice9 *device)
3436 {
3437     IDirect3DPixelShader9 *shader_11, *shader_12, *shader_13, *shader_14;
3438     IDirect3DPixelShader9 *shader_11_coissue, *shader_12_coissue, *shader_13_coissue, *shader_14_coissue;
3439     HRESULT hr;
3440     DWORD color;
3441     /* ps 1.x shaders are rather picky with writemasks and source swizzles. The dp3 is
3442      * used to copy r0.r to all components of r1, then copy r1.a to c0.a. Essentially it
3443      * does a mov r0.a, r0.r, which isn't allowed as-is in 1.x pixel shaders.
3444      */
3445     DWORD shader_code_11[] =  {
3446         0xffff0101,                                                                 /* ps_1_1               */
3447         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
3448         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
3449         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, ???(t0)      */
3450         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3 r1, r0, c0       */
3451         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
3452         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
3453         0x0000ffff                                                                  /* end                  */
3454     };
3455     DWORD shader_code_12[] =  {
3456         0xffff0102,                                                                 /* ps_1_2               */
3457         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
3458         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
3459         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, t0           */
3460         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3 r1, r0, c0       */
3461         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
3462         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
3463         0x0000ffff                                                                  /* end                  */
3464     };
3465     DWORD shader_code_13[] =  {
3466         0xffff0103,                                                                 /* ps_1_3               */
3467         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
3468         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
3469         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, t0           */
3470         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3, r1, r0, c0      */
3471         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
3472         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
3473         0x0000ffff                                                                  /* end                  */
3474     };
3475     DWORD shader_code_14[] =  {
3476         0xffff0104,                                                                 /* ps_1_3               */
3477         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,     /* def c0, 0, 0, 0, 1   */
3478         0x00000040, 0x80070000, 0xb0e40000,                                         /* texcrd r0, t0        */
3479         0x00000001, 0x80080000, 0xa0ff0000,                                         /* mov r0.a, c0.a       */
3480         0x00000050, 0x800f0000, 0x80e40000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0, c1, c2   */
3481         0x0000ffff                                                                  /* end                  */
3482     };
3483
3484     /* Special fun: The coissue flag on cnd: Apparently cnd always selects the 2nd source,
3485      * as if the src0 comparison against 0.5 always evaluates to true. The coissue flag isn't
3486      * set by the compiler, it was added manually after compilation. It isn't always allowed,
3487      * only if there's a mov r0.a, XXXX, and the cnd instruction writes to r0.xyz, otherwise
3488      * native CreatePixelShader returns an error.
3489      *
3490      * The shader attempts to test the range [-1;1] against coissued cnd, which is a bit tricky.
3491      * The input from t0 is [0;1]. 0.5 is substracted, then we have to multiply with 2. Since
3492      * constants are clamped to [-1;1], a 2.0 is constructed by adding c0.r(=1.0) to c0.r into r1.r,
3493      * then r1(2.0, 0.0, 0.0, 0.0) is passed to dp3(explained above).
3494      */
3495     DWORD shader_code_11_coissue[] =  {
3496         0xffff0101,                                                             /* ps_1_1                   */
3497         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
3498         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
3499         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
3500         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
3501         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
3502         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
3503         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
3504         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
3505         /* 0x40000000 = D3DSI_COISSUE */
3506         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
3507         0x0000ffff                                                              /* end                      */
3508     };
3509     DWORD shader_code_12_coissue[] =  {
3510         0xffff0102,                                                             /* ps_1_2                   */
3511         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
3512         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
3513         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
3514         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
3515         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
3516         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
3517         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
3518         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
3519         /* 0x40000000 = D3DSI_COISSUE */
3520         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
3521         0x0000ffff                                                              /* end                      */
3522     };
3523     DWORD shader_code_13_coissue[] =  {
3524         0xffff0103,                                                             /* ps_1_3                   */
3525         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
3526         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
3527         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
3528         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
3529         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
3530         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
3531         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
3532         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
3533         /* 0x40000000 = D3DSI_COISSUE */
3534         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
3535         0x0000ffff                                                              /* end                      */
3536     };
3537     /* ps_1_4 does not have a different cnd behavior, just pass the [0;1] texcrd result to cnd, it will
3538      * compare against 0.5
3539      */
3540     DWORD shader_code_14_coissue[] =  {
3541         0xffff0104,                                                             /* ps_1_4                   */
3542         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0, 0, 0, 1       */
3543         0x00000040, 0x80070000, 0xb0e40000,                                     /* texcrd r0, t0            */
3544         0x00000001, 0x80080000, 0xa0ff0000,                                     /* mov r0.a, c0.a           */
3545         /* 0x40000000 = D3DSI_COISSUE */
3546         0x40000050, 0x80070000, 0x80e40000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0, c1, c2   */
3547         0x0000ffff                                                              /* end                      */
3548     };
3549     float quad1[] = {
3550         -1.0,   -1.0,   0.1,     0.0,    0.0,    1.0,
3551          0.0,   -1.0,   0.1,     1.0,    0.0,    1.0,
3552         -1.0,    0.0,   0.1,     0.0,    1.0,    0.0,
3553          0.0,    0.0,   0.1,     1.0,    1.0,    0.0
3554     };
3555     float quad2[] = {
3556          0.0,   -1.0,   0.1,     0.0,    0.0,    1.0,
3557          1.0,   -1.0,   0.1,     1.0,    0.0,    1.0,
3558          0.0,    0.0,   0.1,     0.0,    1.0,    0.0,
3559          1.0,    0.0,   0.1,     1.0,    1.0,    0.0
3560     };
3561     float quad3[] = {
3562          0.0,    0.0,   0.1,     0.0,    0.0,    1.0,
3563          1.0,    0.0,   0.1,     1.0,    0.0,    1.0,
3564          0.0,    1.0,   0.1,     0.0,    1.0,    0.0,
3565          1.0,    1.0,   0.1,     1.0,    1.0,    0.0
3566     };
3567     float quad4[] = {
3568         -1.0,    0.0,   0.1,     0.0,    0.0,    1.0,
3569          0.0,    0.0,   0.1,     1.0,    0.0,    1.0,
3570         -1.0,    1.0,   0.1,     0.0,    1.0,    0.0,
3571          0.0,    1.0,   0.1,     1.0,    1.0,    0.0
3572     };
3573     float test_data_c1[4] = {  0.0, 0.0, 0.0, 0.0};
3574     float test_data_c2[4] = {  1.0, 1.0, 1.0, 1.0};
3575     float test_data_c1_coi[4] = {  0.0, 1.0, 0.0, 0.0};
3576     float test_data_c2_coi[4] = {  1.0, 0.0, 1.0, 1.0};
3577
3578     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
3579     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
3580
3581     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader_11);
3582     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
3583     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12, &shader_12);
3584     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
3585     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_13, &shader_13);
3586     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
3587     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14, &shader_14);
3588     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
3589     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11_coissue, &shader_11_coissue);
3590     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
3591     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12_coissue, &shader_12_coissue);
3592     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
3593     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_13_coissue, &shader_13_coissue);
3594     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
3595     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14_coissue, &shader_14_coissue);
3596     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
3597
3598     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1, 1);
3599     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
3600     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2, 1);
3601     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
3602     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3603     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
3604
3605     hr = IDirect3DDevice9_BeginScene(device);
3606     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
3607     if(SUCCEEDED(hr))
3608     {
3609         hr = IDirect3DDevice9_SetPixelShader(device, shader_11);
3610         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
3611         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
3612         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3613
3614         hr = IDirect3DDevice9_SetPixelShader(device, shader_12);
3615         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
3616         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
3617         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3618
3619         hr = IDirect3DDevice9_SetPixelShader(device, shader_13);
3620         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
3621         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 6 * sizeof(float));
3622         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3623
3624         hr = IDirect3DDevice9_SetPixelShader(device, shader_14);
3625         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
3626         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
3627         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3628
3629         hr = IDirect3DDevice9_EndScene(device);
3630         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3631     }
3632     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3633     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3634
3635     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
3636     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
3637
3638     /* This is the 1.4 test. Each component(r, g, b) is tested separately against 0.5 */
3639     color = getPixelColor(device, 158, 118);
3640     ok(color == 0x00ff00ff, "pixel 158, 118 has color %08x, expected 0x00ff00ff\n", color);
3641     color = getPixelColor(device, 162, 118);
3642     ok(color == 0x000000ff, "pixel 162, 118 has color %08x, expected 0x000000ff\n", color);
3643     color = getPixelColor(device, 158, 122);
3644     ok(color == 0x00ffffff, "pixel 162, 122 has color %08x, expected 0x00ffffff\n", color);
3645     color = getPixelColor(device, 162, 122);
3646     ok(color == 0x0000ffff, "pixel 162, 122 has color %08x, expected 0x0000ffff\n", color);
3647
3648     /* 1.1 shader. All 3 components get set, based on the .w comparison */
3649     color = getPixelColor(device, 158, 358);
3650     ok(color == 0x00ffffff, "pixel 158, 358 has color %08x, expected 0x00ffffff\n", color);
3651     color = getPixelColor(device, 162, 358);
3652     ok(color == 0x00000000, "pixel 162, 358 has color %08x, expected 0x00000000\n", color);
3653     color = getPixelColor(device, 158, 362);
3654     ok(color == 0x00ffffff, "pixel 158, 362 has color %08x, expected 0x00ffffff\n", color);
3655     color = getPixelColor(device, 162, 362);
3656     ok(color == 0x00000000, "pixel 162, 362 has color %08x, expected 0x00000000\n", color);
3657
3658     /* 1.2 shader */
3659     color = getPixelColor(device, 478, 358);
3660     ok(color == 0x00ffffff, "pixel 478, 358 has color %08x, expected 0x00ffffff\n", color);
3661     color = getPixelColor(device, 482, 358);
3662     ok(color == 0x00000000, "pixel 482, 358 has color %08x, expected 0x00000000\n", color);
3663     color = getPixelColor(device, 478, 362);
3664     ok(color == 0x00ffffff, "pixel 478, 362 has color %08x, expected 0x00ffffff\n", color);
3665     color = getPixelColor(device, 482, 362);
3666     ok(color == 0x00000000, "pixel 482, 362 has color %08x, expected 0x00000000\n", color);
3667
3668     /* 1.3 shader */
3669     color = getPixelColor(device, 478, 118);
3670     ok(color == 0x00ffffff, "pixel 478, 118 has color %08x, expected 0x00ffffff\n", color);
3671     color = getPixelColor(device, 482, 118);
3672     ok(color == 0x00000000, "pixel 482, 118 has color %08x, expected 0x00000000\n", color);
3673     color = getPixelColor(device, 478, 122);
3674     ok(color == 0x00ffffff, "pixel 478, 122 has color %08x, expected 0x00ffffff\n", color);
3675     color = getPixelColor(device, 482, 122);
3676     ok(color == 0x00000000, "pixel 482, 122 has color %08x, expected 0x00000000\n", color);
3677
3678     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
3679     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
3680     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1_coi, 1);
3681     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
3682     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2_coi, 1);
3683     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
3684
3685     hr = IDirect3DDevice9_BeginScene(device);
3686     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
3687     if(SUCCEEDED(hr))
3688     {
3689         hr = IDirect3DDevice9_SetPixelShader(device, shader_11_coissue);
3690         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
3691         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
3692         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3693
3694         hr = IDirect3DDevice9_SetPixelShader(device, shader_12_coissue);
3695         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
3696         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
3697         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3698
3699         hr = IDirect3DDevice9_SetPixelShader(device, shader_13_coissue);
3700         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
3701         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 6 * sizeof(float));
3702         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3703
3704         hr = IDirect3DDevice9_SetPixelShader(device, shader_14_coissue);
3705         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
3706         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
3707         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3708
3709         hr = IDirect3DDevice9_EndScene(device);
3710         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3711     }
3712     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3713     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3714
3715     /* This is the 1.4 test. The coissue doesn't change the behavior here, but keep in mind
3716      * that we swapped the values in c1 and c2 to make the other tests return some color
3717      */
3718     color = getPixelColor(device, 158, 118);
3719     ok(color == 0x00ffffff, "pixel 158, 118 has color %08x, expected 0x00ffffff\n", color);
3720     color = getPixelColor(device, 162, 118);
3721     ok(color == 0x0000ffff, "pixel 162, 118 has color %08x, expected 0x0000ffff\n", color);
3722     color = getPixelColor(device, 158, 122);
3723     ok(color == 0x00ff00ff, "pixel 162, 122 has color %08x, expected 0x00ff00ff\n", color);
3724     color = getPixelColor(device, 162, 122);
3725     ok(color == 0x000000ff, "pixel 162, 122 has color %08x, expected 0x000000ff\n", color);
3726
3727     /* 1.1 shader. coissue flag changed the semantic of cnd, c1 is always selected */
3728     color = getPixelColor(device, 158, 358);
3729     ok(color == 0x0000ff00, "pixel 158, 358 has color %08x, expected 0x0000ff00\n", color);
3730     color = getPixelColor(device, 162, 358);
3731     ok(color == 0x0000ff00, "pixel 162, 358 has color %08x, expected 0x0000ff00\n", color);
3732     color = getPixelColor(device, 158, 362);
3733     ok(color == 0x0000ff00, "pixel 158, 362 has color %08x, expected 0x0000ff00\n", color);
3734     color = getPixelColor(device, 162, 362);
3735     ok(color == 0x0000ff00, "pixel 162, 362 has color %08x, expected 0x0000ff00\n", color);
3736
3737     /* 1.2 shader */
3738     color = getPixelColor(device, 478, 358);
3739     ok(color == 0x0000ff00, "pixel 478, 358 has color %08x, expected 0x0000ff00\n", color);
3740     color = getPixelColor(device, 482, 358);
3741     ok(color == 0x0000ff00, "pixel 482, 358 has color %08x, expected 0x0000ff00\n", color);
3742     color = getPixelColor(device, 478, 362);
3743     ok(color == 0x0000ff00, "pixel 478, 362 has color %08x, expected 0x0000ff00\n", color);
3744     color = getPixelColor(device, 482, 362);
3745     ok(color == 0x0000ff00, "pixel 482, 362 has color %08x, expected 0x0000ff00\n", color);
3746
3747     /* 1.3 shader */
3748     color = getPixelColor(device, 478, 118);
3749     ok(color == 0x0000ff00, "pixel 478, 118 has color %08x, expected 0x0000ff00\n", color);
3750     color = getPixelColor(device, 482, 118);
3751     ok(color == 0x0000ff00, "pixel 482, 118 has color %08x, expected 0x0000ff00\n", color);
3752     color = getPixelColor(device, 478, 122);
3753     ok(color == 0x0000ff00, "pixel 478, 122 has color %08x, expected 0x0000ff00\n", color);
3754     color = getPixelColor(device, 482, 122);
3755     ok(color == 0x0000ff00, "pixel 482, 122 has color %08x, expected 0x0000ff00\n", color);
3756
3757     IDirect3DPixelShader9_Release(shader_14_coissue);
3758     IDirect3DPixelShader9_Release(shader_13_coissue);
3759     IDirect3DPixelShader9_Release(shader_12_coissue);
3760     IDirect3DPixelShader9_Release(shader_11_coissue);
3761     IDirect3DPixelShader9_Release(shader_14);
3762     IDirect3DPixelShader9_Release(shader_13);
3763     IDirect3DPixelShader9_Release(shader_12);
3764     IDirect3DPixelShader9_Release(shader_11);
3765 }
3766
3767 static void nested_loop_test(IDirect3DDevice9 *device) {
3768     const DWORD shader_code[] = {
3769         0xffff0300,                                                             /* ps_3_0               */
3770         0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0, 0, 0, 1   */
3771         0x05000051, 0xa00f0001, 0x3d000000, 0x00000000, 0x00000000, 0x00000000, /* def c1, 1/32, 0, 0, 0*/
3772         0x05000030, 0xf00f0000, 0x00000004, 0x00000000, 0x00000002, 0x00000000, /* defi i0, 4, 0, 2, 0  */
3773         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0           */
3774         0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0          */
3775         0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0          */
3776         0x03000002, 0x800f0000, 0x80e40000, 0xa0e40001,                         /* add r0, r0, c1       */
3777         0x0000001d,                                                             /* endloop              */
3778         0x0000001d,                                                             /* endloop              */
3779         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0          */
3780         0x0000ffff                                                              /* end                  */
3781     };
3782     IDirect3DPixelShader9 *shader;
3783     HRESULT hr;
3784     DWORD color;
3785     const float quad[] = {
3786         -1.0,   -1.0,   0.1,
3787          1.0,   -1.0,   0.1,
3788         -1.0,    1.0,   0.1,
3789          1.0,    1.0,   0.1
3790     };
3791
3792     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
3793     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed with %s\n", DXGetErrorString9(hr));
3794     hr = IDirect3DDevice9_SetPixelShader(device, shader);
3795     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with %s\n", DXGetErrorString9(hr));
3796     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
3797     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
3798     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 0.0, 0);
3799     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
3800
3801     hr = IDirect3DDevice9_BeginScene(device);
3802     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
3803     if(SUCCEEDED(hr))
3804     {
3805         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
3806         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3807         hr = IDirect3DDevice9_EndScene(device);
3808         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3809     }
3810     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3811     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3812
3813     color = getPixelColor(device, 360, 240);
3814     ok(color == 0x007f0000 || color == 0x00800000 || color == 0x00810000,
3815        "Nested loop test returned color 0x%08x, expected 0x00800000\n", color);
3816
3817     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
3818     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with %s\n", DXGetErrorString9(hr));
3819     IDirect3DPixelShader9_Release(shader);
3820 }
3821
3822 struct varying_test_struct
3823 {
3824     const DWORD             *shader_code;
3825     IDirect3DPixelShader9   *shader;
3826     DWORD                   color, color_rhw;
3827     const char              *name;
3828     BOOL                    todo, todo_rhw;
3829 };
3830
3831 struct hugeVertex
3832 {
3833     float pos_x,        pos_y,      pos_z,      rhw;
3834     float weight_1,     weight_2,   weight_3,   weight_4;
3835     float index_1,      index_2,    index_3,    index_4;
3836     float normal_1,     normal_2,   normal_3,   normal_4;
3837     float fog_1,        fog_2,      fog_3,      fog_4;
3838     float texcoord_1,   texcoord_2, texcoord_3, texcoord_4;
3839     float tangent_1,    tangent_2,  tangent_3,  tangent_4;
3840     float binormal_1,   binormal_2, binormal_3, binormal_4;
3841     float depth_1,      depth_2,    depth_3,    depth_4;
3842     DWORD diffuse, specular;
3843 };
3844
3845 static void fixed_function_varying_test(IDirect3DDevice9 *device) {
3846     /* dcl_position: fails to compile */
3847     const DWORD blendweight_code[] = {
3848         0xffff0300,                             /* ps_3_0                   */
3849         0x0200001f, 0x80000001, 0x900f0000,     /* dcl_blendweight, v0      */
3850         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
3851         0x0000ffff                              /* end                      */
3852     };
3853     const DWORD blendindices_code[] = {
3854         0xffff0300,                             /* ps_3_0                   */
3855         0x0200001f, 0x80000002, 0x900f0000,     /* dcl_blendindices, v0     */
3856         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
3857         0x0000ffff                              /* end                      */
3858     };
3859     const DWORD normal_code[] = {
3860         0xffff0300,                             /* ps_3_0                   */
3861         0x0200001f, 0x80000003, 0x900f0000,     /* dcl_normal, v0           */
3862         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
3863         0x0000ffff                              /* end                      */
3864     };
3865     /* psize: fails? */
3866     const DWORD texcoord0_code[] = {
3867         0xffff0300,                             /* ps_3_0                   */
3868         0x0200001f, 0x80000005, 0x900f0000,     /* dcl_texcoord0, v0        */
3869         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
3870         0x0000ffff                              /* end                      */
3871     };
3872     const DWORD tangent_code[] = {
3873         0xffff0300,                             /* ps_3_0                   */
3874         0x0200001f, 0x80000006, 0x900f0000,     /* dcl_tangent, v0          */
3875         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
3876         0x0000ffff                              /* end                      */
3877     };
3878     const DWORD binormal_code[] = {
3879         0xffff0300,                             /* ps_3_0                   */
3880         0x0200001f, 0x80000007, 0x900f0000,     /* dcl_binormal, v0         */
3881         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
3882         0x0000ffff                              /* end                      */
3883     };
3884     /* tessfactor: fails */
3885     /* positiont: fails */
3886     const DWORD color_code[] = {
3887         0xffff0300,                             /* ps_3_0                   */
3888         0x0200001f, 0x8000000a, 0x900f0000,     /* dcl_color0, v0           */
3889         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
3890         0x0000ffff                              /* end                      */
3891     };
3892     const DWORD fog_code[] = {
3893         0xffff0300,                             /* ps_3_0                   */
3894         0x0200001f, 0x8000000b, 0x900f0000,     /* dcl_fog, v0              */
3895         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
3896         0x0000ffff                              /* end                      */
3897     };
3898     const DWORD depth_code[] = {
3899         0xffff0300,                             /* ps_3_0                   */
3900         0x0200001f, 0x8000000c, 0x900f0000,     /* dcl_depth, v0            */
3901         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
3902         0x0000ffff                              /* end                      */
3903     };
3904     const DWORD specular_code[] = {
3905         0xffff0300,                             /* ps_3_0                   */
3906         0x0200001f, 0x8001000a, 0x900f0000,     /* dcl_color1, v0           */
3907         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
3908         0x0000ffff                              /* end                      */
3909     };
3910     /* sample: fails */
3911
3912     struct varying_test_struct tests[] = {
3913        {blendweight_code,       NULL,       0x00000000,     0x00191919,     "blendweight"   ,   FALSE,  TRUE  },
3914        {blendindices_code,      NULL,       0x00000000,     0x00000000,     "blendindices"  ,   FALSE,  FALSE },
3915        {normal_code,            NULL,       0x00000000,     0x004c4c4c,     "normal"        ,   FALSE,  TRUE  },
3916        /* Why does dx not forward the texcoord? */
3917        {texcoord0_code,         NULL,       0x00000000,     0x00808c8c,     "texcoord0"     ,   FALSE,  FALSE },
3918        {tangent_code,           NULL,       0x00000000,     0x00999999,     "tangent"       ,   FALSE,  TRUE  },
3919        {binormal_code,          NULL,       0x00000000,     0x00b2b2b2,     "binormal"      ,   FALSE,  TRUE  },
3920        {color_code,             NULL,       0x00e6e6e6,     0x00e6e6e6,     "color"         ,   FALSE,  FALSE },
3921        {fog_code,               NULL,       0x00000000,     0x00666666,     "fog"           ,   FALSE,  TRUE  },
3922        {depth_code,             NULL,       0x00000000,     0x00cccccc,     "depth"         ,   FALSE,  TRUE  },
3923        {specular_code,          NULL,       0x004488ff,     0x004488ff,     "specular"      ,   FALSE,  FALSE }
3924     };
3925     /* Declare a monster vertex type :-) */
3926     static const D3DVERTEXELEMENT9 decl_elements[] = {
3927         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
3928         {0,  16,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT,    0},
3929         {0,  32,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES,   0},
3930         {0,  48,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,         0},
3931         {0,  64,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_FOG,            0},
3932         {0,  80,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
3933         {0,  96,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT,        0},
3934         {0, 112,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL,       0},
3935         {0, 128,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_DEPTH,          0},
3936         {0, 144,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
3937         {0, 148,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          1},
3938         D3DDECL_END()
3939     };
3940     static const D3DVERTEXELEMENT9 decl_elements2[] = {
3941         {0,   0,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT,      0},
3942         {0,  16,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT,    0},
3943         {0,  32,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES,   0},
3944         {0,  48,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,         0},
3945         {0,  64,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_FOG,            0},
3946         {0,  80,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
3947         {0,  96,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT,        0},
3948         {0, 112,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL,       0},
3949         {0, 128,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_DEPTH,          0},
3950         {0, 144,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
3951         {0, 148,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          1},
3952         D3DDECL_END()
3953     };
3954     struct hugeVertex data[4] = {
3955         {
3956             -1.0,   -1.0,   0.1,    1.0,
3957              0.1,    0.1,   0.1,    0.1,
3958              0.2,    0.2,   0.2,    0.2,
3959              0.3,    0.3,   0.3,    0.3,
3960              0.4,    0.4,   0.4,    0.4,
3961              0.50,   0.55,  0.55,   0.55,
3962              0.6,    0.6,   0.6,    0.7,
3963              0.7,    0.7,   0.7,    0.6,
3964              0.8,    0.8,   0.8,    0.8,
3965              0xe6e6e6e6, /* 0.9 * 256 */
3966              0x224488ff  /* Nothing special */
3967         },
3968         {
3969              1.0,   -1.0,   0.1,    1.0,
3970              0.1,    0.1,   0.1,    0.1,
3971              0.2,    0.2,   0.2,    0.2,
3972              0.3,    0.3,   0.3,    0.3,
3973              0.4,    0.4,   0.4,    0.4,
3974              0.50,   0.55,  0.55,   0.55,
3975              0.6,    0.6,   0.6,    0.7,
3976              0.7,    0.7,   0.7,    0.6,
3977              0.8,    0.8,   0.8,    0.8,
3978              0xe6e6e6e6, /* 0.9 * 256 */
3979              0x224488ff /* Nothing special */
3980         },
3981         {
3982             -1.0,    1.0,   0.1,    1.0,
3983              0.1,    0.1,   0.1,    0.1,
3984              0.2,    0.2,   0.2,    0.2,
3985              0.3,    0.3,   0.3,    0.3,
3986              0.4,    0.4,   0.4,    0.4,
3987              0.50,   0.55,  0.55,   0.55,
3988              0.6,    0.6,   0.6,    0.7,
3989              0.7,    0.7,   0.7,    0.6,
3990              0.8,    0.8,   0.8,    0.8,
3991              0xe6e6e6e6, /* 0.9 * 256 */
3992              0x224488ff /* Nothing special */
3993         },
3994         {
3995              1.0,    1.0,   0.1,    1.0,
3996              0.1,    0.1,   0.1,    0.1,
3997              0.2,    0.2,   0.2,    0.2,
3998              0.3,    0.3,   0.3,    0.3,
3999              0.4,    0.4,   0.4,    0.4,
4000              0.50,   0.55,  0.55,   0.55,
4001              0.6,    0.6,   0.6,    0.7,
4002              0.7,    0.7,   0.7,    0.6,
4003              0.8,    0.8,   0.8,    0.8,
4004              0xe6e6e6e6, /* 0.9 * 256 */
4005              0x224488ff /* Nothing special */
4006         },
4007     };
4008     struct hugeVertex data2[4];
4009     IDirect3DVertexDeclaration9 *decl;
4010     IDirect3DVertexDeclaration9 *decl2;
4011     HRESULT hr;
4012     unsigned int i;
4013     DWORD color, r, g, b, r_e, g_e, b_e;
4014
4015     memcpy(data2, data, sizeof(data2));
4016     data2[0].pos_x = 0;     data2[0].pos_y = 0;
4017     data2[1].pos_x = 640;   data2[1].pos_y = 0;
4018     data2[2].pos_x = 0;     data2[2].pos_y = 480;
4019     data2[3].pos_x = 640;   data2[3].pos_y = 480;
4020
4021     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
4022     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4023     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements2, &decl2);
4024     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4025     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
4026     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4027
4028     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
4029     {
4030         hr = IDirect3DDevice9_CreatePixelShader(device, tests[i].shader_code, &tests[i].shader);
4031         ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed for shader %s, hr = %s\n",
4032            tests[i].name, DXGetErrorString9(hr));
4033     }
4034
4035     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
4036     {
4037         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4038         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
4039
4040         IDirect3DDevice9_SetPixelShader(device, tests[i].shader);
4041         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4042
4043         hr = IDirect3DDevice9_BeginScene(device);
4044         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
4045         if(SUCCEEDED(hr))
4046         {
4047             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, data, sizeof(data[0]));
4048             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4049             hr = IDirect3DDevice9_EndScene(device);
4050             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
4051         }
4052         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4053         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4054
4055         color = getPixelColor(device, 360, 240);
4056         r = color & 0x00ff0000 >> 16;
4057         g = color & 0x0000ff00 >>  8;
4058         b = color & 0x000000ff;
4059         r_e = tests[i].color & 0x00ff0000 >> 16;
4060         g_e = tests[i].color & 0x0000ff00 >>  8;
4061         b_e = tests[i].color & 0x000000ff;
4062
4063         if(tests[i].todo) {
4064             todo_wine ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
4065                          "Test %s returned color 0x%08x, expected 0x%08x(todo)\n",
4066                          tests[i].name, color, tests[i].color);
4067         } else {
4068             ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
4069                "Test %s returned color 0x%08x, expected 0x%08x\n",
4070                tests[i].name, color, tests[i].color);
4071         }
4072     }
4073
4074     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl2);
4075     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4076     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
4077     {
4078         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4079         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
4080
4081         IDirect3DDevice9_SetPixelShader(device, tests[i].shader);
4082         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4083
4084         hr = IDirect3DDevice9_BeginScene(device);
4085         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
4086         if(SUCCEEDED(hr))
4087         {
4088             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, data2, sizeof(data2[0]));
4089             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4090             hr = IDirect3DDevice9_EndScene(device);
4091             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
4092         }
4093         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4094         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4095
4096         color = getPixelColor(device, 360, 240);
4097         r = color & 0x00ff0000 >> 16;
4098         g = color & 0x0000ff00 >>  8;
4099         b = color & 0x000000ff;
4100         r_e = tests[i].color_rhw & 0x00ff0000 >> 16;
4101         g_e = tests[i].color_rhw & 0x0000ff00 >>  8;
4102         b_e = tests[i].color_rhw & 0x000000ff;
4103
4104         if(tests[i].todo_rhw) {
4105             /* This isn't a weekend's job to fix, ignore the problem for now. Needs a replacement
4106              * pipeline
4107              */
4108             todo_wine ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
4109                          "Test %s returned color 0x%08x, expected 0x%08x(todo)\n",
4110                          tests[i].name, color, tests[i].color_rhw);
4111         } else {
4112             ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
4113                "Test %s returned color 0x%08x, expected 0x%08x\n",
4114                tests[i].name, color, tests[i].color_rhw);
4115         }
4116     }
4117
4118     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
4119     {
4120         IDirect3DPixelShader9_Release(tests[i].shader);
4121     }
4122
4123     IDirect3DVertexDeclaration9_Release(decl2);
4124     IDirect3DVertexDeclaration9_Release(decl);
4125 }
4126
4127 static void vshader_version_varying_test(IDirect3DDevice9 *device) {
4128     static const DWORD ps_code[] = {
4129     0xffff0300,                                                             /* ps_3_0                       */
4130     0x05000030, 0xf00f0000, 0x00000003, 0x00000003, 0x00000001, 0x00000000, /* defi i0, 3, 3, 1, 0          */
4131     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0   */
4132     0x0200001f, 0x8001000a, 0x900f0003,                                     /* dcl_color1 v3                */
4133     0x0200001f, 0x8000000b, 0x900f0004,                                     /* dcl_fog v4                   */
4134     0x0200001f, 0x80030005, 0x900f0005,                                     /* dcl_texcoord3 v5             */
4135     0x0200001f, 0x80000003, 0x900f0006,
4136     0x0200001f, 0x80000006, 0x900f0007,
4137     0x0200001f, 0x80000001, 0x900f0008,
4138     0x0200001f, 0x8000000c, 0x900f0009,
4139
4140     0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                   */
4141     0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0                  */
4142     0x04000002, 0x800f0000, 0x80e40000, 0x90e42000, 0xf0e40800,             /* add r0, r0, v0[aL]           */
4143     0x0000001d,                                                             /* endloop                      */
4144     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
4145     0x0000ffff                                                              /* end                          */
4146     };
4147     static const DWORD vs_1_code[] = {
4148     0xfffe0101,                                                             /* vs_1_1                       */
4149     0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
4150     0x00000051, 0xa00f0000, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.1, 0.0, 0.0, 0.0   */
4151     0x00000051, 0xa00f0001, 0x00000000, 0x3e4ccccd, 0x00000000, 0x00000000, /* def c1, 0.0, 0.2, 0.0, 0.0   */
4152     0x00000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3ecccccd, 0x00000000, /* def c2, 0.0, 0.0, 0.4, 0.0   */
4153     0x00000051, 0xa00f0003, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 1.0, 1.0, 1.0, 1.0   */
4154     0x00000001, 0xd00f0000, 0xa0e40002,                                     /* mov oD0, c2                  */
4155     0x00000001, 0xd00f0001, 0xa0e40000,                                     /* mov oD1, c0                  */
4156     0x00000001, 0xc00f0001, 0xa0550001,                                     /* mov oFog, c1.g               */
4157     0x00000001, 0xe00f0000, 0xa0e40003,                                     /* mov oT0, c3                  */
4158     0x00000001, 0xe00f0001, 0xa0e40003,                                     /* mov oT1, c3                  */
4159     0x00000001, 0xe00f0002, 0xa0e40003,                                     /* mov oT2, c3                  */
4160     0x00000001, 0xe00f0003, 0xa0e40002,                                     /* mov oT3, c2                  */
4161     0x00000001, 0xe00f0004, 0xa0e40003,                                     /* mov oT4, c3                  */
4162     0x00000001, 0xe00f0005, 0xa0e40003,                                     /* mov oT5, c3                  */
4163     0x00000001, 0xe00f0006, 0xa0e40003,                                     /* mov oT6, c3                  */
4164     0x00000001, 0xe00f0007, 0xa0e40003,                                     /* mov oT7, c3                  */
4165     0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
4166     0x0000ffff
4167     };
4168     DWORD vs_2_code[] = {
4169     0xfffe0200,                                                             /* vs_2_0                       */
4170     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
4171     0x05000051, 0xa00f0000, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.5, 0.0, 0.0, 0.0   */
4172     0x05000051, 0xa00f0001, 0x00000000, 0x3e4ccccd, 0x00000000, 0x00000000, /* def c1, 0.0, 0.5, 0.0, 0.0   */
4173     0x05000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3ecccccd, 0x00000000, /* def c2, 0.0, 0.0, 0.5, 0.0   */
4174     0x05000051, 0xa00f0003, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 1.0, 1.0, 1.0, 1.0   */
4175     0x02000001, 0xd00f0000, 0xa0e40002,                                     /* mov oD0, c2                  */
4176     0x02000001, 0xd00f0001, 0xa0e40000,                                     /* mov oD1, c0                  */
4177     0x02000001, 0xc00f0001, 0xa0550001,                                     /* mov oFog, c1.g               */
4178     0x02000001, 0xe00f0000, 0xa0e40003,                                     /* mov oT0, c3                  */
4179     0x02000001, 0xe00f0001, 0xa0e40003,                                     /* mov oT1, c3                  */
4180     0x02000001, 0xe00f0002, 0xa0e40003,                                     /* mov oT2, c3                  */
4181     0x02000001, 0xe00f0003, 0xa0e40002,                                     /* mov oT3, c2                  */
4182     0x02000001, 0xe00f0004, 0xa0e40003,                                     /* mov oT4, c3                  */
4183     0x02000001, 0xe00f0005, 0xa0e40003,                                     /* mov oT5, c3                  */
4184     0x02000001, 0xe00f0006, 0xa0e40003,                                     /* mov oT6, c3                  */
4185     0x02000001, 0xe00f0007, 0xa0e40003,                                     /* mov oT7, c3                  */
4186     0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
4187     0x0000ffff                                                              /* end                          */
4188     };
4189     /* TODO: Define normal, tangent, blendweight and depth here */
4190     static const DWORD vs_3_code[] = {
4191     0xfffe0300,                                                             /* vs_3_0                       */
4192     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
4193     0x0200001f, 0x8001000a, 0xe00f0009,                                     /* dcl_color1 o9                */
4194     0x0200001f, 0x8000000b, 0xe00f0002,                                     /* dcl_fog o2                   */
4195     0x0200001f, 0x80030005, 0xe00f0005,                                     /* dcl_texcoord3 o5             */
4196     0x0200001f, 0x80000000, 0xe00f000b,                                     /* dcl_position o11             */
4197     0x05000051, 0xa00f0000, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.1, 0.0, 0.0, 0.0   */
4198     0x05000051, 0xa00f0001, 0x00000000, 0x3e4ccccd, 0x00000000, 0x00000000, /* def c1, 0.0, 0.2, 0.0, 0.0   */
4199     0x05000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3ecccccd, 0x00000000, /* def c2, 0.0, 0.0, 0.4, 0.0   */
4200     0x05000051, 0xa00f0003, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 1.0, 1.0, 1.0, 1.0   */
4201     0x02000001, 0xe00f0009, 0xa0e40000,                                     /* mov o9, c0                   */
4202     0x02000001, 0xe00f0002, 0xa0e40001,                                     /* mov o2, c1                   */
4203     0x02000001, 0xe00f0005, 0xa0e40002,                                     /* mov o5, c2                   */
4204     0x02000001, 0xe00f000b, 0x90e40000,                                     /* mov o11, v0                  */
4205     0x0000ffff                                                              /* end                          */
4206     };
4207     float quad1[] =  {
4208         -1.0,   -1.0,   0.1,
4209          0.0,   -1.0,   0.1,
4210         -1.0,    0.0,   0.1,
4211          0.0,    0.0,   0.1
4212     };
4213     float quad2[] =  {
4214          0.0,   -1.0,   0.1,
4215          1.0,   -1.0,   0.1,
4216          0.0,    0.0,   0.1,
4217          1.0,    0.0,   0.1
4218     };
4219     float quad3[] =  {
4220         -1.0,    0.0,   0.1,
4221          0.0,    0.0,   0.1,
4222         -1.0,    1.0,   0.1,
4223          0.0,    1.0,   0.1
4224     };
4225
4226     HRESULT hr;
4227     DWORD color;
4228     IDirect3DPixelShader9 *pixelshader = NULL;
4229     IDirect3DVertexShader9 *vs_1_shader = NULL;
4230     IDirect3DVertexShader9 *vs_2_shader = NULL;
4231     IDirect3DVertexShader9 *vs_3_shader = NULL;
4232
4233     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff110000, 0.0, 0);
4234
4235     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code, &pixelshader);
4236     ok(hr == D3D_OK, "IDirect3DDevice_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4237     hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_code, &vs_1_shader);
4238     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4239     hr = IDirect3DDevice9_CreateVertexShader(device, vs_2_code, &vs_2_shader);
4240     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4241     hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_code, &vs_3_shader);
4242     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4243     hr = IDirect3DDevice9_SetPixelShader(device, pixelshader);
4244     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4245     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4246
4247     hr = IDirect3DDevice9_BeginScene(device);
4248     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
4249     if(SUCCEEDED(hr))
4250     {
4251         hr = IDirect3DDevice9_SetVertexShader(device, vs_1_shader);
4252         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4253         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 3);
4254         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4255
4256         hr = IDirect3DDevice9_SetVertexShader(device, vs_2_shader);
4257         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4258         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2,  quad2, sizeof(float) * 3);
4259         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4260
4261         hr = IDirect3DDevice9_SetVertexShader(device, vs_3_shader);
4262         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4263         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 3);
4264         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4265
4266         hr = IDirect3DDevice9_EndScene(device);
4267         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
4268     }
4269     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4270     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4271
4272     color = getPixelColor(device, 160, 120);
4273     ok((color & 0x00ff0000) >= 0x00190000 && (color & 0x00ff0000) <= 0x00210000 &&
4274        (color & 0x0000ff00) >= 0x00003300 && (color & 0x0000ff00) <= 0x00003500 &&
4275        (color & 0x000000ff) >= 0x00000066 && (color & 0x000000ff) <= 0x00210068,
4276        "vs_3_0 returned color 0x%08x, expected 0x00203366\n", color);
4277     color = getPixelColor(device, 160, 360);
4278     ok((color & 0x00ff0000) >= 0x003c0000 && (color & 0x00ff0000) <= 0x004e0000 &&
4279        (color & 0x0000ff00) >= 0x00000000 && (color & 0x0000ff00) <= 0x00000000 &&
4280        (color & 0x000000ff) >= 0x00000066 && (color & 0x000000ff) <= 0x00210068,
4281        "vs_1_1 returned color 0x%08x, expected 0x00808080\n", color);
4282     color = getPixelColor(device, 480, 360);
4283     ok((color & 0x00ff0000) >= 0x003c0000 && (color & 0x00ff0000) <= 0x004e0000 &&
4284        (color & 0x0000ff00) >= 0x00000000 && (color & 0x0000ff00) <= 0x00000000 &&
4285        (color & 0x000000ff) >= 0x00000066 && (color & 0x000000ff) <= 0x00210068,
4286        "vs_2_0 returned color 0x%08x, expected 0x00000000\n", color);
4287
4288     /* cleanup */
4289     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4290     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4291     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
4292     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4293     if(pixelshader) IDirect3DPixelShader9_Release(pixelshader);
4294     if(vs_1_shader) IDirect3DVertexShader9_Release(vs_1_shader);
4295     if(vs_2_shader) IDirect3DVertexShader9_Release(vs_2_shader);
4296     if(vs_3_shader) IDirect3DVertexShader9_Release(vs_3_shader);
4297 }
4298
4299 static void pshader_version_varying_test(IDirect3DDevice9 *device) {
4300     static const DWORD vs_code[] = {
4301     0xfffe0300,                                                             /* vs_3_0                       */
4302     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
4303     0x0200001f, 0x80000000, 0xe00f0000,                                     /* dcl_position o0              */
4304     0x0200001f, 0x8000000a, 0xe00f0001,                                     /* dcl_color0 o1                */
4305     0x0200001f, 0x80000005, 0xe00f0002,                                     /* dcl_texcoord0 o2             */
4306     0x0200001f, 0x8000000b, 0xe00f0003,                                     /* dcl_fog o3                   */
4307     0x0200001f, 0x80000003, 0xe00f0004,                                     /* dcl_normal o4                */
4308     0x0200001f, 0x8000000c, 0xe00f0005,                                     /* dcl_depth o5                 */
4309     0x0200001f, 0x80000006, 0xe00f0006,                                     /* dcl_tangent o6               */
4310     0x0200001f, 0x80000001, 0xe00f0007,                                     /* dcl_blendweight o7           */
4311     0x05000051, 0xa00f0001, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c1, 0.1, 0.0, 0.0, 0.0   */
4312     0x05000051, 0xa00f0002, 0x00000000, 0x3e4ccccd, 0x00000000, 0x3f800000, /* def c2, 0.0, 0.2, 0.0, 1.0   */
4313     0x05000051, 0xa00f0003, 0x3ecccccd, 0x3f59999a, 0x3f666666, 0x00000000, /* def c3, 0.4, 0.85,0.9, 0.0   */
4314     0x05000051, 0xa00f0000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c0, 1.0, 1.0, 1.0, 1.0   */
4315
4316     0x02000001, 0xe00f0000, 0x90e40000,                                     /* mov o0, v0                   */
4317     0x02000001, 0xe00f0001, 0xa0e40001,                                     /* mov o1, c1                   */
4318     0x02000001, 0xe00f0002, 0xa0e40002,                                     /* mov o2, c2                   */
4319     0x02000001, 0xe00f0003, 0xa0e40003,                                     /* mov o3, c3                   */
4320     0x02000001, 0xe00f0004, 0xa0e40000,                                     /* mov o4, c0                   */
4321     0x02000001, 0xe00f0005, 0xa0e40000,                                     /* mov o5, c0                   */
4322     0x02000001, 0xe00f0006, 0xa0e40000,                                     /* mov o6, c0                   */
4323     0x02000001, 0xe00f0007, 0xa0e40000,                                     /* mov o7, c0                   */
4324     0x0000ffff                                                              /* end                          */
4325     };
4326     static const DWORD ps_1_code[] = {
4327     0xffff0104,                                                             /* ps_1_4                       */
4328     0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0   */
4329     0x00000040, 0x80070001, 0xb0e40000,                                     /* texcrd r1.xyz, t0            */
4330     0x00000001, 0x80080001, 0xa0ff0000,                                     /* mov r1.a, c0.a               */
4331     0x00000002, 0x800f0000, 0x90e40000, 0x80e40001,                         /* add r0, v0, r1               */
4332     0x0000ffff                                                              /* end                          */
4333     };
4334     static const DWORD ps_2_code[] = {
4335     0xffff0200,                                                             /* ps_2_0                       */
4336     0x0200001f, 0x80000000, 0xb00f0000,                                     /* dcl t0                       */
4337     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl v0                       */
4338     0x0200001f, 0x80000000, 0x900f0001,                                     /* dcl v1                       */
4339
4340     0x02000001, 0x800f0000, 0x90e40000,                                     /* mov r0, v0                   */
4341     0x03000002, 0x800f0000, 0x80e40000,0xb0e40000,                          /* add r0, r0, t0               */
4342     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
4343     0x0000ffff                                                              /* end                          */
4344     };
4345     static const DWORD ps_3_code[] = {
4346     0xffff0300,                                                             /* ps_3_0                       */
4347     0x0200001f, 0x80000005, 0x900f0000,                                     /* dcl_texcoord0 v0             */
4348     0x0200001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                */
4349     0x0200001f, 0x8000000b, 0x900f0002,                                     /* dcl_fog v2                   */
4350
4351     0x02000001, 0x800f0000, 0x90e40000,                                     /* mov r0, v0                   */
4352     0x03000002, 0x800f0000, 0x80e40000, 0x90e40001,                         /* add r0, r0, v1               */
4353     0x03000002, 0x800f0000, 0x80e40000, 0x90e40002,                         /* mov r0, r0, v2               */
4354     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
4355     0x0000ffff                                                              /* end                          */
4356     };
4357
4358     float quad1[] =  {
4359         -1.0,   -1.0,   0.1,
4360          0.0,   -1.0,   0.1,
4361         -1.0,    0.0,   0.1,
4362          0.0,    0.0,   0.1
4363     };
4364     float quad2[] =  {
4365          0.0,   -1.0,   0.1,
4366          1.0,   -1.0,   0.1,
4367          0.0,    0.0,   0.1,
4368          1.0,    0.0,   0.1
4369     };
4370     float quad3[] =  {
4371         -1.0,    0.0,   0.1,
4372          0.0,    0.0,   0.1,
4373         -1.0,    1.0,   0.1,
4374          0.0,    1.0,   0.1
4375     };
4376     float quad4[] =  {
4377          0.0,    0.0,   0.1,
4378          1.0,    0.0,   0.1,
4379          0.0,    1.0,   0.1,
4380          1.0,    1.0,   0.1
4381     };
4382
4383     HRESULT hr;
4384     DWORD color;
4385     IDirect3DVertexShader9 *vertexshader = NULL;
4386     IDirect3DPixelShader9 *ps_1_shader = NULL;
4387     IDirect3DPixelShader9 *ps_2_shader = NULL;
4388     IDirect3DPixelShader9 *ps_3_shader = NULL;
4389     IDirect3DTexture9 *texture = NULL;
4390     D3DLOCKED_RECT lr;
4391     unsigned int x, y;
4392
4393     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
4394
4395     hr = IDirect3DDevice9_CreateTexture(device, 512,  512, 1, 0, D3DFMT_A16B16G16R16, D3DPOOL_MANAGED, &texture, NULL);
4396     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %s\n", DXGetErrorString9(hr));
4397     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
4398     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %s\n", DXGetErrorString9(hr));
4399     for(y = 0; y < 512; y++) {
4400         for(x = 0; x < 512; x++) {
4401             double r_f = (double) x / (double) 512;
4402             double g_f = (double) y / (double) 512;
4403             unsigned short *dst = (unsigned short *) (((unsigned char *) lr.pBits) + y * lr.Pitch + x * 8);
4404             unsigned short r = (unsigned short) (r_f * 65535.0);
4405             unsigned short g = (unsigned short) (g_f * 65535.0);
4406             dst[0] = r;
4407             dst[1] = g;
4408             dst[2] = 0;
4409             dst[3] = 65535;
4410         }
4411     }
4412     hr = IDirect3DTexture9_UnlockRect(texture, 0);
4413     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect returned %s\n", DXGetErrorString9(hr));
4414
4415     hr = IDirect3DDevice9_CreateVertexShader(device, vs_code, &vertexshader);
4416     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4417     hr = IDirect3DDevice9_CreatePixelShader(device, ps_1_code, &ps_1_shader);
4418     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4419     hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_code, &ps_2_shader);
4420     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4421     hr = IDirect3DDevice9_CreatePixelShader(device, ps_3_code, &ps_3_shader);
4422     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4423     hr = IDirect3DDevice9_SetVertexShader(device, vertexshader);
4424     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4425     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4426
4427     hr = IDirect3DDevice9_BeginScene(device);
4428     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
4429     if(SUCCEEDED(hr))
4430     {
4431         hr = IDirect3DDevice9_SetPixelShader(device, ps_1_shader);
4432         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4433         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 3);
4434         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4435
4436         hr = IDirect3DDevice9_SetPixelShader(device, ps_2_shader);
4437         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4438         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2,  quad2, sizeof(float) * 3);
4439         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4440
4441         hr = IDirect3DDevice9_SetPixelShader(device, ps_3_shader);
4442         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4443         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 3);
4444         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4445
4446         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4447         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4448         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
4449         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
4450         hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
4451         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
4452         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
4453         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
4454         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 3);
4455         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4456
4457         hr = IDirect3DDevice9_EndScene(device);
4458         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
4459     }
4460     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4461     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4462
4463     color = getPixelColor(device, 160, 120);
4464     ok((color & 0x00ff0000) >= 0x00790000 && (color & 0x00ff0000) <= 0x00810000 &&
4465        (color & 0x0000ff00) == 0x0000ff00 &&
4466        (color & 0x000000ff) >= 0x000000e4 && (color & 0x000000ff) <= 0x000000e6,
4467        "ps_3_0 returned color 0x%08x, expected 0x0080ffe5\n", color);
4468     color = getPixelColor(device, 160, 360);
4469     ok((color & 0x00ff0000) >= 0x00190000 && (color & 0x00ff0000) <= 0x00210000 &&
4470        (color & 0x0000ff00) >= 0x00003300 && (color & 0x0000ff00) <= 0x00003400 &&
4471        (color & 0x000000ff) == 0x00000000,
4472        "ps_1_4 returned color 0x%08x, expected 0x00203300\n", color);
4473     color = getPixelColor(device, 480, 360);
4474     ok((color & 0x00ff0000) >= 0x00190000 && (color & 0x00ff0000) <= 0x00210000 &&
4475        (color & 0x0000ff00) >= 0x00003200 && (color & 0x0000ff00) <= 0x00003400 &&
4476        (color & 0x000000ff) == 0x00000000,
4477        "ps_2_0 returned color 0x%08x, expected 0x00203300\n", color);
4478     color = getPixelColor(device, 480, 160);
4479     ok((color & 0x00ff0000) >= 0x00190000 && (color & 0x00ff0000) <= 0x00210000 &&
4480        (color & 0x0000ff00) >= 0x00003200 && (color & 0x0000ff00) <= 0x00003400 &&
4481        (color & 0x000000ff) == 0x00000000,
4482        "fixed function fragment processing returned color 0x%08x, expected 0x00203300\n", color);
4483
4484     /* cleanup */
4485     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4486     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
4487     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4488     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4489     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
4490     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4491     if(vertexshader) IDirect3DVertexShader9_Release(vertexshader);
4492     if(ps_1_shader) IDirect3DPixelShader9_Release(ps_1_shader);
4493     if(ps_2_shader) IDirect3DPixelShader9_Release(ps_2_shader);
4494     if(ps_3_shader) IDirect3DPixelShader9_Release(ps_3_shader);
4495     if(texture) IDirect3DTexture9_Release(texture);
4496 }
4497
4498 void test_compare_instructions(IDirect3DDevice9 *device)
4499 {
4500     DWORD shader_sge_vec_code[] = {
4501         0xfffe0101,                                         /* vs_1_1                   */
4502         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
4503         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
4504         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
4505         0x0000000d, 0xd00f0000, 0x80e40000, 0xa0e40001,     /* sge oD0, r0, c1          */
4506         0x0000ffff                                          /* end                      */
4507     };
4508     DWORD shader_slt_vec_code[] = {
4509         0xfffe0101,                                         /* vs_1_1                   */
4510         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
4511         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
4512         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
4513         0x0000000c, 0xd00f0000, 0x80e40000, 0xa0e40001,     /* slt oD0, r0, c1          */
4514         0x0000ffff                                          /* end                      */
4515     };
4516     DWORD shader_sge_scalar_code[] = {
4517         0xfffe0101,                                         /* vs_1_1                   */
4518         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
4519         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
4520         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
4521         0x0000000d, 0xd0010000, 0x80000000, 0xa0550001,     /* slt oD0.r, r0.r, c1.b    */
4522         0x0000000d, 0xd0020000, 0x80550000, 0xa0aa0001,     /* slt oD0.g, r0.g, c1.r    */
4523         0x0000000d, 0xd0040000, 0x80aa0000, 0xa0000001,     /* slt oD0.b, r0.b, c1.g    */
4524         0x0000ffff                                          /* end                      */
4525     };
4526     DWORD shader_slt_scalar_code[] = {
4527         0xfffe0101,                                         /* vs_1_1                   */
4528         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
4529         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
4530         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
4531         0x0000000c, 0xd0010000, 0x80000000, 0xa0aa0001,     /* slt oD0.r, r0.r, c1.b    */
4532         0x0000000c, 0xd0020000, 0x80550000, 0xa0000001,     /* slt oD0.g, r0.g, c1.r    */
4533         0x0000000c, 0xd0040000, 0x80aa0000, 0xa0550001,     /* slt oD0.b, r0.b, c1.g    */
4534         0x0000ffff                                          /* end                      */
4535     };
4536     IDirect3DVertexShader9 *shader_sge_vec;
4537     IDirect3DVertexShader9 *shader_slt_vec;
4538     IDirect3DVertexShader9 *shader_sge_scalar;
4539     IDirect3DVertexShader9 *shader_slt_scalar;
4540     HRESULT hr, color;
4541     float quad1[] =  {
4542         -1.0,   -1.0,   0.1,
4543          0.0,   -1.0,   0.1,
4544         -1.0,    0.0,   0.1,
4545          0.0,    0.0,   0.1
4546     };
4547     float quad2[] =  {
4548          0.0,   -1.0,   0.1,
4549          1.0,   -1.0,   0.1,
4550          0.0,    0.0,   0.1,
4551          1.0,    0.0,   0.1
4552     };
4553     float quad3[] =  {
4554         -1.0,    0.0,   0.1,
4555          0.0,    0.0,   0.1,
4556         -1.0,    1.0,   0.1,
4557          0.0,    1.0,   0.1
4558     };
4559     float quad4[] =  {
4560          0.0,    0.0,   0.1,
4561          1.0,    0.0,   0.1,
4562          0.0,    1.0,   0.1,
4563          1.0,    1.0,   0.1
4564     };
4565     const float const0[4] = {0.8, 0.2, 0.2, 0.2};
4566     const float const1[4] = {0.2, 0.8, 0.2, 0.2};
4567
4568     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
4569
4570     hr = IDirect3DDevice9_CreateVertexShader(device, shader_sge_vec_code, &shader_sge_vec);
4571     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4572     hr = IDirect3DDevice9_CreateVertexShader(device, shader_slt_vec_code, &shader_slt_vec);
4573     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4574     hr = IDirect3DDevice9_CreateVertexShader(device, shader_sge_scalar_code, &shader_sge_scalar);
4575     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4576     hr = IDirect3DDevice9_CreateVertexShader(device, shader_slt_scalar_code, &shader_slt_scalar);
4577     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4578     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, const0, 1);
4579     ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
4580     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, const1, 1);
4581     ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
4582     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4583     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetFVF failed (%08x)\n", hr);
4584
4585     hr = IDirect3DDevice9_BeginScene(device);
4586     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
4587     if(SUCCEEDED(hr))
4588     {
4589         hr = IDirect3DDevice9_SetVertexShader(device, shader_sge_vec);
4590         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4591         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 3);
4592         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4593
4594         hr = IDirect3DDevice9_SetVertexShader(device, shader_slt_vec);
4595         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4596         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2,  quad2, sizeof(float) * 3);
4597         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4598
4599         hr = IDirect3DDevice9_SetVertexShader(device, shader_sge_scalar);
4600         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4601         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 3);
4602         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4603
4604         hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, const0, 1);
4605         ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
4606
4607         hr = IDirect3DDevice9_SetVertexShader(device, shader_slt_scalar);
4608         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4609         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 3);
4610         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4611
4612         hr = IDirect3DDevice9_EndScene(device);
4613         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
4614     }
4615
4616     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4617     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4618
4619     color = getPixelColor(device, 160, 360);
4620     ok(color == 0x00FF00FF, "Compare test: Quad 1(sge vec) returned color 0x%08x, expected 0x00FF00FF\n", color);
4621     color = getPixelColor(device, 480, 360);
4622     ok(color == 0x0000FF00, "Compare test: Quad 2(slt vec) returned color 0x%08x, expected 0x0000FF00\n", color);
4623     color = getPixelColor(device, 160, 120);
4624     ok(color == 0x00FFFFFF, "Compare test: Quad 3(sge scalar) returned color 0x%08x, expected 0x00FFFFFF\n", color);
4625     color = getPixelColor(device, 480, 160);
4626     ok(color == 0x000000ff, "Compare test: Quad 4(slt scalar) returned color 0x%08x, expected 0x000000ff\n", color);
4627
4628     IDirect3DVertexShader9_Release(shader_sge_vec);
4629     IDirect3DVertexShader9_Release(shader_slt_vec);
4630     IDirect3DVertexShader9_Release(shader_sge_scalar);
4631     IDirect3DVertexShader9_Release(shader_slt_scalar);
4632 }
4633
4634 void test_vshader_input(IDirect3DDevice9 *device)
4635 {
4636     DWORD swapped_shader_code_3[] = {
4637         0xfffe0300,                                         /* vs_3_0               */
4638         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
4639         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
4640         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
4641         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
4642         0x0200001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
4643         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
4644         0x02000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
4645         0x03000002, 0xe00f0001, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
4646         0x0000ffff                                          /* end                  */
4647     };
4648     DWORD swapped_shader_code_1[] = {
4649         0xfffe0101,                                         /* vs_1_1               */
4650         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
4651         0x0000001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
4652         0x0000001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
4653         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov o0, v0           */
4654         0x00000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
4655         0x00000002, 0xd00f0000, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
4656         0x0000ffff                                          /* end                  */
4657     };
4658     DWORD swapped_shader_code_2[] = {
4659         0xfffe0200,                                         /* vs_2_0               */
4660         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
4661         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
4662         0x0200001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
4663         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov o0, v0           */
4664         0x02000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
4665         0x03000002, 0xd00f0000, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
4666         0x0000ffff                                          /* end                  */
4667     };
4668     DWORD texcoord_color_shader_code_3[] = {
4669         0xfffe0300,                                         /* vs_3_0               */
4670         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
4671         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
4672         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
4673         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
4674         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
4675         0x02000001, 0xe00f0001, 0x90e40001,                 /* mov o1, v1           */
4676         0x0000ffff                                          /* end                  */
4677     };
4678     DWORD texcoord_color_shader_code_2[] = {
4679         0xfffe0200,                                         /* vs_2_0               */
4680         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
4681         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
4682         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
4683         0x02000001, 0xd00f0000, 0x90e40001,                 /* mov oD0, v1          */
4684         0x0000ffff                                          /* end                  */
4685     };
4686     DWORD texcoord_color_shader_code_1[] = {
4687         0xfffe0101,                                         /* vs_1_1               */
4688         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
4689         0x0000001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
4690         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
4691         0x00000001, 0xd00f0000, 0x90e40001,                 /* mov oD0, v1          */
4692         0x0000ffff                                          /* end                  */
4693     };
4694     DWORD color_color_shader_code_3[] = {
4695         0xfffe0300,                                         /* vs_3_0               */
4696         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
4697         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
4698         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
4699         0x0200001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
4700         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
4701         0x03000005, 0xe00f0001, 0xa0e40000, 0x90e40001,     /* mul o1, c0, v1       */
4702         0x0000ffff                                          /* end                  */
4703     };
4704     DWORD color_color_shader_code_2[] = {
4705         0xfffe0200,                                         /* vs_2_0               */
4706         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
4707         0x0200001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
4708         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
4709         0x03000005, 0xd00f0000, 0xa0e40000, 0x90e40001,     /* mul oD0, c0, v1       */
4710         0x0000ffff                                          /* end                  */
4711     };
4712     DWORD color_color_shader_code_1[] = {
4713         0xfffe0101,                                         /* vs_1_1               */
4714         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
4715         0x0000001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
4716         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
4717         0x00000005, 0xd00f0000, 0xa0e40000, 0x90e40001,     /* mul oD0, c0, v1       */
4718         0x0000ffff                                          /* end                  */
4719     };
4720     IDirect3DVertexShader9 *swapped_shader, *texcoord_color_shader, *color_color_shader;
4721     HRESULT hr;
4722     DWORD color, r, g, b;
4723     float quad1[] =  {
4724         -1.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
4725          0.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
4726         -1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
4727          0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
4728     };
4729     float quad2[] =  {
4730          0.0,   -1.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
4731          1.0,   -1.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
4732          0.0,    0.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
4733          1.0,    0.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
4734     };
4735     float quad3[] =  {
4736         -1.0,    0.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    1.0,    -1.0,   0.0,    0.0,
4737          0.0,    0.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    1.0,     0.0,   0.0,    0.0,
4738         -1.0,    1.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    0.0,    -1.0,   1.0,    0.0,
4739          0.0,    1.0,   0.1,   -1.0,    0.0,    0.0,    0.0,   -1.0,     0.0,   0.0,    0.0,
4740     };
4741     float quad4[] =  {
4742          0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
4743          1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
4744          0.0,    1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
4745          1.0,    1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
4746     };
4747     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd[] = {
4748         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
4749         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
4750         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
4751         D3DDECL_END()
4752     };
4753     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd_rightorder[] = {
4754         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
4755         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
4756         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
4757         D3DDECL_END()
4758     };
4759     static const D3DVERTEXELEMENT9 decl_elements_onetexcrd[] = {
4760         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
4761         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
4762         D3DDECL_END()
4763     };
4764     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd_wrongidx[] = {
4765         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
4766         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
4767         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       2},
4768         D3DDECL_END()
4769     };
4770     static const D3DVERTEXELEMENT9 decl_elements_texcoord_color[] = {
4771         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
4772         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
4773         D3DDECL_END()
4774     };
4775     static const D3DVERTEXELEMENT9 decl_elements_color_color[] = {
4776         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
4777         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
4778         D3DDECL_END()
4779     };
4780     static const D3DVERTEXELEMENT9 decl_elements_color_ubyte[] = {
4781         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
4782         {0,  12,  D3DDECLTYPE_UBYTE4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
4783         D3DDECL_END()
4784     };
4785     static const D3DVERTEXELEMENT9 decl_elements_color_float[] = {
4786         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
4787         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
4788         D3DDECL_END()
4789     };
4790     IDirect3DVertexDeclaration9 *decl_twotexcrd, *decl_onetexcrd, *decl_twotex_wrongidx, *decl_twotexcrd_rightorder;
4791     IDirect3DVertexDeclaration9 *decl_texcoord_color, *decl_color_color, *decl_color_ubyte, *decl_color_float;
4792     unsigned int i;
4793     float normalize[4] = {1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0};
4794     float no_normalize[4] = {1.0, 1.0, 1.0, 1.0};
4795
4796     struct vertex quad1_color[] =  {
4797        {-1.0,   -1.0,   0.1,    0x00ff8040},
4798        { 0.0,   -1.0,   0.1,    0x00ff8040},
4799        {-1.0,    0.0,   0.1,    0x00ff8040},
4800        { 0.0,    0.0,   0.1,    0x00ff8040}
4801     };
4802     struct vertex quad2_color[] =  {
4803        { 0.0,   -1.0,   0.1,    0x00ff8040},
4804        { 1.0,   -1.0,   0.1,    0x00ff8040},
4805        { 0.0,    0.0,   0.1,    0x00ff8040},
4806        { 1.0,    0.0,   0.1,    0x00ff8040}
4807     };
4808     struct vertex quad3_color[] =  {
4809        {-1.0,    0.0,   0.1,    0x00ff8040},
4810        { 0.0,    0.0,   0.1,    0x00ff8040},
4811        {-1.0,    1.0,   0.1,    0x00ff8040},
4812        { 0.0,    1.0,   0.1,    0x00ff8040}
4813     };
4814     float quad4_color[] =  {
4815          0.0,    0.0,   0.1,    1.0,    1.0,    0.0,    0.0,
4816          1.0,    0.0,   0.1,    1.0,    1.0,    0.0,    1.0,
4817          0.0,    1.0,   0.1,    1.0,    1.0,    0.0,    0.0,
4818          1.0,    1.0,   0.1,    1.0,    1.0,    0.0,    1.0,
4819     };
4820
4821     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd, &decl_twotexcrd);
4822     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4823     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_onetexcrd, &decl_onetexcrd);
4824     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4825     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd_wrongidx, &decl_twotex_wrongidx);
4826     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4827     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd_rightorder, &decl_twotexcrd_rightorder);
4828     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4829
4830     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_texcoord_color, &decl_texcoord_color);
4831     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4832     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_color, &decl_color_color);
4833     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4834     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_ubyte, &decl_color_ubyte);
4835     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4836     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_float, &decl_color_float);
4837     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4838
4839     for(i = 1; i <= 3; i++) {
4840         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
4841         if(i == 3) {
4842             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_3, &swapped_shader);
4843             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4844         } else if(i == 2){
4845             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_2, &swapped_shader);
4846             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4847         } else if(i == 1) {
4848             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_1, &swapped_shader);
4849             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4850         }
4851
4852         hr = IDirect3DDevice9_BeginScene(device);
4853         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
4854         if(SUCCEEDED(hr))
4855         {
4856             hr = IDirect3DDevice9_SetVertexShader(device, swapped_shader);
4857             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4858
4859             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd);
4860             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4861             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 11);
4862             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4863
4864             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_onetexcrd);
4865             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4866             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(float) * 11);
4867             if(i == 3 || i == 2) {
4868                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
4869             } else if(i == 1) {
4870                 /* Succeeds or fails, depending on SW or HW vertex processing */
4871                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x), i = 1\n", hr);
4872             }
4873
4874             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd_rightorder);
4875             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4876             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 11);
4877             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4878
4879             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotex_wrongidx);
4880             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4881             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 11);
4882             if(i == 3 || i == 2) {
4883                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
4884             } else if(i == 1) {
4885                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = 1\n", hr);
4886             }
4887
4888             hr = IDirect3DDevice9_EndScene(device);
4889             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
4890         }
4891
4892         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4893         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4894
4895         if(i == 3 || i == 2) {
4896             color = getPixelColor(device, 160, 360);
4897             ok(color == 0x00FFFF80 || color == 0x00FFFF7f || color == 0x00FFFF81,
4898                "Input test: Quad 1(2crd) returned color 0x%08x, expected 0x00FFFF80\n", color);
4899
4900             /* The last value of the read but undefined stream is used */
4901             color = getPixelColor(device, 480, 360);
4902             ok(color == 0x00FFFF00, "Input test: Quad 2(1crd) returned color 0x%08x, expected 0x00FFFF00\n", color);
4903             color = getPixelColor(device, 160, 120);
4904             ok(color == 0x00FF0080 || color == 0x00FF007f || color == 0x00FF0081,
4905                "Input test: Quad 3(2crd-wrongidx) returned color 0x%08x, expected 0x00FF0080\n", color);
4906
4907             color = getPixelColor(device, 480, 160);
4908             ok(color == 0x00000000, "Input test: Quad 4(2crd-rightorder) returned color 0x%08x, expected 0x00000000\n", color);
4909         } else if(i == 1) {
4910             color = getPixelColor(device, 160, 360);
4911             ok(color == 0x00FFFF80 || color == 0x00FFFF7f || color == 0x00FFFF81,
4912                "Input test: Quad 1(2crd) returned color 0x%08x, expected 0x00FFFF80\n", color);
4913             color = getPixelColor(device, 480, 360);
4914             /* Accept the clear color as well in this case, since SW VP returns an error */
4915             ok(color == 0x00FFFF00 || color == 0x00FF0000, "Input test: Quad 2(1crd) returned color 0x%08x, expected 0x00FFFF00\n", color);
4916             color = getPixelColor(device, 160, 120);
4917             ok(color == 0x00FF0080 || color == 0x00FF0000 || color == 0x00FF007f || color == 0x00FF0081,
4918                "Input test: Quad 3(2crd-wrongidx) returned color 0x%08x, expected 0x00FF0080\n", color);
4919             color = getPixelColor(device, 480, 160);
4920             ok(color == 0x00000000, "Input test: Quad 4(2crd-rightorder) returned color 0x%08x, expected 0x00000000\n", color);
4921         }
4922
4923         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff808080, 0.0, 0);
4924         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
4925
4926         /* Now find out if the whole streams are re-read, or just the last active value for the
4927          * vertices is used.
4928          */
4929         hr = IDirect3DDevice9_BeginScene(device);
4930         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
4931         if(SUCCEEDED(hr))
4932         {
4933             float quad1_modified[] =  {
4934                 -1.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,   -1.0,     0.0,   0.0,    0.0,
4935                  0.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.0,    0.0,
4936                 -1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,     0.0,  -1.0,    0.0,
4937                  0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,   -1.0,    -1.0,  -1.0,    0.0,
4938             };
4939             float quad2_modified[] =  {
4940                  0.0,   -1.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
4941                  1.0,   -1.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
4942                  0.0,    0.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
4943                  1.0,    0.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
4944             };
4945
4946             hr = IDirect3DDevice9_SetVertexShader(device, swapped_shader);
4947             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4948
4949             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd);
4950             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4951             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 3, quad1_modified, sizeof(float) * 11);
4952             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4953
4954             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_onetexcrd);
4955             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4956             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2_modified, sizeof(float) * 11);
4957             if(i == 3 || i == 2) {
4958                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
4959             } else if(i == 1) {
4960                 /* Succeeds or fails, depending on SW or HW vertex processing */
4961                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x), i = 1\n", hr);
4962             }
4963
4964             hr = IDirect3DDevice9_EndScene(device);
4965             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
4966         }
4967         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4968         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4969
4970         color = getPixelColor(device, 480, 360);
4971         /* vs_1_1 may fail, accept the clear color */
4972         ok(color == 0x000000FF || color == 0x00808080,
4973            "Input test: Quad 2(different colors) returned color 0x%08x, expected 0x000000FF\n", color);
4974         color = getPixelColor(device, 160, 120);
4975
4976         IDirect3DDevice9_SetVertexShader(device, NULL);
4977         IDirect3DDevice9_SetVertexDeclaration(device, NULL);
4978
4979         IDirect3DVertexShader9_Release(swapped_shader);
4980     }
4981
4982     for(i = 1; i <= 3; i++) {
4983         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
4984         if(i == 3) {
4985             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_3, &texcoord_color_shader);
4986             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4987             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_3, &color_color_shader);
4988             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4989         } else if(i == 2){
4990             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_2, &texcoord_color_shader);
4991             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4992             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_2, &color_color_shader);
4993             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4994         } else if(i == 1) {
4995             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_1, &texcoord_color_shader);
4996             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4997             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_1, &color_color_shader);
4998             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4999         }
5000
5001         hr = IDirect3DDevice9_BeginScene(device);
5002         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
5003         if(SUCCEEDED(hr))
5004         {
5005             hr = IDirect3DDevice9_SetVertexShader(device, texcoord_color_shader);
5006             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5007             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_texcoord_color);
5008             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
5009             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1_color, sizeof(quad1_color[0]));
5010             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5011
5012             hr = IDirect3DDevice9_SetVertexShader(device, color_color_shader);
5013             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5014
5015             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, normalize, 1);
5016             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5017             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_ubyte);
5018             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
5019             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2_color, sizeof(quad2_color[0]));
5020             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5021
5022             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, no_normalize, 1);
5023             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5024             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_color);
5025             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
5026             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3_color, sizeof(quad3_color[0]));
5027             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5028
5029             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_float);
5030             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
5031             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4_color, sizeof(float) * 7);
5032             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5033
5034             hr = IDirect3DDevice9_EndScene(device);
5035             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
5036         }
5037         IDirect3DDevice9_SetVertexShader(device, NULL);
5038         IDirect3DDevice9_SetVertexDeclaration(device, NULL);
5039
5040         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5041         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
5042
5043         color = getPixelColor(device, 160, 360);
5044         r = (color & 0x00ff0000) >> 16;
5045         g = (color & 0x0000ff00) >>  8;
5046         b = (color & 0x000000ff) >>  0;
5047         ok(r >= 0xfe && r <= 0xff && g >= 0x7f && g <= 0x81 && b >= 0x3f && b <= 0x41,
5048            "Input test: Quad 1(color-texcoord) returned color 0x%08x, expected 0x00ff8040\n", color);
5049         color = getPixelColor(device, 480, 360);
5050         r = (color & 0x00ff0000) >> 16;
5051         g = (color & 0x0000ff00) >>  8;
5052         b = (color & 0x000000ff) >>  0;
5053         ok(r >= 0x3f && r <= 0x41 && g >= 0x7f && g <= 0x81 && b >= 0xfe && b <= 0xff,
5054            "Input test: Quad 2(color-ubyte) returned color 0x%08x, expected 0x004080ff\n", color);
5055         color = getPixelColor(device, 160, 120);
5056         r = (color & 0x00ff0000) >> 16;
5057         g = (color & 0x0000ff00) >>  8;
5058         b = (color & 0x000000ff) >>  0;
5059         ok(r >= 0xfe && r <= 0xff && g >= 0x7f && g <= 0x81 && b >= 0x3f && b <= 0x41,
5060            "Input test: Quad 3(color-color) returned color 0x%08x, expected 0x00ff8040\n", color);
5061         color = getPixelColor(device, 480, 160);
5062         r = (color & 0x00ff0000) >> 16;
5063         g = (color & 0x0000ff00) >>  8;
5064         b = (color & 0x000000ff) >>  0;
5065         ok(r >= 0xfe && r <= 0xff && g >= 0xfe && g <= 0xff && b >= 0x00 && b <= 0x01,
5066            "Input test: Quad 4(color-float) returned color 0x%08x, expected 0x00FFFF00\n", color);
5067
5068         IDirect3DVertexShader9_Release(texcoord_color_shader);
5069         IDirect3DVertexShader9_Release(color_color_shader);
5070     }
5071
5072     IDirect3DVertexDeclaration9_Release(decl_twotexcrd);
5073     IDirect3DVertexDeclaration9_Release(decl_onetexcrd);
5074     IDirect3DVertexDeclaration9_Release(decl_twotex_wrongidx);
5075     IDirect3DVertexDeclaration9_Release(decl_twotexcrd_rightorder);
5076
5077     IDirect3DVertexDeclaration9_Release(decl_texcoord_color);
5078     IDirect3DVertexDeclaration9_Release(decl_color_color);
5079     IDirect3DVertexDeclaration9_Release(decl_color_ubyte);
5080     IDirect3DVertexDeclaration9_Release(decl_color_float);
5081 }
5082
5083 static void fog_srgbwrite_test(IDirect3DDevice9 *device)
5084 {
5085     /* Draw a black quad, half fogged with white fog -> grey color. Enable sRGB writing.
5086      * if sRGB writing is applied before fogging, the 0.0 will be multiplied with ~ 12.92, so still
5087      * stay 0.0. After that the fog gives 0.5. If sRGB writing is applied after fogging, the
5088      * 0.5 will run through the alternative path(0^5 ^ 0.41666 * 1.055 - 0.055), resulting in approx.
5089      * 0.73
5090      *
5091      * At the time of this writing, wined3d could not apply sRGB correction to fixed function rendering,
5092      * so use shaders for this task
5093      */
5094     IDirect3DPixelShader9 *pshader;
5095     IDirect3DVertexShader9 *vshader;
5096     IDirect3D9 *d3d;
5097     DWORD vshader_code[] = {
5098         0xfffe0101,                                                             /* vs_1_1                       */
5099         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
5100         0x00000051, 0xa00f0000, 0x3f000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.5, 0.0, 0.0, 0.0   */
5101         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
5102         0x00000001, 0xc00f0001, 0xa0000000,                                     /* mov oFog, c0.x               */
5103         0x0000ffff                                                              /* end                          */
5104     };
5105     DWORD pshader_code[] = {
5106         0xffff0101,                                                             /* ps_1_1                       */
5107         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0   */
5108         0x00000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                   */
5109         0x0000ffff                                                              /* end                          */
5110     };
5111     const float quad[] = {
5112        -1.0,   -1.0,    0.1,
5113         1.0,   -1.0,    0.1,
5114        -1.0,    1.0,    0.1,
5115         1.0,    1.0,    0.1
5116     };
5117     HRESULT hr;
5118     DWORD color;
5119
5120     IDirect3DDevice9_GetDirect3D(device, &d3d);
5121     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
5122                                     D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE,
5123                                     D3DRTYPE_SURFACE, D3DFMT_A8R8G8B8) != D3D_OK) {
5124         skip("No SRGBWRITEENABLE support on D3DFMT_X8R8G8B8\n");
5125         IDirect3D9_Release(d3d);
5126         return;
5127     }
5128     IDirect3D9_Release(d3d);
5129
5130     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
5131     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
5132
5133     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
5134     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
5135     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
5136     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
5137     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
5138     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
5139     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xffffffff);
5140     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
5141     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, TRUE);
5142     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
5143
5144     hr = IDirect3DDevice9_CreateVertexShader(device, vshader_code, &vshader);
5145     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
5146     hr = IDirect3DDevice9_CreatePixelShader(device, pshader_code, &pshader);
5147     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
5148     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5149     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
5150     hr = IDirect3DDevice9_SetVertexShader(device, vshader);
5151     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5152     hr = IDirect3DDevice9_SetPixelShader(device, pshader);
5153     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
5154
5155     hr = IDirect3DDevice9_BeginScene(device);
5156     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
5157     if(SUCCEEDED(hr)) {
5158         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 3);
5159         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5160
5161         hr = IDirect3DDevice9_EndScene(device);
5162         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
5163     }
5164
5165     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
5166     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5167     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5168     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
5169     IDirect3DPixelShader9_Release(pshader);
5170     IDirect3DVertexShader9_Release(vshader);
5171
5172     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
5173     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
5174     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, FALSE);
5175     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
5176
5177     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5178     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
5179     color = getPixelColor(device, 160, 360);
5180     ok(color == 0x00808080 || color == 0x007f7f7f || color == 0x00818181,
5181        "Fog with D3DRS_SRGBWRITEENABLE returned color 0x%08x, expected 0x00808080\n", color);
5182 }
5183
5184 static void alpha_test(IDirect3DDevice9 *device)
5185 {
5186     HRESULT hr;
5187     IDirect3DTexture9 *offscreenTexture;
5188     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
5189     DWORD color, red, green, blue;
5190
5191     struct vertex quad1[] =
5192     {
5193         {-1.0f, -1.0f,   0.1f,                          0x4000ff00},
5194         {-1.0f,  0.0f,   0.1f,                          0x4000ff00},
5195         { 1.0f, -1.0f,   0.1f,                          0x4000ff00},
5196         { 1.0f,  0.0f,   0.1f,                          0x4000ff00},
5197     };
5198     struct vertex quad2[] =
5199     {
5200         {-1.0f,  0.0f,   0.1f,                          0xc00000ff},
5201         {-1.0f,  1.0f,   0.1f,                          0xc00000ff},
5202         { 1.0f,  0.0f,   0.1f,                          0xc00000ff},
5203         { 1.0f,  1.0f,   0.1f,                          0xc00000ff},
5204     };
5205     static const float composite_quad[][5] = {
5206         { 0.0f, -1.0f, 0.1f, 0.0f, 1.0f},
5207         { 0.0f,  1.0f, 0.1f, 0.0f, 0.0f},
5208         { 1.0f, -1.0f, 0.1f, 1.0f, 1.0f},
5209         { 1.0f,  1.0f, 0.1f, 1.0f, 0.0f},
5210     };
5211
5212     /* Clear the render target with alpha = 0.5 */
5213     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
5214     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
5215
5216     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
5217     ok(hr == D3D_OK || D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr);
5218
5219     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
5220     ok(hr == D3D_OK, "Can't get back buffer, hr = %s\n", DXGetErrorString9(hr));
5221     if(!backbuffer) {
5222         goto out;
5223     }
5224
5225     hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
5226     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %s\n", DXGetErrorString9(hr));
5227     if(!offscreen) {
5228         goto out;
5229     }
5230
5231     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
5232     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr);
5233
5234     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
5235     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
5236     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
5237     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
5238     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
5239     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
5240     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
5241     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
5242     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
5243     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
5244
5245     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
5246     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
5247     if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
5248
5249         /* Draw two quads, one with src alpha blending, one with dest alpha blending. The
5250          * SRCALPHA / INVSRCALPHA blend doesn't give any surprises. Colors are blended based on
5251          * the input alpha
5252          *
5253          * The DESTALPHA / INVDESTALPHA do not "work" on the regular buffer because there is no alpha.
5254          * They give essentially ZERO and ONE blend factors
5255          */
5256         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
5257         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
5258         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
5259         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
5260         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
5261         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
5262
5263         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
5264         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
5265         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
5266         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
5267         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
5268         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
5269
5270         /* Switch to the offscreen buffer, and redo the testing. SRCALPHA and DESTALPHA. The offscreen buffer
5271          * has a alpha channel on its own. Clear the offscreen buffer with alpha = 0.5 again, then draw the
5272          * quads again. The SRCALPHA/INVSRCALPHA doesn't give any surprises, but the DESTALPHA/INVDESTALPHA
5273          * blending works as supposed now - blend factor is 0.5 in both cases, not 0.75 as from the input
5274          * vertices
5275          */
5276         hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
5277         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
5278         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
5279         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
5280
5281         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
5282         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
5283         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
5284         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
5285         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
5286         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
5287
5288         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
5289         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
5290         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
5291         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
5292         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
5293         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
5294
5295         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
5296         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
5297
5298         /* Render the offscreen texture onto the frame buffer to be able to compare it regularly.
5299          * Disable alpha blending for the final composition
5300          */
5301         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
5302         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
5303         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
5304         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr);
5305
5306         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
5307         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr = %08x\n", hr);
5308         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, composite_quad, sizeof(float) * 5);
5309         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
5310         hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
5311         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr = %08x\n", hr);
5312
5313         hr = IDirect3DDevice9_EndScene(device);
5314         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
5315     }
5316
5317     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5318
5319     color = getPixelColor(device, 160, 360);
5320     red =   (color & 0x00ff0000) >> 16;
5321     green = (color & 0x0000ff00) >>  8;
5322     blue =  (color & 0x000000ff);
5323     ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
5324        "SRCALPHA on frame buffer returned color %08x, expected 0x00bf4000\n", color);
5325
5326     color = getPixelColor(device, 160, 120);
5327     red =   (color & 0x00ff0000) >> 16;
5328     green = (color & 0x0000ff00) >>  8;
5329     blue =  (color & 0x000000ff);
5330     ok(red == 0x00 && green == 0x00 && blue >= 0xfe && blue <= 0xff ,
5331        "DSTALPHA on frame buffer returned color %08x, expected 0x00ff0000\n", color);
5332
5333     color = getPixelColor(device, 480, 360);
5334     red =   (color & 0x00ff0000) >> 16;
5335     green = (color & 0x0000ff00) >>  8;
5336     blue =  (color & 0x000000ff);
5337     ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
5338        "SRCALPHA on texture returned color %08x, expected bar\n", color);
5339
5340     color = getPixelColor(device, 480, 120);
5341     red =   (color & 0x00ff0000) >> 16;
5342     green = (color & 0x0000ff00) >>  8;
5343     blue =  (color & 0x000000ff);
5344     ok(red >= 0x7e && red <= 0x81 && green == 0x00 && blue >= 0x7e && blue <= 0x81,
5345        "DSTALPHA on texture returned color %08x, expected foo\n", color);
5346
5347     out:
5348     /* restore things */
5349     if(backbuffer) {
5350         IDirect3DSurface9_Release(backbuffer);
5351     }
5352     if(offscreenTexture) {
5353         IDirect3DTexture9_Release(offscreenTexture);
5354     }
5355     if(offscreen) {
5356         IDirect3DSurface9_Release(offscreen);
5357     }
5358 }
5359
5360 START_TEST(visual)
5361 {
5362     IDirect3DDevice9 *device_ptr;
5363     D3DCAPS9 caps;
5364     HRESULT hr;
5365     DWORD color;
5366
5367     d3d9_handle = LoadLibraryA("d3d9.dll");
5368     if (!d3d9_handle)
5369     {
5370         skip("Could not load d3d9.dll\n");
5371         return;
5372     }
5373
5374     device_ptr = init_d3d9();
5375     if (!device_ptr)
5376     {
5377         skip("Creating the device failed\n");
5378         return;
5379     }
5380
5381     IDirect3DDevice9_GetDeviceCaps(device_ptr, &caps);
5382
5383     /* Check for the reliability of the returned data */
5384     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
5385     if(FAILED(hr))
5386     {
5387         trace("Clear failed, can't assure correctness of the test results, skipping\n");
5388         goto cleanup;
5389     }
5390     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
5391
5392     color = getPixelColor(device_ptr, 1, 1);
5393     if(color !=0x00ff0000)
5394     {
5395         trace("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
5396         goto cleanup;
5397     }
5398
5399     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xff00ddee, 0.0, 0);
5400     if(FAILED(hr))
5401     {
5402         trace("Clear failed, can't assure correctness of the test results, skipping\n");
5403         goto cleanup;
5404     }
5405     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
5406
5407     color = getPixelColor(device_ptr, 639, 479);
5408     if(color != 0x0000ddee)
5409     {
5410         trace("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
5411         goto cleanup;
5412     }
5413
5414     /* Now execute the real tests */
5415     lighting_test(device_ptr);
5416     clear_test(device_ptr);
5417     fog_test(device_ptr);
5418     if(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
5419     {
5420         test_cube_wrap(device_ptr);
5421     } else {
5422         skip("No cube texture support\n");
5423     }
5424     z_range_test(device_ptr);
5425     if(caps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)
5426     {
5427         maxmip_test(device_ptr);
5428     }
5429     else
5430     {
5431         skip("No mipmap support\n");
5432     }
5433     offscreen_test(device_ptr);
5434     alpha_test(device_ptr);
5435     release_buffer_test(device_ptr);
5436     float_texture_test(device_ptr);
5437     texture_transform_flags_test(device_ptr);
5438     autogen_mipmap_test(device_ptr);
5439
5440     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1))
5441     {
5442         test_constant_clamp_vs(device_ptr);
5443         test_compare_instructions(device_ptr);
5444     }
5445     else skip("No vs_1_1 support\n");
5446
5447     if (caps.VertexShaderVersion >= D3DVS_VERSION(2, 0))
5448     {
5449         test_mova(device_ptr);
5450         if (caps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) {
5451             test_vshader_input(device_ptr);
5452         } else {
5453             skip("No vs_3_0 support\n");
5454         }
5455     }
5456     else skip("No vs_2_0 support\n");
5457
5458     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1) && caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
5459     {
5460         fog_with_shader_test(device_ptr);
5461         fog_srgbwrite_test(device_ptr);
5462     }
5463     else skip("No vs_1_1 and ps_1_1 support\n");
5464
5465     if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
5466     {
5467         texbem_test(device_ptr);
5468         texdepth_test(device_ptr);
5469         texkill_test(device_ptr);
5470         x8l8v8u8_test(device_ptr);
5471         if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 4)) {
5472             constant_clamp_ps_test(device_ptr);
5473             cnd_test(device_ptr);
5474             if (caps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) {
5475                 nested_loop_test(device_ptr);
5476                 fixed_function_varying_test(device_ptr);
5477                 if(caps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) {
5478                     vshader_version_varying_test(device_ptr);
5479                     pshader_version_varying_test(device_ptr);
5480                 } else {
5481                     skip("No vs_3_0 support\n");
5482                 }
5483             } else {
5484                 skip("No ps_3_0 support\n");
5485             }
5486         }
5487     }
5488     else skip("No ps_1_1 support\n");
5489
5490 cleanup:
5491     if(device_ptr) {
5492         ULONG ref;
5493
5494         D3DPRESENT_PARAMETERS present_parameters;
5495         IDirect3DSwapChain9 *swapchain;
5496         IDirect3DDevice9_GetSwapChain(device_ptr, 0, &swapchain);
5497         IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters);
5498         IDirect3DSwapChain9_Release(swapchain);
5499         ref = IDirect3DDevice9_Release(device_ptr);
5500         DestroyWindow(present_parameters.hDeviceWindow);
5501         ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
5502     }
5503 }