wintrust/tests: Fix test on win9x.
[wine] / dlls / d3d9 / tests / visual.c
1 /*
2  * Copyright 2005, 2007 Henri Verbeet
3  * Copyright (C) 2007-2008 Stefan Dösinger(for CodeWeavers)
4  * Copyright (C) 2008 Jason Green(for TransGaming)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 /* This test framework allows limited testing of rendering results. Things are rendered, shown on
22  * the framebuffer, read back from there and compared to expected colors.
23  *
24  * However, neither d3d nor opengl is guaranteed to be pixel exact, and thus the capability of this test
25  * is rather limited. As a general guideline for adding tests, do not rely on corner pixels. Draw a big enough
26  * area which shows specific behavior(like a quad on the whole screen), and try to get resulting colors with
27  * all bits set or unset in all channels(like pure red, green, blue, white, black). Hopefully everything that
28  * causes visible results in games can be tested in a way that does not depend on pixel exactness
29  */
30
31 #define COBJMACROS
32 #include <d3d9.h>
33 #include <dxerr9.h>
34 #include "wine/test.h"
35
36 static HMODULE d3d9_handle = 0;
37
38 static HWND create_window(void)
39 {
40     WNDCLASS wc = {0};
41     HWND ret;
42     wc.lpfnWndProc = &DefWindowProc;
43     wc.lpszClassName = "d3d9_test_wc";
44     RegisterClass(&wc);
45
46     ret = CreateWindow("d3d9_test_wc", "d3d9_test",
47                         WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
48     return ret;
49 }
50
51 static BOOL color_match(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
52 {
53     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
54     c1 >>= 8; c2 >>= 8;
55     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
56     c1 >>= 8; c2 >>= 8;
57     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
58     c1 >>= 8; c2 >>= 8;
59     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
60     return TRUE;
61 }
62
63 /* Locks a given surface and returns the color at (x,y).  It's the caller's
64  * responsibility to only pass in lockable surfaces and valid x,y coordinates */
65 static DWORD getPixelColorFromSurface(IDirect3DSurface9 *surface, UINT x, UINT y)
66 {
67     DWORD color;
68     HRESULT hr;
69     D3DSURFACE_DESC desc;
70     RECT rectToLock = {x, y, x+1, y+1};
71     D3DLOCKED_RECT lockedRect;
72
73     hr = IDirect3DSurface9_GetDesc(surface, &desc);
74     if(FAILED(hr))  /* This is not a test */
75     {
76         trace("Can't get the surface description, hr=%s\n", DXGetErrorString9(hr));
77         return 0xdeadbeef;
78     }
79
80     hr = IDirect3DSurface9_LockRect(surface, &lockedRect, &rectToLock, D3DLOCK_READONLY);
81     if(FAILED(hr))  /* This is not a test */
82     {
83         trace("Can't lock the surface, hr=%s\n", DXGetErrorString9(hr));
84         return 0xdeadbeef;
85     }
86     switch(desc.Format) {
87         case D3DFMT_A8R8G8B8:
88         {
89             color = ((DWORD *) lockedRect.pBits)[0] & 0xffffffff;
90             break;
91         }
92         default:
93             trace("Error: unknown surface format: %d\n", desc.Format);
94             color = 0xdeadbeef;
95             break;
96     }
97     hr = IDirect3DSurface9_UnlockRect(surface);
98     if(FAILED(hr))
99     {
100         trace("Can't unlock the surface, hr=%s\n", DXGetErrorString9(hr));
101     }
102     return color;
103 }
104
105 static DWORD getPixelColor(IDirect3DDevice9 *device, UINT x, UINT y)
106 {
107     DWORD ret;
108     IDirect3DSurface9 *surf;
109     HRESULT hr;
110     D3DLOCKED_RECT lockedRect;
111     RECT rectToLock = {x, y, x+1, y+1};
112
113     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 640, 480, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL);
114     if(FAILED(hr) || !surf )  /* This is not a test */
115     {
116         trace("Can't create an offscreen plain surface to read the render target data, hr=%s\n", DXGetErrorString9(hr));
117         return 0xdeadbeef;
118     }
119
120     hr = IDirect3DDevice9_GetFrontBufferData(device, 0, surf);
121     if(FAILED(hr))
122     {
123         trace("Can't read the front buffer data, hr=%s\n", DXGetErrorString9(hr));
124         ret = 0xdeadbeed;
125         goto out;
126     }
127
128     hr = IDirect3DSurface9_LockRect(surf, &lockedRect, &rectToLock, D3DLOCK_READONLY);
129     if(FAILED(hr))
130     {
131         trace("Can't lock the offscreen surface, hr=%s\n", DXGetErrorString9(hr));
132         ret = 0xdeadbeec;
133         goto out;
134     }
135
136     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
137      * really important for these tests
138      */
139     ret = ((DWORD *) lockedRect.pBits)[0] & 0x00ffffff;
140     hr = IDirect3DSurface9_UnlockRect(surf);
141     if(FAILED(hr))
142     {
143         trace("Can't unlock the offscreen surface, hr=%s\n", DXGetErrorString9(hr));
144     }
145
146 out:
147     if(surf) IDirect3DSurface9_Release(surf);
148     return ret;
149 }
150
151 static IDirect3DDevice9 *init_d3d9(void)
152 {
153     IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion) = 0;
154     IDirect3D9 *d3d9_ptr = 0;
155     IDirect3DDevice9 *device_ptr = 0;
156     D3DPRESENT_PARAMETERS present_parameters;
157     HRESULT hr;
158     D3DADAPTER_IDENTIFIER9 identifier;
159
160     d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
161     ok(d3d9_create != NULL, "Failed to get address of Direct3DCreate9\n");
162     if (!d3d9_create) return NULL;
163
164     d3d9_ptr = d3d9_create(D3D_SDK_VERSION);
165     ok(d3d9_ptr != NULL, "Failed to create IDirect3D9 object\n");
166     if (!d3d9_ptr) return NULL;
167
168     ZeroMemory(&present_parameters, sizeof(present_parameters));
169     present_parameters.Windowed = FALSE;
170     present_parameters.hDeviceWindow = create_window();
171     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
172     present_parameters.BackBufferWidth = 640;
173     present_parameters.BackBufferHeight = 480;
174     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
175     present_parameters.EnableAutoDepthStencil = TRUE;
176     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
177
178     memset(&identifier, 0, sizeof(identifier));
179     hr = IDirect3D9_GetAdapterIdentifier(d3d9_ptr, 0, 0, &identifier);
180     ok(hr == D3D_OK, "Failed to get adapter identifier description\n");
181     trace("Driver string: \"%s\"\n", identifier.Driver);
182     trace("Description string: \"%s\"\n", identifier.Description);
183     trace("Device name string: \"%s\"\n", identifier.DeviceName);
184     trace("Driver version %d.%d.%d.%d\n",
185           HIWORD(U(identifier.DriverVersion).HighPart), LOWORD(U(identifier.DriverVersion).HighPart),
186           HIWORD(U(identifier.DriverVersion).LowPart), LOWORD(U(identifier.DriverVersion).LowPart));
187
188     hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
189     if(FAILED(hr)) {
190         present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
191         hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
192         if(FAILED(hr)) {
193             hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
194         }
195     }
196     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D_CreateDevice returned: %s\n", DXGetErrorString9(hr));
197
198     return device_ptr;
199 }
200
201 struct vertex
202 {
203     float x, y, z;
204     DWORD diffuse;
205 };
206
207 struct tvertex
208 {
209     float x, y, z, rhw;
210     DWORD diffuse;
211 };
212
213 struct nvertex
214 {
215     float x, y, z;
216     float nx, ny, nz;
217     DWORD diffuse;
218 };
219
220 static void lighting_test(IDirect3DDevice9 *device)
221 {
222     HRESULT hr;
223     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
224     DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
225     DWORD color;
226
227     float mat[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
228                       0.0f, 1.0f, 0.0f, 0.0f,
229                       0.0f, 0.0f, 1.0f, 0.0f,
230                       0.0f, 0.0f, 0.0f, 1.0f };
231
232     struct vertex unlitquad[] =
233     {
234         {-1.0f, -1.0f,   0.1f,                          0xffff0000},
235         {-1.0f,  0.0f,   0.1f,                          0xffff0000},
236         { 0.0f,  0.0f,   0.1f,                          0xffff0000},
237         { 0.0f, -1.0f,   0.1f,                          0xffff0000},
238     };
239     struct vertex litquad[] =
240     {
241         {-1.0f,  0.0f,   0.1f,                          0xff00ff00},
242         {-1.0f,  1.0f,   0.1f,                          0xff00ff00},
243         { 0.0f,  1.0f,   0.1f,                          0xff00ff00},
244         { 0.0f,  0.0f,   0.1f,                          0xff00ff00},
245     };
246     struct nvertex unlitnquad[] =
247     {
248         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
249         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
250         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
251         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
252     };
253     struct nvertex litnquad[] =
254     {
255         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
256         { 0.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
257         { 1.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
258         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
259     };
260     WORD Indices[] = {0, 1, 2, 2, 3, 0};
261
262     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
263     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
264
265     /* Setup some states that may cause issues */
266     hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(0), (D3DMATRIX *) mat);
267     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %s\n", DXGetErrorString9(hr));
268     hr = IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, (D3DMATRIX *)mat);
269     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %s\n", DXGetErrorString9(hr));
270     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, (D3DMATRIX *) mat);
271     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %s\n", DXGetErrorString9(hr));
272     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
273     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
274     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
275     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
276     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
277     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
278     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
279     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
280     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, FALSE);
281     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
282     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
283     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
284     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, FALSE);
285     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
286     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
287     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %s\n", DXGetErrorString9(hr));
288     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
289     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %s\n", DXGetErrorString9(hr));
290
291     hr = IDirect3DDevice9_SetFVF(device, fvf);
292     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
293
294     hr = IDirect3DDevice9_BeginScene(device);
295     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
296     if(hr == D3D_OK)
297     {
298         /* No lights are defined... That means, lit vertices should be entirely black */
299         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
300         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
301         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
302                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitquad, sizeof(unlitquad[0]));
303         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
304
305         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
306         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
307         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
308                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litquad, sizeof(litquad[0]));
309         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
310
311         hr = IDirect3DDevice9_SetFVF(device, nfvf);
312         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
313
314         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
315         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
316         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
317                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitnquad, sizeof(unlitnquad[0]));
318         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
319
320         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
321         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
322         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
323                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litnquad, sizeof(litnquad[0]));
324         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
325
326         IDirect3DDevice9_EndScene(device);
327         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
328     }
329
330     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
331
332     color = getPixelColor(device, 160, 360); /* lower left quad - unlit without normals */
333     ok(color == 0x00ff0000, "Unlit quad without normals has color %08x\n", color);
334     color = getPixelColor(device, 160, 120); /* upper left quad - lit without normals */
335     ok(color == 0x00000000, "Lit quad without normals has color %08x\n", color);
336     color = getPixelColor(device, 480, 360); /* lower left quad - unlit with normals */
337     ok(color == 0x000000ff, "Unlit quad with normals has color %08x\n", color);
338     color = getPixelColor(device, 480, 120); /* upper left quad - lit with normals */
339     ok(color == 0x00000000, "Lit quad with normals has color %08x\n", color);
340
341     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
342     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
343 }
344
345 static void clear_test(IDirect3DDevice9 *device)
346 {
347     /* Tests the correctness of clearing parameters */
348     HRESULT hr;
349     D3DRECT rect[2];
350     D3DRECT rect_negneg;
351     DWORD color;
352     D3DVIEWPORT9 old_vp, vp;
353     RECT scissor;
354     DWORD oldColorWrite;
355     BOOL invalid_clear_failed = FALSE;
356
357     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
358     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
359
360     /* Positive x, negative y */
361     rect[0].x1 = 0;
362     rect[0].y1 = 480;
363     rect[0].x2 = 320;
364     rect[0].y2 = 240;
365
366     /* Positive x, positive y */
367     rect[1].x1 = 0;
368     rect[1].y1 = 0;
369     rect[1].x2 = 320;
370     rect[1].y2 = 240;
371     /* Clear 2 rectangles with one call. The refrast returns an error in this case, every real driver tested so far
372      * returns D3D_OK, but ignores the rectangle silently
373      */
374     hr = IDirect3DDevice9_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
375     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
376     if(hr == D3DERR_INVALIDCALL) invalid_clear_failed = TRUE;
377
378     /* negative x, negative y */
379     rect_negneg.x1 = 640;
380     rect_negneg.y1 = 240;
381     rect_negneg.x2 = 320;
382     rect_negneg.y2 = 0;
383     hr = IDirect3DDevice9_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
384     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
385     if(hr == D3DERR_INVALIDCALL) invalid_clear_failed = TRUE;
386
387     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
388
389     color = getPixelColor(device, 160, 360); /* lower left quad */
390     ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
391     color = getPixelColor(device, 160, 120); /* upper left quad */
392     if(invalid_clear_failed) {
393         /* If the negative rectangle was refused, the other rectangles in the list shouldn't be cleared either */
394         ok(color == 0x00ffffff, "Clear rectangle 1(pos, pos) has color %08x\n", color);
395     } else {
396         /* If the negative rectangle was dropped silently, the correct ones are cleared */
397         ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
398     }
399     color = getPixelColor(device, 480, 360); /* lower right quad  */
400     ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
401     color = getPixelColor(device, 480, 120); /* upper right quad */
402     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
403
404     /* Test how the viewport affects clears */
405     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
406     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
407     hr = IDirect3DDevice9_GetViewport(device, &old_vp);
408     ok(hr == D3D_OK, "IDirect3DDevice9_GetViewport failed with %s\n", DXGetErrorString9(hr));
409
410     vp.X = 160;
411     vp.Y = 120;
412     vp.Width = 160;
413     vp.Height = 120;
414     vp.MinZ = 0.0;
415     vp.MaxZ = 1.0;
416     hr = IDirect3DDevice9_SetViewport(device, &vp);
417     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %s\n", DXGetErrorString9(hr));
418     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
419     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
420
421     vp.X = 320;
422     vp.Y = 240;
423     vp.Width = 320;
424     vp.Height = 240;
425     vp.MinZ = 0.0;
426     vp.MaxZ = 1.0;
427     hr = IDirect3DDevice9_SetViewport(device, &vp);
428     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %s\n", DXGetErrorString9(hr));
429     rect[0].x1 = 160;
430     rect[0].y1 = 120;
431     rect[0].x2 = 480;
432     rect[0].y2 = 360;
433     hr = IDirect3DDevice9_Clear(device, 1, &rect[0], D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
434     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
435
436     hr = IDirect3DDevice9_SetViewport(device, &old_vp);
437     ok(hr == D3D_OK, "IDirect3DDevice9_SetViewport failed with %s\n", DXGetErrorString9(hr));
438
439     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
440     color = getPixelColor(device, 158, 118);
441     ok(color == 0x00ffffff, "(158,118) has color %08x\n", color);
442     color = getPixelColor(device, 162, 118);
443     ok(color == 0x00ffffff, "(162,118) has color %08x\n", color);
444     color = getPixelColor(device, 158, 122);
445     ok(color == 0x00ffffff, "(158,122) has color %08x\n", color);
446     color = getPixelColor(device, 162, 122);
447     ok(color == 0x000000ff, "(162,122) has color %08x\n", color);
448
449     color = getPixelColor(device, 318, 238);
450     ok(color == 0x000000ff, "(318,238) has color %08x\n", color);
451     color = getPixelColor(device, 322, 238);
452     ok(color == 0x00ffffff, "(322,328) has color %08x\n", color);
453     color = getPixelColor(device, 318, 242);
454     ok(color == 0x00ffffff, "(318,242) has color %08x\n", color);
455     color = getPixelColor(device, 322, 242);
456     ok(color == 0x0000ff00, "(322,242) has color %08x\n", color);
457
458     color = getPixelColor(device, 478, 358);
459     ok(color == 0x0000ff00, "(478,358 has color %08x\n", color);
460     color = getPixelColor(device, 482, 358);
461     ok(color == 0x00ffffff, "(482,358) has color %08x\n", color);
462     color = getPixelColor(device, 478, 362);
463     ok(color == 0x00ffffff, "(478,362) has color %08x\n", color);
464     color = getPixelColor(device, 482, 362);
465     ok(color == 0x00ffffff, "(482,362) has color %08x\n", color);
466
467     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
468     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
469
470     scissor.left = 160;
471     scissor.right = 480;
472     scissor.top = 120;
473     scissor.bottom = 360;
474     hr = IDirect3DDevice9_SetScissorRect(device, &scissor);
475     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %s\n", DXGetErrorString9(hr));
476     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, TRUE);
477     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %s\n", DXGetErrorString9(hr));
478
479     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
480     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
481     hr = IDirect3DDevice9_Clear(device, 1, &rect[1], D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
482     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
483
484     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, FALSE);
485     ok(hr == D3D_OK, "IDirect3DDevice_SetScissorRect failed with %s\n", DXGetErrorString9(hr));
486
487     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
488     color = getPixelColor(device, 158, 118);
489     ok(color == 0x00ffffff, "Pixel 158/118 has color %08x\n", color);
490     color = getPixelColor(device, 162, 118);
491     ok(color == 0x00ffffff, "Pixel 162/118 has color %08x\n", color);
492     color = getPixelColor(device, 158, 122);
493     ok(color == 0x00ffffff, "Pixel 158/122 has color %08x\n", color);
494     color = getPixelColor(device, 162, 122);
495     ok(color == 0x00ff0000, "Pixel 162/122 has color %08x\n", color);
496
497     color = getPixelColor(device, 158, 358);
498     ok(color == 0x00ffffff, "Pixel 158/358 has color %08x\n", color);
499     color = getPixelColor(device, 162, 358);
500     ok(color == 0x0000ff00, "Pixel 162/358 has color %08x\n", color);
501     color = getPixelColor(device, 158, 358);
502     ok(color == 0x00ffffff, "Pixel 158/358 has color %08x\n", color);
503     color = getPixelColor(device, 162, 362);
504     ok(color == 0x00ffffff, "Pixel 162/362 has color %08x\n", color);
505
506     color = getPixelColor(device, 478, 118);
507     ok(color == 0x00ffffff, "Pixel 158/118 has color %08x\n", color);
508     color = getPixelColor(device, 478, 122);
509     ok(color == 0x0000ff00, "Pixel 162/118 has color %08x\n", color);
510     color = getPixelColor(device, 482, 122);
511     ok(color == 0x00ffffff, "Pixel 158/122 has color %08x\n", color);
512     color = getPixelColor(device, 482, 358);
513     ok(color == 0x00ffffff, "Pixel 162/122 has color %08x\n", color);
514
515     color = getPixelColor(device, 478, 358);
516     ok(color == 0x0000ff00, "Pixel 478/358 has color %08x\n", color);
517     color = getPixelColor(device, 478, 362);
518     ok(color == 0x00ffffff, "Pixel 478/118 has color %08x\n", color);
519     color = getPixelColor(device, 482, 358);
520     ok(color == 0x00ffffff, "Pixel 482/122 has color %08x\n", color);
521     color = getPixelColor(device, 482, 362);
522     ok(color == 0x00ffffff, "Pixel 482/122 has color %08x\n", color);
523
524     color = getPixelColor(device, 318, 238);
525     ok(color == 0x00ff0000, "Pixel 318/238 has color %08x\n", color);
526     color = getPixelColor(device, 318, 242);
527     ok(color == 0x0000ff00, "Pixel 318/242 has color %08x\n", color);
528     color = getPixelColor(device, 322, 238);
529     ok(color == 0x0000ff00, "Pixel 322/238 has color %08x\n", color);
530     color = getPixelColor(device, 322, 242);
531     ok(color == 0x0000ff00, "Pixel 322/242 has color %08x\n", color);
532
533     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_COLORWRITEENABLE, &oldColorWrite);
534     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed with %s\n", DXGetErrorString9(hr));
535     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED);
536     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %s\n", DXGetErrorString9(hr));
537
538     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
539     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
540
541     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, oldColorWrite);
542     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %s\n", DXGetErrorString9(hr));
543
544     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
545
546     /* Colorwriteenable does not affect the clear */
547     color = getPixelColor(device, 320, 240);
548     ok(color == 0x00ffffff, "Color write protected clear returned color %08x\n", color);
549 }
550
551 typedef struct {
552     float in[4];
553     DWORD out;
554 } test_data_t;
555
556 /*
557  *  c7      mova    ARGB            mov     ARGB
558  * -2.4     -2      0x00ffff00      -3      0x00ff0000
559  * -1.6     -2      0x00ffff00      -2      0x00ffff00
560  * -0.4      0      0x0000ffff      -1      0x0000ff00
561  *  0.4      0      0x0000ffff       0      0x0000ffff
562  *  1.6      2      0x00ff00ff       1      0x000000ff
563  *  2.4      2      0x00ff00ff       2      0x00ff00ff
564  */
565 static void test_mova(IDirect3DDevice9 *device)
566 {
567     static const DWORD mova_test[] = {
568         0xfffe0200,                                                             /* vs_2_0                       */
569         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
570         0x05000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0   */
571         0x05000051, 0xa00f0001, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, /* def c1, 1.0, 1.0, 0.0, 1.0   */
572         0x05000051, 0xa00f0002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, /* def c2, 0.0, 1.0, 0.0, 1.0   */
573         0x05000051, 0xa00f0003, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 0.0, 1.0, 1.0, 1.0   */
574         0x05000051, 0xa00f0004, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c4, 0.0, 0.0, 1.0, 1.0   */
575         0x05000051, 0xa00f0005, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, /* def c5, 1.0, 0.0, 1.0, 1.0   */
576         0x05000051, 0xa00f0006, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c6, 1.0, 1.0, 1.0, 1.0   */
577         0x0200002e, 0xb0010000, 0xa0000007,                                     /* mova a0.x, c7.x              */
578         0x03000001, 0xd00f0000, 0xa0e42003, 0xb0000000,                         /* mov oD0, c[a0.x + 3]         */
579         0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
580         0x0000ffff                                                              /* END                          */
581     };
582     static const DWORD mov_test[] = {
583         0xfffe0101,                                                             /* vs_1_1                       */
584         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
585         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0   */
586         0x00000051, 0xa00f0001, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, /* def c1, 1.0, 1.0, 0.0, 1.0   */
587         0x00000051, 0xa00f0002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, /* def c2, 0.0, 1.0, 0.0, 1.0   */
588         0x00000051, 0xa00f0003, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 0.0, 1.0, 1.0, 1.0   */
589         0x00000051, 0xa00f0004, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c4, 0.0, 0.0, 1.0, 1.0   */
590         0x00000051, 0xa00f0005, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, /* def c5, 1.0, 0.0, 1.0, 1.0   */
591         0x00000051, 0xa00f0006, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c6, 1.0, 1.0, 1.0, 1.0   */
592         0x00000001, 0xb0010000, 0xa0000007,                                     /* mov a0.x, c7.x               */
593         0x00000001, 0xd00f0000, 0xa0e42003,                                     /* mov oD0, c[a0.x + 3]         */
594         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
595         0x0000ffff                                                              /* END                          */
596     };
597
598     static const test_data_t test_data[2][6] = {
599         {
600             {{-2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff0000},
601             {{-1.6f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
602             {{-0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ff00},
603             {{ 0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
604             {{ 1.6f, 0.0f, 0.0f, 0.0f}, 0x000000ff},
605             {{ 2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff}
606         },
607         {
608             {{-2.4f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
609             {{-1.6f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
610             {{-0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
611             {{ 0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
612             {{ 1.6f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff},
613             {{ 2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff}
614         }
615     };
616
617     static const float quad[][3] = {
618         {-1.0f, -1.0f, 0.0f},
619         {-1.0f,  1.0f, 0.0f},
620         { 1.0f, -1.0f, 0.0f},
621         { 1.0f,  1.0f, 0.0f},
622     };
623
624     static const D3DVERTEXELEMENT9 decl_elements[] = {
625         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
626         D3DDECL_END()
627     };
628
629     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
630     IDirect3DVertexShader9 *mova_shader = NULL;
631     IDirect3DVertexShader9 *mov_shader = NULL;
632     HRESULT hr;
633     UINT i, j;
634
635     hr = IDirect3DDevice9_CreateVertexShader(device, mova_test, &mova_shader);
636     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
637     hr = IDirect3DDevice9_CreateVertexShader(device, mov_test, &mov_shader);
638     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
639     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
640     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
641     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
642     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
643
644     hr = IDirect3DDevice9_SetVertexShader(device, mov_shader);
645     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
646     for(j = 0; j < 2; ++j)
647     {
648         for (i = 0; i < (sizeof(test_data[0]) / sizeof(test_data_t)); ++i)
649         {
650             DWORD color;
651
652             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 7, test_data[j][i].in, 1);
653             ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
654
655             hr = IDirect3DDevice9_BeginScene(device);
656             ok(SUCCEEDED(hr), "BeginScene failed (%08x)\n", hr);
657
658             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], 3 * sizeof(float));
659             ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
660
661             hr = IDirect3DDevice9_EndScene(device);
662             ok(SUCCEEDED(hr), "EndScene failed (%08x)\n", hr);
663
664             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
665             ok(SUCCEEDED(hr), "Present failed (%08x)\n", hr);
666
667             color = getPixelColor(device, 320, 240);
668             ok(color == test_data[j][i].out, "Expected color %08x, got %08x (for input %f, instruction %s)\n",
669                test_data[j][i].out, color, test_data[j][i].in[0], j == 0 ? "mov" : "mova");
670
671             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
672             ok(SUCCEEDED(hr), "Clear failed (%08x)\n", hr);
673         }
674         hr = IDirect3DDevice9_SetVertexShader(device, mova_shader);
675         ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
676     }
677
678     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
679     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
680
681     IDirect3DVertexDeclaration9_Release(vertex_declaration);
682     IDirect3DVertexShader9_Release(mova_shader);
683     IDirect3DVertexShader9_Release(mov_shader);
684 }
685
686 struct sVertex {
687     float x, y, z;
688     DWORD diffuse;
689     DWORD specular;
690 };
691
692 struct sVertexT {
693     float x, y, z, rhw;
694     DWORD diffuse;
695     DWORD specular;
696 };
697
698 static void fog_test(IDirect3DDevice9 *device)
699 {
700     HRESULT hr;
701     DWORD color;
702     BYTE r, g, b;
703     float start = 0.0f, end = 1.0f;
704     D3DCAPS9 caps;
705     int i;
706
707     /* Gets full z based fog with linear fog, no fog with specular color */
708     struct sVertex unstransformed_1[] = {
709         {-1,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
710         {-1,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
711         { 0,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
712         { 0,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
713     };
714     /* Ok, I am too lazy to deal with transform matrices */
715     struct sVertex unstransformed_2[] = {
716         {-1,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
717         {-1,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
718         { 0,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
719         { 0,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
720     };
721     /* Untransformed ones. Give them a different diffuse color to make the test look
722      * nicer. It also makes making sure that they are drawn correctly easier.
723      */
724     struct sVertexT transformed_1[] = {
725         {320,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
726         {640,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
727         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
728         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
729     };
730     struct sVertexT transformed_2[] = {
731         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
732         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
733         {640,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
734         {320,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
735     };
736     struct vertex rev_fog_quads[] = {
737        {-1.0,   -1.0,   0.1,    0x000000ff},
738        {-1.0,    0.0,   0.1,    0x000000ff},
739        { 0.0,    0.0,   0.1,    0x000000ff},
740        { 0.0,   -1.0,   0.1,    0x000000ff},
741
742        { 0.0,   -1.0,   0.9,    0x000000ff},
743        { 0.0,    0.0,   0.9,    0x000000ff},
744        { 1.0,    0.0,   0.9,    0x000000ff},
745        { 1.0,   -1.0,   0.9,    0x000000ff},
746
747        { 0.0,    0.0,   0.4,    0x000000ff},
748        { 0.0,    1.0,   0.4,    0x000000ff},
749        { 1.0,    1.0,   0.4,    0x000000ff},
750        { 1.0,    0.0,   0.4,    0x000000ff},
751
752        {-1.0,    0.0,   0.7,    0x000000ff},
753        {-1.0,    1.0,   0.7,    0x000000ff},
754        { 0.0,    1.0,   0.7,    0x000000ff},
755        { 0.0,    0.0,   0.7,    0x000000ff},
756     };
757     WORD Indices[] = {0, 1, 2, 2, 3, 0};
758
759     memset(&caps, 0, sizeof(caps));
760     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
761     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %s\n", DXGetErrorString9(hr));
762     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
763     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
764
765     /* Setup initial states: No lighting, fog on, fog color */
766     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
767     ok(hr == D3D_OK, "Turning off lighting returned %s\n", DXGetErrorString9(hr));
768     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
769     ok(hr == D3D_OK, "Turning on fog calculations returned %s\n", DXGetErrorString9(hr));
770     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
771     ok(hr == D3D_OK, "Turning on fog calculations returned %s\n", DXGetErrorString9(hr));
772
773     /* First test: Both table fog and vertex fog off */
774     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
775     ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString9(hr));
776     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
777     ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString9(hr));
778
779     /* Start = 0, end = 1. Should be default, but set them */
780     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
781     ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
782     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
783     ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
784
785     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
786     {
787         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
788         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
789         /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
790         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
791                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_1,
792                                                      sizeof(unstransformed_1[0]));
793         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
794
795         /* That makes it use the Z value */
796         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
797         ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString9(hr));
798         /* Untransformed, vertex fog != none (or table fog != none):
799          * Use the Z value as input into the equation
800          */
801         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
802                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_2,
803                                                      sizeof(unstransformed_1[0]));
804         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
805
806         /* transformed verts */
807         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
808         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
809         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
810         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
811                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
812                                                      sizeof(transformed_1[0]));
813         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
814
815         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
816         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %s\n", DXGetErrorString9(hr));
817         /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
818          * equation
819          */
820         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
821                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_2,
822                                                      sizeof(transformed_2[0]));
823
824         hr = IDirect3DDevice9_EndScene(device);
825         ok(hr == D3D_OK, "EndScene returned %s\n", DXGetErrorString9(hr));
826     }
827     else
828     {
829         ok(FALSE, "BeginScene failed\n");
830     }
831
832     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
833     color = getPixelColor(device, 160, 360);
834     ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color);
835     color = getPixelColor(device, 160, 120);
836     ok(color == 0x0000FF00 || color == 0x0000FE00, "Untransformed vertex with linear vertex fog has color %08x\n", color);
837     color = getPixelColor(device, 480, 120);
838     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
839     if(caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
840     {
841         color = getPixelColor(device, 480, 360);
842         ok(color == 0x0000FF00 || color == 0x0000FE00, "Transformed vertex with linear table fog has color %08x\n", color);
843     }
844     else
845     {
846         /* Without fog table support the vertex fog is still applied, even though table fog is turned on.
847          * The settings above result in no fogging with vertex fog
848          */
849         color = getPixelColor(device, 480, 120);
850         ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
851         trace("Info: Table fog not supported by this device\n");
852     }
853
854     /* Now test the special case fogstart == fogend */
855     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
856     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
857
858     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
859     {
860         start = 512;
861         end = 512;
862         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
863         ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
864         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
865         ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
866
867         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
868         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
869         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
870         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState %s\n", DXGetErrorString9(hr));
871         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
872         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %s\n", DXGetErrorString9(hr));
873
874         /* Untransformed vertex, z coord = 0.1, fogstart = 512, fogend = 512. Would result in
875          * a completely fog-free primitive because start > zcoord, but because start == end, the primitive
876          * is fully covered by fog. The same happens to the 2nd untransformed quad with z = 1.0.
877          * The third transformed quad remains unfogged because the fogcoords are read from the specular
878          * color and has fixed fogstart and fogend.
879          */
880         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
881                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_1,
882                 sizeof(unstransformed_1[0]));
883         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
884         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
885                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_2,
886                 sizeof(unstransformed_1[0]));
887         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
888
889         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
890         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
891         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
892         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
893                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
894                 sizeof(transformed_1[0]));
895         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
896
897         hr = IDirect3DDevice9_EndScene(device);
898         ok(hr == D3D_OK, "EndScene returned %s\n", DXGetErrorString9(hr));
899     }
900     else
901     {
902         ok(FALSE, "BeginScene failed\n");
903     }
904     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
905     color = getPixelColor(device, 160, 360);
906     ok(color == 0x0000FF00 || color == 0x0000FE00, "Untransformed vertex with vertex fog and z = 0.1 has color %08x\n", color);
907     color = getPixelColor(device, 160, 120);
908     ok(color == 0x0000FF00 || color == 0x0000FE00, "Untransformed vertex with vertex fog and z = 1.0 has color %08x\n", color);
909     color = getPixelColor(device, 480, 120);
910     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
911
912     /* Test "reversed" fog without shaders. With shaders this fails on a few Windows D3D implementations,
913      * but without shaders it seems to work everywhere
914      */
915     end = 0.2;
916     start = 0.8;
917     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
918     ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
919     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
920     ok(hr == D3D_OK, "Setting fog end returned %s\n", DXGetErrorString9(hr));
921     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
922     ok( hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
923
924     /* Test reversed fog without shaders. ATI cards have problems with reversed fog and shaders, so
925      * it doesn't seem very important for games. ATI cards also have problems with reversed table fog,
926      * so skip this for now
927      */
928     for(i = 0; i < 1 /*2 - Table fog test disabled, fails on ATI */; i++) {
929         const char *mode = (i ? "table" : "vertex");
930         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
931         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
932         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, i == 0 ? D3DFOG_LINEAR : D3DFOG_NONE);
933         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
934         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, i == 0 ? D3DFOG_NONE : D3DFOG_LINEAR);
935         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
936         hr = IDirect3DDevice9_BeginScene(device);
937         ok( hr == D3D_OK, "IDirect3DDDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
938         if(SUCCEEDED(hr)) {
939             WORD Indices2[] = { 0,  1,  2,  2,  3, 0,
940                                 4,  5,  6,  6,  7, 4,
941                                 8,  9, 10, 10, 11, 8,
942                             12, 13, 14, 14, 15, 12};
943
944             hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */,
945                     16 /* NumVerts */, 8 /*PrimCount */, Indices2, D3DFMT_INDEX16, rev_fog_quads,
946                     sizeof(rev_fog_quads[0]));
947
948             hr = IDirect3DDevice9_EndScene(device);
949             ok( hr == D3D_OK, "IDirect3DDDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
950         }
951         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
952         color = getPixelColor(device, 160, 360);
953         ok(color == 0x0000FF00 || color == 0x0000FE00, "Reversed %s fog: z=0.1 has color 0x%08x, expected 0x0000ff00\n", mode, color);
954
955         color = getPixelColor(device, 160, 120);
956         r = (color & 0x00ff0000) >> 16;
957         g = (color & 0x0000ff00) >>  8;
958         b = (color & 0x000000ff);
959         ok(r == 0x00 && g >= 0x29 && g <= 0x2d && b >= 0xd2 && b <= 0xd6,
960            "Reversed %s fog: z=0.7 has color 0x%08x, expected\n", mode, color);
961
962         color = getPixelColor(device, 480, 120);
963         r = (color & 0x00ff0000) >> 16;
964         g = (color & 0x0000ff00) >>  8;
965         b = (color & 0x000000ff);
966         ok(r == 0x00 && g >= 0xa8 && g <= 0xac && b >= 0x53 && b <= 0x57,
967            "Reversed %s fog: z=0.4 has color 0x%08x, expected\n", mode, color);
968
969         color = getPixelColor(device, 480, 360);
970         ok(color == 0x000000ff, "Reversed %s fog: z=0.9 has color 0x%08x, expected 0x000000ff\n", mode, color);
971
972         if(!(caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)) {
973             skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping reversed table fog test\n");
974             break;
975         }
976     }
977     /* Turn off the fog master switch to avoid confusing other tests */
978     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
979     ok(hr == D3D_OK, "Turning off fog calculations returned %s\n", DXGetErrorString9(hr));
980     start = 0.0;
981     end = 1.0;
982     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
983     ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
984     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
985     ok(hr == D3D_OK, "Setting fog end returned %s\n", DXGetErrorString9(hr));
986     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
987     ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState %s\n", DXGetErrorString9(hr));
988     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
989     ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %s\n", DXGetErrorString9(hr));
990 }
991
992 /* This test verifies the behaviour of cube maps wrt. texture wrapping.
993  * D3D cube map wrapping always behaves like GL_CLAMP_TO_EDGE,
994  * regardless of the actual addressing mode set. */
995 static void test_cube_wrap(IDirect3DDevice9 *device)
996 {
997     static const float quad[][6] = {
998         {-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
999         {-1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1000         { 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1001         { 1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
1002     };
1003
1004     static const D3DVERTEXELEMENT9 decl_elements[] = {
1005         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1006         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1007         D3DDECL_END()
1008     };
1009
1010     static const struct {
1011         D3DTEXTUREADDRESS mode;
1012         const char *name;
1013     } address_modes[] = {
1014         {D3DTADDRESS_WRAP, "D3DTADDRESS_WRAP"},
1015         {D3DTADDRESS_MIRROR, "D3DTADDRESS_MIRROR"},
1016         {D3DTADDRESS_CLAMP, "D3DTADDRESS_CLAMP"},
1017         {D3DTADDRESS_BORDER, "D3DTADDRESS_BORDER"},
1018         {D3DTADDRESS_MIRRORONCE, "D3DTADDRESS_MIRRORONCE"},
1019     };
1020
1021     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1022     IDirect3DCubeTexture9 *texture = NULL;
1023     IDirect3DSurface9 *surface = NULL;
1024     D3DLOCKED_RECT locked_rect;
1025     HRESULT hr;
1026     UINT x;
1027     INT y, face;
1028
1029     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1030     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1031     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1032     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1033
1034     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
1035             D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL);
1036     ok(SUCCEEDED(hr), "CreateOffscreenPlainSurface failed (0x%08x)\n", hr);
1037
1038     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, 0);
1039     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1040
1041     for (y = 0; y < 128; ++y)
1042     {
1043         DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1044         for (x = 0; x < 64; ++x)
1045         {
1046             *ptr++ = 0xffff0000;
1047         }
1048         for (x = 64; x < 128; ++x)
1049         {
1050             *ptr++ = 0xff0000ff;
1051         }
1052     }
1053
1054     hr = IDirect3DSurface9_UnlockRect(surface);
1055     ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
1056
1057     hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
1058             D3DPOOL_DEFAULT, &texture, NULL);
1059     ok(SUCCEEDED(hr), "CreateCubeTexture failed (0x%08x)\n", hr);
1060
1061     /* Create cube faces */
1062     for (face = 0; face < 6; ++face)
1063     {
1064         IDirect3DSurface9 *face_surface = NULL;
1065
1066         hr= IDirect3DCubeTexture9_GetCubeMapSurface(texture, face, 0, &face_surface);
1067         ok(SUCCEEDED(hr), "GetCubeMapSurface failed (0x%08x)\n", hr);
1068
1069         hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, face_surface, NULL);
1070         ok(SUCCEEDED(hr), "UpdateSurface failed (0x%08x)\n", hr);
1071
1072         IDirect3DSurface9_Release(face_surface);
1073     }
1074
1075     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
1076     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1077
1078     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
1079     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1080     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
1081     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1082     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_BORDERCOLOR, 0xff00ff00);
1083     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_BORDERCOLOR failed (0x%08x)\n", hr);
1084
1085     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1086     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1087
1088     for (x = 0; x < (sizeof(address_modes) / sizeof(*address_modes)); ++x)
1089     {
1090         DWORD color;
1091
1092         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, address_modes[x].mode);
1093         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU (%s) failed (0x%08x)\n", address_modes[x].name, hr);
1094         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, address_modes[x].mode);
1095         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV (%s) failed (0x%08x)\n", address_modes[x].name, hr);
1096
1097         hr = IDirect3DDevice9_BeginScene(device);
1098         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1099
1100         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1101         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
1102
1103         hr = IDirect3DDevice9_EndScene(device);
1104         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1105
1106         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1107         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1108
1109         /* Due to the nature of this test, we sample essentially at the edge
1110          * between two faces. Because of this it's undefined from which face
1111          * the driver will sample. Fortunately that's not important for this
1112          * test, since all we care about is that it doesn't sample from the
1113          * other side of the surface or from the border. */
1114         color = getPixelColor(device, 320, 240);
1115         ok(color == 0x00ff0000 || color == 0x000000ff,
1116                 "Got color 0x%08x for addressing mode %s, expected 0x00ff0000 or 0x000000ff.\n",
1117                 color, address_modes[x].name);
1118
1119         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
1120         ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
1121     }
1122
1123     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1124     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1125
1126     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1127     IDirect3DCubeTexture9_Release(texture);
1128     IDirect3DSurface9_Release(surface);
1129 }
1130
1131 static void offscreen_test(IDirect3DDevice9 *device)
1132 {
1133     HRESULT hr;
1134     IDirect3DTexture9 *offscreenTexture = NULL;
1135     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
1136     DWORD color;
1137
1138     static const float quad[][5] = {
1139         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
1140         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
1141         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
1142         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
1143     };
1144
1145     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
1146     ok(hr == D3D_OK, "Clear failed, hr = %s\n", DXGetErrorString9(hr));
1147
1148     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
1149     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %s\n", DXGetErrorString9(hr));
1150     if(!offscreenTexture) {
1151         trace("Failed to create an X8R8G8B8 offscreen texture, trying R5G6B5\n");
1152         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
1153         ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %s\n", DXGetErrorString9(hr));
1154         if(!offscreenTexture) {
1155             skip("Cannot create an offscreen render target\n");
1156             goto out;
1157         }
1158     }
1159
1160     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1161     ok(hr == D3D_OK, "Can't get back buffer, hr = %s\n", DXGetErrorString9(hr));
1162     if(!backbuffer) {
1163         goto out;
1164     }
1165
1166     hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
1167     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %s\n", DXGetErrorString9(hr));
1168     if(!offscreen) {
1169         goto out;
1170     }
1171
1172     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
1173     ok(hr == D3D_OK, "SetFVF failed, hr = %s\n", DXGetErrorString9(hr));
1174
1175     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
1176     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
1177     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
1178     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
1179     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
1180     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1181     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
1182     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1183     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1184     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1185
1186     if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
1187         hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
1188         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %s\n", DXGetErrorString9(hr));
1189         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1190         ok(hr == D3D_OK, "Clear failed, hr = %s\n", DXGetErrorString9(hr));
1191
1192         /* Draw without textures - Should result in a white quad */
1193         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
1194         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %s\n", DXGetErrorString9(hr));
1195
1196         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
1197         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %s\n", DXGetErrorString9(hr));
1198         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
1199         ok(hr == D3D_OK, "SetTexture failed, %s\n", DXGetErrorString9(hr));
1200
1201         /* This time with the texture */
1202         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
1203         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %s\n", DXGetErrorString9(hr));
1204
1205         IDirect3DDevice9_EndScene(device);
1206     }
1207
1208     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1209
1210     /* Center quad - should be white */
1211     color = getPixelColor(device, 320, 240);
1212     ok(color == 0x00ffffff, "Offscreen failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1213     /* Some quad in the cleared part of the texture */
1214     color = getPixelColor(device, 170, 240);
1215     ok(color == 0x00ff00ff, "Offscreen failed: Got color 0x%08x, expected 0x00ff00ff.\n", color);
1216     /* Part of the originally cleared back buffer */
1217     color = getPixelColor(device, 10, 10);
1218     ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1219     if(0) {
1220         /* Lower left corner of the screen, where back buffer offscreen rendering draws the offscreen texture.
1221          * It should be red, but the offscreen texture may leave some junk there. Not tested yet. Depending on
1222          * the offscreen rendering mode this test would succeed or fail
1223          */
1224         color = getPixelColor(device, 10, 470);
1225         ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1226     }
1227
1228 out:
1229     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1230
1231     /* restore things */
1232     if(backbuffer) {
1233         IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
1234         IDirect3DSurface9_Release(backbuffer);
1235     }
1236     if(offscreenTexture) {
1237         IDirect3DTexture9_Release(offscreenTexture);
1238     }
1239     if(offscreen) {
1240         IDirect3DSurface9_Release(offscreen);
1241     }
1242 }
1243
1244 /* This test tests fog in combination with shaders.
1245  * What's tested: linear fog (vertex and table) with pixel shader
1246  *                linear table fog with non foggy vertex shader
1247  *                vertex fog with foggy vertex shader
1248  * What's not tested: non linear fog with shader
1249  *                    table fog with foggy vertex shader
1250  */
1251 static void fog_with_shader_test(IDirect3DDevice9 *device)
1252 {
1253     HRESULT hr;
1254     DWORD color;
1255     union {
1256         float f;
1257         DWORD i;
1258     } start, end;
1259     unsigned int i, j;
1260
1261     /* basic vertex shader without fog computation ("non foggy") */
1262     static const DWORD vertex_shader_code1[] = {
1263         0xfffe0101,                                                             /* vs_1_1                       */
1264         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
1265         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                */
1266         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
1267         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                  */
1268         0x0000ffff
1269     };
1270     /* basic vertex shader with reversed fog computation ("foggy") */
1271     static const DWORD vertex_shader_code2[] = {
1272         0xfffe0101,                                                             /* vs_1_1                        */
1273         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0               */
1274         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                 */
1275         0x00000051, 0xa00f0000, 0xbfa00000, 0x00000000, 0xbf666666, 0x00000000, /* def c0, -1.25, 0.0, -0.9, 0.0 */
1276         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                  */
1277         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                   */
1278         0x00000002, 0x800f0000, 0x90aa0000, 0xa0aa0000,                         /* add r0, v0.z, c0.z            */
1279         0x00000005, 0xc00f0001, 0x80000000, 0xa0000000,                         /* mul oFog, r0.x, c0.x          */
1280         0x0000ffff
1281     };
1282     /* basic pixel shader */
1283     static const DWORD pixel_shader_code[] = {
1284         0xffff0101,                                                             /* ps_1_1     */
1285         0x00000001, 0x800f0000, 0x90e40000,                                     /* mov r0, vo */
1286         0x0000ffff
1287     };
1288
1289     static struct vertex quad[] = {
1290         {-1.0f, -1.0f,  0.0f,          0xFFFF0000  },
1291         {-1.0f,  1.0f,  0.0f,          0xFFFF0000  },
1292         { 1.0f, -1.0f,  0.0f,          0xFFFF0000  },
1293         { 1.0f,  1.0f,  0.0f,          0xFFFF0000  },
1294     };
1295
1296     static const D3DVERTEXELEMENT9 decl_elements[] = {
1297         {0,  0, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1298         {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
1299         D3DDECL_END()
1300     };
1301
1302     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1303     IDirect3DVertexShader9      *vertex_shader[3]   = {NULL, NULL, NULL};
1304     IDirect3DPixelShader9       *pixel_shader[2]    = {NULL, NULL};
1305
1306     /* This reference data was collected on a nVidia GeForce 7600GS driver version 84.19 DirectX version 9.0c on Windows XP */
1307     static const struct test_data_t {
1308         int vshader;
1309         int pshader;
1310         D3DFOGMODE vfog;
1311         D3DFOGMODE tfog;
1312         unsigned int color[11];
1313     } test_data[] = {
1314         /* only pixel shader: */
1315         {0, 1, 0, 3,
1316         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1317         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1318         {0, 1, 1, 3,
1319         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1320         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1321         {0, 1, 2, 3,
1322         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1323         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1324         {0, 1, 3, 0,
1325         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1326         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1327         {0, 1, 3, 3,
1328         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1329         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1330
1331         /* vertex shader */
1332         {1, 0, 0, 0,
1333         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
1334          0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
1335         {1, 0, 0, 3,
1336         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1337         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1338         {1, 0, 1, 3,
1339         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1340         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1341
1342         {1, 0, 2, 3,
1343         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1344         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1345         {1, 0, 3, 3,
1346         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1347         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1348
1349         /* vertex shader and pixel shader */
1350         {1, 1, 0, 3,
1351         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1352         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1353         {1, 1, 1, 3,
1354         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1355         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1356         {1, 1, 2, 3,
1357         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1358         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1359
1360         {1, 1, 3, 3,
1361         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
1362         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
1363
1364
1365 #if 0  /* FIXME: these fail on GeForce 8500 */
1366         /* foggy vertex shader */
1367         {2, 0, 0, 0,
1368         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1369          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1370         {2, 0, 1, 0,
1371         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1372          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1373         {2, 0, 2, 0,
1374         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1375          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1376         {2, 0, 3, 0,
1377         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1378          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1379 #endif
1380
1381         /* foggy vertex shader and pixel shader */
1382         {2, 1, 0, 0,
1383         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1384          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1385         {2, 1, 1, 0,
1386         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1387          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1388         {2, 1, 2, 0,
1389         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1390          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1391         {2, 1, 3, 0,
1392         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1393          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1394
1395     };
1396
1397     /* NOTE: changing these values will not affect the tests with foggy vertex shader, as the values are hardcoded in the shader*/
1398     start.f=0.1f;
1399     end.f=0.9f;
1400
1401     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code1, &vertex_shader[1]);
1402     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1403     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code2, &vertex_shader[2]);
1404     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1405     hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader[1]);
1406     ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1407     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1408     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
1409
1410     /* Setup initial states: No lighting, fog on, fog color */
1411     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1412     ok(hr == D3D_OK, "Turning off lighting failed (%08x)\n", hr);
1413     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
1414     ok(hr == D3D_OK, "Turning on fog calculations failed (%08x)\n", hr);
1415     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
1416     ok(hr == D3D_OK, "Setting fog color failed (%08x)\n", hr);
1417     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1418     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1419
1420     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
1421     ok(hr == D3D_OK, "Turning off table fog failed (%08x)\n", hr);
1422     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
1423     ok(hr == D3D_OK, "Turning off vertex fog failed (%08x)\n", hr);
1424
1425     /* Use fogtart = 0.1 and end = 0.9 to test behavior outside the fog transition phase, too*/
1426     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, start.i);
1427     ok(hr == D3D_OK, "Setting fog start failed (%08x)\n", hr);
1428     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, end.i);
1429     ok(hr == D3D_OK, "Setting fog end failed (%08x)\n", hr);
1430
1431     for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++)
1432     {
1433         hr = IDirect3DDevice9_SetVertexShader(device, vertex_shader[test_data[i].vshader]);
1434         ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1435         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader[test_data[i].pshader]);
1436         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1437         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, test_data[i].vfog);
1438         ok( hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1439         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, test_data[i].tfog);
1440         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1441
1442         for(j=0; j < 11; j++)
1443         {
1444             /* Don't use the whole zrange to prevent rounding errors */
1445             quad[0].z = 0.001f + (float)j / 10.02f;
1446             quad[1].z = 0.001f + (float)j / 10.02f;
1447             quad[2].z = 0.001f + (float)j / 10.02f;
1448             quad[3].z = 0.001f + (float)j / 10.02f;
1449
1450             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1451             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
1452
1453             hr = IDirect3DDevice9_BeginScene(device);
1454             ok( hr == D3D_OK, "BeginScene returned failed (%08x)\n", hr);
1455
1456             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1457             ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1458
1459             hr = IDirect3DDevice9_EndScene(device);
1460             ok(hr == D3D_OK, "EndScene failed (%08x)\n", hr);
1461
1462             IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1463
1464             /* As the red and green component are the result of blending use 5% tolerance on the expected value */
1465             color = getPixelColor(device, 128, 240);
1466             ok((unsigned char)(color) == ((unsigned char)test_data[i].color[j])
1467                     && abs( ((unsigned char)(color>>8)) - (unsigned char)(test_data[i].color[j]>>8) ) < 13
1468                     && abs( ((unsigned char)(color>>16)) - (unsigned char)(test_data[i].color[j]>>16) ) < 13,
1469                "fog vs%i ps%i fvm%i ftm%i %d: got color %08x, expected %08x +-5%%\n",
1470                test_data[i].vshader, test_data[i].pshader, test_data[i].vfog, test_data[i].tfog, j, color, test_data[i].color[j]);
1471         }
1472     }
1473
1474     /* reset states */
1475     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
1476     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1477     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1478     ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1479     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1480     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1481     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
1482     ok(hr == D3D_OK, "Turning off fog calculations failed (%08x)\n", hr);
1483
1484     IDirect3DVertexShader9_Release(vertex_shader[1]);
1485     IDirect3DVertexShader9_Release(vertex_shader[2]);
1486     IDirect3DPixelShader9_Release(pixel_shader[1]);
1487     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1488 }
1489
1490 static void generate_bumpmap_textures(IDirect3DDevice9 *device) {
1491     unsigned int i, x, y;
1492     HRESULT hr;
1493     IDirect3DTexture9 *texture[2] = {NULL, NULL};
1494     D3DLOCKED_RECT locked_rect;
1495
1496     /* Generate the textures */
1497     for(i=0; i<2; i++)
1498     {
1499         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, i?D3DFMT_A8R8G8B8:D3DFMT_V8U8,
1500                                             D3DPOOL_MANAGED, &texture[i], NULL);
1501         ok(SUCCEEDED(hr), "CreateTexture failed (0x%08x)\n", hr);
1502
1503         hr = IDirect3DTexture9_LockRect(texture[i], 0, &locked_rect, NULL, 0);
1504         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1505         for (y = 0; y < 128; ++y)
1506         {
1507             if(i)
1508             { /* Set up black texture with 2x2 texel white spot in the middle */
1509                 DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1510                 for (x = 0; x < 128; ++x)
1511                 {
1512                     if(y>62 && y<66 && x>62 && x<66)
1513                         *ptr++ = 0xffffffff;
1514                     else
1515                         *ptr++ = 0xff000000;
1516                 }
1517             }
1518             else
1519             { /* Set up a displacement map which points away from the center parallel to the closest axis.
1520                * (if multiplied with bumpenvmat)
1521               */
1522                 WORD *ptr = (WORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1523                 for (x = 0; x < 128; ++x)
1524                 {
1525                     if(abs(x-64)>abs(y-64))
1526                     {
1527                         if(x < 64)
1528                             *ptr++ = 0xc000;
1529                         else
1530                             *ptr++ = 0x4000;
1531                     }
1532                     else
1533                     {
1534                         if(y < 64)
1535                             *ptr++ = 0x0040;
1536                         else
1537                             *ptr++ = 0x00c0;
1538                     }
1539                 }
1540             }
1541         }
1542         hr = IDirect3DTexture9_UnlockRect(texture[i], 0);
1543         ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
1544
1545         hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture[i]);
1546         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1547
1548         /* Disable texture filtering */
1549         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MINFILTER, D3DTEXF_POINT);
1550         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1551         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
1552         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1553
1554         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1555         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU failed (0x%08x)\n", hr);
1556         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1557         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV failed (0x%08x)\n", hr);
1558     }
1559 }
1560
1561 /* test the behavior of the texbem instruction
1562  * with normal 2D and projective 2D textures
1563  */
1564 static void texbem_test(IDirect3DDevice9 *device)
1565 {
1566     HRESULT hr;
1567     DWORD color;
1568     int i;
1569
1570     static const DWORD pixel_shader_code[] = {
1571         0xffff0101,                         /* ps_1_1*/
1572         0x00000042, 0xb00f0000,             /* tex t0*/
1573         0x00000043, 0xb00f0001, 0xb0e40000, /* texbem t1, t0*/
1574         0x00000001, 0x800f0000, 0xb0e40001, /* mov r0, t1*/
1575         0x0000ffff
1576     };
1577     static const DWORD double_texbem_code[] =  {
1578         0xffff0103,                                         /* ps_1_3           */
1579         0x00000042, 0xb00f0000,                             /* tex t0           */
1580         0x00000043, 0xb00f0001, 0xb0e40000,                 /* texbem t1, t0    */
1581         0x00000042, 0xb00f0002,                             /* tex t2           */
1582         0x00000043, 0xb00f0003, 0xb0e40002,                 /* texbem t3, t2    */
1583         0x00000002, 0x800f0000, 0xb0e40001, 0xb0e40003,     /* add r0, t1, t3   */
1584         0x0000ffff                                          /* end              */
1585     };
1586
1587
1588     static const float quad[][7] = {
1589         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f},
1590         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f},
1591         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 1.0f, 0.0f},
1592         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 1.0f, 1.0f},
1593     };
1594     static const float quad_proj[][9] = {
1595         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f,   0.0f,   0.0f, 0.0f, 128.0f},
1596         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f,   0.0f, 128.0f, 0.0f, 128.0f},
1597         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 128.0f,   0.0f, 0.0f, 128.0f},
1598         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 128.0f, 128.0f, 0.0f, 128.0f},
1599     };
1600
1601     static const D3DVERTEXELEMENT9 decl_elements[][4] = { {
1602         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1603         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1604         {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1605         D3DDECL_END()
1606     },{
1607         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1608         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1609         {0, 20, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1610         D3DDECL_END()
1611     } };
1612
1613     /* use asymmetric matrix to test loading */
1614     float bumpenvmat[4] = {0.0,0.5,-0.5,0.0};
1615
1616     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1617     IDirect3DPixelShader9       *pixel_shader       = NULL;
1618     IDirect3DTexture9           *texture            = NULL, *texture1, *texture2;
1619     D3DLOCKED_RECT locked_rect;
1620
1621     generate_bumpmap_textures(device);
1622
1623     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
1624     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
1625     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
1626     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
1627     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
1628
1629     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
1630     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1631
1632     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1633     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
1634
1635     for(i=0; i<2; i++)
1636     {
1637         if(i)
1638         {
1639             hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4|D3DTTFF_PROJECTED);
1640             ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
1641         }
1642
1643         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements[i], &vertex_declaration);
1644         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1645         hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1646         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1647
1648         hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader);
1649         ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1650         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader);
1651         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1652
1653         hr = IDirect3DDevice9_BeginScene(device);
1654         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1655
1656         if(!i)
1657             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1658         else
1659             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad_proj[0], sizeof(quad_proj[0]));
1660         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
1661
1662         hr = IDirect3DDevice9_EndScene(device);
1663         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1664
1665         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1666         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1667
1668         color = getPixelColor(device, 320-32, 240);
1669         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1670         color = getPixelColor(device, 320+32, 240);
1671         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1672         color = getPixelColor(device, 320, 240-32);
1673         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1674         color = getPixelColor(device, 320, 240+32);
1675         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1676
1677         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1678         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1679         IDirect3DPixelShader9_Release(pixel_shader);
1680
1681         hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1682         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1683         IDirect3DVertexDeclaration9_Release(vertex_declaration);
1684     }
1685
1686     /* clean up */
1687     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
1688     ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
1689
1690     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
1691     ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
1692
1693     for(i=0; i<2; i++)
1694     {
1695         hr = IDirect3DDevice9_GetTexture(device, i, (IDirect3DBaseTexture9 **) &texture);
1696         ok(SUCCEEDED(hr), "IDirect3DDevice9_GetTexture failed (0x%08x)\n", hr);
1697         IDirect3DTexture9_Release(texture); /* For the GetTexture */
1698         hr = IDirect3DDevice9_SetTexture(device, i, NULL);
1699         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1700         IDirect3DTexture9_Release(texture);
1701     }
1702
1703     /* Test double texbem */
1704     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_V8U8, D3DPOOL_MANAGED, &texture, NULL);
1705     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed (0x%08x)\n", hr);
1706     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_V8U8, D3DPOOL_MANAGED, &texture1, NULL);
1707     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed (0x%08x)\n", hr);
1708     hr = IDirect3DDevice9_CreateTexture(device, 8, 8, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture2, NULL);
1709     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed (0x%08x)\n", hr);
1710     hr = IDirect3DDevice9_CreatePixelShader(device, double_texbem_code, &pixel_shader);
1711     ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1712
1713     hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
1714     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1715     ((signed char *) locked_rect.pBits)[0] = (-1.0 / 8.0) * 127;
1716     ((signed char *) locked_rect.pBits)[1] = ( 1.0 / 8.0) * 127;
1717
1718     hr = IDirect3DTexture9_UnlockRect(texture, 0);
1719     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1720
1721     hr = IDirect3DTexture9_LockRect(texture1, 0, &locked_rect, NULL, 0);
1722     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1723     ((signed char *) locked_rect.pBits)[0] = (-2.0 / 8.0) * 127;
1724     ((signed char *) locked_rect.pBits)[1] = (-4.0 / 8.0) * 127;
1725     hr = IDirect3DTexture9_UnlockRect(texture1, 0);
1726     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1727
1728     {
1729         /* Some data without any meaning, just to have an 8x8 array to see which element is picked */
1730 #define tex  0x00ff0000
1731 #define tex1 0x0000ff00
1732 #define origin 0x000000ff
1733         static const DWORD pixel_data[] = {
1734             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1735             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1736             0x000000ff, tex1      , 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1737             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1738             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, origin,     0x000000ff, tex       , 0x000000ff,
1739             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1740             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1741             0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
1742         };
1743 #undef tex1
1744 #undef tex2
1745 #undef origin
1746
1747         hr = IDirect3DTexture9_LockRect(texture2, 0, &locked_rect, NULL, 0);
1748         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1749         for(i = 0; i < 8; i++) {
1750             memcpy(((char *) locked_rect.pBits) + i * locked_rect.Pitch, pixel_data + 8 * i, 8 * sizeof(DWORD));
1751         }
1752         hr = IDirect3DTexture9_UnlockRect(texture2, 0);
1753         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1754     }
1755
1756     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
1757     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1758     hr = IDirect3DDevice9_SetTexture(device, 1, (IDirect3DBaseTexture9 *) texture2);
1759     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1760     hr = IDirect3DDevice9_SetTexture(device, 2, (IDirect3DBaseTexture9 *) texture1);
1761     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1762     hr = IDirect3DDevice9_SetTexture(device, 3, (IDirect3DBaseTexture9 *) texture2);
1763     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1764     hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader);
1765     ok(SUCCEEDED(hr), "Direct3DDevice9_SetPixelShader failed (0x%08x)\n", hr);
1766     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX4);
1767     ok(SUCCEEDED(hr), "Direct3DDevice9_SetPixelShader failed (0x%08x)\n", hr);
1768
1769     bumpenvmat[0] =-1.0;  bumpenvmat[2] =  2.0;
1770     bumpenvmat[1] = 0.0;  bumpenvmat[3] =  0.0;
1771     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
1772     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
1773     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
1774     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
1775
1776     bumpenvmat[0] = 1.5; bumpenvmat[2] =  0.0;
1777     bumpenvmat[1] = 0.0; bumpenvmat[3] =  0.5;
1778     IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
1779     IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
1780     IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
1781     IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
1782
1783     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1784     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1785     hr = IDirect3DDevice9_SetSamplerState(device, 1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1786     hr = IDirect3DDevice9_SetSamplerState(device, 1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1787     hr = IDirect3DDevice9_SetSamplerState(device, 2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1788     hr = IDirect3DDevice9_SetSamplerState(device, 2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1789     hr = IDirect3DDevice9_SetSamplerState(device, 3, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1790     hr = IDirect3DDevice9_SetSamplerState(device, 3, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1791
1792     hr = IDirect3DDevice9_BeginScene(device);
1793     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1794     if(SUCCEEDED(hr)) {
1795         static const float double_quad[] = {
1796             -1.0,   -1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
1797              1.0,   -1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
1798             -1.0,    1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
1799              1.0,    1.0,   0.0,    0.0,    0.0,    0.5,    0.5,    0.0,    0.0,    0.5,    0.5,
1800         };
1801
1802         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, double_quad, sizeof(float) * 11);
1803         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
1804         hr = IDirect3DDevice9_EndScene(device);
1805         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1806     }
1807     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1808     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1809     color = getPixelColor(device, 320, 240);
1810     ok(color == 0x00ffff00, "double texbem failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
1811
1812     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1813     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1814     hr = IDirect3DDevice9_SetTexture(device, 1, NULL);
1815     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1816     hr = IDirect3DDevice9_SetTexture(device, 2, NULL);
1817     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1818     hr = IDirect3DDevice9_SetTexture(device, 3, NULL);
1819     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTexture failed (0x%08x)\n", hr);
1820     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1821     ok(SUCCEEDED(hr), "Direct3DDevice9_SetPixelShader failed (0x%08x)\n", hr);
1822
1823     IDirect3DPixelShader9_Release(pixel_shader);
1824     IDirect3DTexture9_Release(texture);
1825     IDirect3DTexture9_Release(texture1);
1826     IDirect3DTexture9_Release(texture2);
1827 }
1828
1829 static void z_range_test(IDirect3DDevice9 *device)
1830 {
1831     const struct vertex quad[] =
1832     {
1833         {-1.0f,  0.0f,   1.1f,                          0xffff0000},
1834         {-1.0f,  1.0f,   1.1f,                          0xffff0000},
1835         { 1.0f,  0.0f,  -1.1f,                          0xffff0000},
1836         { 1.0f,  1.0f,  -1.1f,                          0xffff0000},
1837     };
1838     const struct vertex quad2[] =
1839     {
1840         {-1.0f,  0.0f,   1.1f,                          0xff0000ff},
1841         {-1.0f,  1.0f,   1.1f,                          0xff0000ff},
1842         { 1.0f,  0.0f,  -1.1f,                          0xff0000ff},
1843         { 1.0f,  1.0f,  -1.1f,                          0xff0000ff},
1844     };
1845
1846     const struct tvertex quad3[] =
1847     {
1848         {    0,   240,   1.1f,  1.0,                    0xffffff00},
1849         {    0,   480,   1.1f,  1.0,                    0xffffff00},
1850         {  640,   240,  -1.1f,  1.0,                    0xffffff00},
1851         {  640,   480,  -1.1f,  1.0,                    0xffffff00},
1852     };
1853     const struct tvertex quad4[] =
1854     {
1855         {    0,   240,   1.1f,  1.0,                    0xff00ff00},
1856         {    0,   480,   1.1f,  1.0,                    0xff00ff00},
1857         {  640,   240,  -1.1f,  1.0,                    0xff00ff00},
1858         {  640,   480,  -1.1f,  1.0,                    0xff00ff00},
1859     };
1860     HRESULT hr;
1861     DWORD color;
1862     IDirect3DVertexShader9 *shader;
1863     IDirect3DVertexDeclaration9 *decl;
1864     D3DCAPS9 caps;
1865     const DWORD shader_code[] = {
1866         0xfffe0101,                                     /* vs_1_1           */
1867         0x0000001f, 0x80000000, 0x900f0000,             /* dcl_position v0  */
1868         0x00000001, 0xc00f0000, 0x90e40000,             /* mov oPos, v0     */
1869         0x00000001, 0xd00f0000, 0xa0e40000,             /* mov oD0, c0      */
1870         0x0000ffff                                      /* end              */
1871     };
1872     static const D3DVERTEXELEMENT9 decl_elements[] = {
1873         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1874         D3DDECL_END()
1875     };
1876     /* Does the Present clear the depth stencil? Clear the depth buffer with some value != 0,
1877      * then call Present. Then clear the color buffer to make sure it has some defined content
1878      * after the Present with D3DSWAPEFFECT_DISCARD. After that draw a plane that is somewhere cut
1879      * by the depth value.
1880      */
1881     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.75, 0);
1882     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
1883     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1884     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4, 0);
1885
1886     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, TRUE);
1887     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1888     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
1889     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1890     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
1891     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1892     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
1893     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1894     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1895     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
1896
1897     hr = IDirect3DDevice9_BeginScene(device);
1898     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
1899     if(hr == D3D_OK)
1900     {
1901         /* Test the untransformed vertex path */
1902         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
1903         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1904         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS);
1905         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1906         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad2, sizeof(quad2[0]));
1907         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1908
1909         /* Test the transformed vertex path */
1910         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
1911         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
1912
1913         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad4, sizeof(quad4[0]));
1914         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1915         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
1916         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1917         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad3, sizeof(quad3[0]));
1918         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1919
1920         hr = IDirect3DDevice9_EndScene(device);
1921         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
1922     }
1923
1924     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1925     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1926
1927     /* Do not test the exact corner pixels, but go pretty close to them */
1928
1929     /* Clipped because z > 1.0 */
1930     color = getPixelColor(device, 28, 238);
1931     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1932     color = getPixelColor(device, 28, 241);
1933     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1934
1935     /* Not clipped, > z buffer clear value(0.75) */
1936     color = getPixelColor(device, 31, 238);
1937     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1938     color = getPixelColor(device, 31, 241);
1939     ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
1940     color = getPixelColor(device, 100, 238);
1941     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1942     color = getPixelColor(device, 100, 241);
1943     ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
1944
1945     /* Not clipped, < z buffer clear value */
1946     color = getPixelColor(device, 104, 238);
1947     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
1948     color = getPixelColor(device, 104, 241);
1949     ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color);
1950     color = getPixelColor(device, 318, 238);
1951     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
1952     color = getPixelColor(device, 318, 241);
1953     ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color);
1954
1955     /* Clipped because z < 0.0 */
1956     color = getPixelColor(device, 321, 238);
1957     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1958     color = getPixelColor(device, 321, 241);
1959     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1960
1961     /* Test the shader path */
1962     IDirect3DDevice9_GetDeviceCaps(device, &caps);
1963     if (caps.VertexShaderVersion < D3DVS_VERSION(1, 1)) {
1964         skip("Vertex shaders not supported\n");
1965         goto out;
1966     }
1967     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
1968     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
1969     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
1970     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
1971
1972     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4, 0);
1973
1974     IDirect3DDevice9_SetVertexDeclaration(device, decl);
1975     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
1976     IDirect3DDevice9_SetVertexShader(device, shader);
1977     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
1978
1979     hr = IDirect3DDevice9_BeginScene(device);
1980     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
1981     if(hr == D3D_OK)
1982     {
1983         float colorf[] = {1.0, 0.0, 0.0, 1.0};
1984         float colorf2[] = {0.0, 0.0, 1.0, 1.0};
1985         IDirect3DDevice9_SetVertexShaderConstantF(device, 0, colorf, 1);
1986         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
1987         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1988         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS);
1989         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1990         IDirect3DDevice9_SetVertexShaderConstantF(device, 0, colorf2, 1);
1991         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad2, sizeof(quad2[0]));
1992         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1993
1994         hr = IDirect3DDevice9_EndScene(device);
1995         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
1996     }
1997
1998     IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1999     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
2000     IDirect3DDevice9_SetVertexShader(device, NULL);
2001     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
2002
2003     IDirect3DVertexDeclaration9_Release(decl);
2004     IDirect3DVertexShader9_Release(shader);
2005
2006     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2007     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2008     /* Z < 1.0 */
2009     color = getPixelColor(device, 28, 238);
2010     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2011
2012     /* 1.0 < z < 0.75 */
2013     color = getPixelColor(device, 31, 238);
2014     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2015     color = getPixelColor(device, 100, 238);
2016     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
2017
2018     /* 0.75 < z < 0.0 */
2019     color = getPixelColor(device, 104, 238);
2020     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2021     color = getPixelColor(device, 318, 238);
2022     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
2023
2024     /* 0.0 < z */
2025     color = getPixelColor(device, 321, 238);
2026     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
2027
2028     out:
2029     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
2030     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2031     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
2032     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2033     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
2034     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2035 }
2036
2037 static void fill_surface(IDirect3DSurface9 *surface, DWORD color)
2038 {
2039     D3DSURFACE_DESC desc;
2040     D3DLOCKED_RECT l;
2041     HRESULT hr;
2042     unsigned int x, y;
2043     DWORD *mem;
2044
2045     memset(&desc, 0, sizeof(desc));
2046     memset(&l, 0, sizeof(l));
2047     hr = IDirect3DSurface9_GetDesc(surface, &desc);
2048     ok(hr == D3D_OK, "IDirect3DSurface9_GetDesc failed with %s\n", DXGetErrorString9(hr));
2049     hr = IDirect3DSurface9_LockRect(surface, &l, NULL, 0);
2050     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed with %s\n", DXGetErrorString9(hr));
2051     if(FAILED(hr)) return;
2052
2053     for(y = 0; y < desc.Height; y++)
2054     {
2055         mem = (DWORD *) ((BYTE *) l.pBits + y * l.Pitch);
2056         for(x = 0; x < l.Pitch / sizeof(DWORD); x++)
2057         {
2058             mem[x] = color;
2059         }
2060     }
2061     hr = IDirect3DSurface9_UnlockRect(surface);
2062     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed with %s\n", DXGetErrorString9(hr));
2063 }
2064
2065 /* This tests a variety of possible StretchRect() situations */
2066 static void stretchrect_test(IDirect3DDevice9 *device)
2067 {
2068     HRESULT hr;
2069     IDirect3DTexture9 *tex_rt32 = NULL, *tex_rt64 = NULL, *tex_rt_dest64 = NULL;
2070     IDirect3DSurface9 *surf_tex_rt32 = NULL, *surf_tex_rt64 = NULL, *surf_tex_rt_dest64 = NULL;
2071     IDirect3DTexture9 *tex32 = NULL, *tex64 = NULL, *tex_dest64 = NULL;
2072     IDirect3DSurface9 *surf_tex32 = NULL, *surf_tex64 = NULL, *surf_tex_dest64 = NULL;
2073     IDirect3DSurface9 *surf_rt32 = NULL, *surf_rt64 = NULL, *surf_rt_dest64 = NULL;
2074     IDirect3DSurface9 *surf_offscreen32 = NULL, *surf_offscreen64 = NULL, *surf_offscreen_dest64 = NULL;
2075     IDirect3DSurface9 *surf_temp32 = NULL, *surf_temp64 = NULL;
2076     IDirect3DSurface9 *orig_rt = NULL;
2077     DWORD color;
2078
2079     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &orig_rt);
2080     ok(hr == D3D_OK, "Can't get render target, hr = %s\n", DXGetErrorString9(hr));
2081     if(!orig_rt) {
2082         goto out;
2083     }
2084
2085     /* Create our temporary surfaces in system memory */
2086     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf_temp32, NULL);
2087     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %s\n", DXGetErrorString9(hr));
2088     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf_temp64, NULL);
2089     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %s\n", DXGetErrorString9(hr));
2090
2091     /* Create offscreen plain surfaces in D3DPOOL_DEFAULT */
2092     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 32, 32, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_offscreen32, NULL);
2093     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %s\n", DXGetErrorString9(hr));
2094     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_offscreen64, NULL);
2095     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %s\n", DXGetErrorString9(hr));
2096     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 64, 64, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surf_offscreen_dest64, NULL);
2097     ok(hr == D3D_OK, "IDirect3DDevice9_CreateOffscreenPlainSurface failed with %s\n", DXGetErrorString9(hr));
2098
2099     /* Create render target surfaces */
2100     hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &surf_rt32, NULL );
2101     ok(hr == D3D_OK, "Creating the render target surface failed with %s\n", DXGetErrorString9(hr));
2102     hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &surf_rt64, NULL );
2103     ok(hr == D3D_OK, "Creating the render target surface failed with %s\n", DXGetErrorString9(hr));
2104     hr = IDirect3DDevice9_CreateRenderTarget(device, 64, 64, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &surf_rt_dest64, NULL );
2105     ok(hr == D3D_OK, "Creating the render target surface failed with %s\n", DXGetErrorString9(hr));
2106
2107     /* Create render target textures */
2108     hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt32, NULL);
2109     ok(hr == D3D_OK, "Creating the render target texture failed with %s\n", DXGetErrorString9(hr));
2110     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt64, NULL);
2111     ok(hr == D3D_OK, "Creating the render target texture failed with %s\n", DXGetErrorString9(hr));
2112     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_rt_dest64, NULL);
2113     ok(hr == D3D_OK, "Creating the render target texture failed with %s\n", DXGetErrorString9(hr));
2114     if (tex_rt32) {
2115         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt32, 0, &surf_tex_rt32);
2116         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %s\n", DXGetErrorString9(hr));
2117     }
2118     if (tex_rt64) {
2119         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt64, 0, &surf_tex_rt64);
2120         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %s\n", DXGetErrorString9(hr));
2121     }
2122     if (tex_rt_dest64) {
2123         hr = IDirect3DTexture9_GetSurfaceLevel(tex_rt_dest64, 0, &surf_tex_rt_dest64);
2124         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %s\n", DXGetErrorString9(hr));
2125     }
2126
2127     /* Create regular textures in D3DPOOL_DEFAULT */
2128     hr = IDirect3DDevice9_CreateTexture(device, 32, 32, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex32, NULL);
2129     ok(hr == D3D_OK, "Creating the regular texture failed with %s\n", DXGetErrorString9(hr));
2130     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex64, NULL);
2131     ok(hr == D3D_OK, "Creating the regular texture failed with %s\n", DXGetErrorString9(hr));
2132     hr = IDirect3DDevice9_CreateTexture(device, 64, 64, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &tex_dest64, NULL);
2133     ok(hr == D3D_OK, "Creating the regular texture failed with %s\n", DXGetErrorString9(hr));
2134     if (tex32) {
2135         hr = IDirect3DTexture9_GetSurfaceLevel(tex32, 0, &surf_tex32);
2136         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %s\n", DXGetErrorString9(hr));
2137     }
2138     if (tex64) {
2139         hr = IDirect3DTexture9_GetSurfaceLevel(tex64, 0, &surf_tex64);
2140         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %s\n", DXGetErrorString9(hr));
2141     }
2142     if (tex_dest64) {
2143         hr = IDirect3DTexture9_GetSurfaceLevel(tex_dest64, 0, &surf_tex_dest64);
2144         ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %s\n", DXGetErrorString9(hr));
2145     }
2146
2147     /*********************************************************************
2148      * Tests for when the source parameter is an offscreen plain surface *
2149      *********************************************************************/
2150
2151     /* Fill the offscreen 64x64 surface with green */
2152     if (surf_offscreen64)
2153         fill_surface(surf_offscreen64, 0xff00ff00);
2154
2155     /* offscreenplain ==> offscreenplain, same size */
2156     if(surf_offscreen64 && surf_offscreen_dest64) {
2157         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_offscreen_dest64, NULL, 0);
2158         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2159
2160         if (hr == D3D_OK) {
2161             color = getPixelColorFromSurface(surf_offscreen_dest64, 32, 32);
2162             ok(color == 0xff00ff00, "StretchRect offscreen ==> offscreen same size failed: Got color 0x%08x, expected 0xff00ff00.\n", color);
2163         }
2164     }
2165
2166     /* offscreenplain ==> rendertarget texture, same size */
2167     if(surf_offscreen64 && surf_tex_rt_dest64 && surf_temp64) {
2168         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_tex_rt_dest64, NULL, 0);
2169         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2170
2171         /* We can't lock rendertarget textures, so copy to our temp surface first */
2172         if (hr == D3D_OK) {
2173             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2174             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %s\n", DXGetErrorString9(hr));
2175         }
2176
2177         if (hr == D3D_OK) {
2178             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2179             ok(color == 0xff00ff00, "StretchRect offscreen ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xff00ff00.\n", color);
2180         }
2181     }
2182
2183     /* offscreenplain ==> rendertarget surface, same size */
2184     if(surf_offscreen64 && surf_rt_dest64) {
2185         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_rt_dest64, NULL, 0);
2186         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2187
2188         if (hr == D3D_OK) {
2189             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2190             ok(color == 0xff00ff00, "StretchRect offscreen ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xff00ff00.\n", color);
2191         }
2192     }
2193
2194     /* offscreenplain ==> texture, same size (should fail) */
2195     if(surf_offscreen64 && surf_tex_dest64) {
2196         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen64, NULL, surf_tex_dest64, NULL, 0);
2197         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2198     }
2199
2200     /* Fill the smaller offscreen surface with red */
2201     fill_surface(surf_offscreen32, 0xffff0000);
2202
2203     /* offscreenplain ==> offscreenplain, scaling (should fail) */
2204     if(surf_offscreen32 && surf_offscreen64) {
2205         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_offscreen64, NULL, 0);
2206         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2207     }
2208
2209     /* offscreenplain ==> rendertarget texture, scaling */
2210     if(surf_offscreen32 && surf_tex_rt_dest64 && surf_temp64) {
2211         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_tex_rt_dest64, NULL, 0);
2212         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2213
2214         /* We can't lock rendertarget textures, so copy to our temp surface first */
2215         if (hr == D3D_OK) {
2216             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2217             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %s\n", DXGetErrorString9(hr));
2218         }
2219
2220         if (hr == D3D_OK) {
2221             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2222             ok(color == 0xffff0000, "StretchRect offscreen ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2223         }
2224     }
2225
2226     /* offscreenplain ==> rendertarget surface, scaling */
2227     if(surf_offscreen32 && surf_rt_dest64) {
2228         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_rt_dest64, NULL, 0);
2229         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2230
2231         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2232         ok(color == 0xffff0000, "StretchRect offscreen ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2233     }
2234
2235     /* offscreenplain ==> texture, scaling (should fail) */
2236     if(surf_offscreen32 && surf_tex_dest64) {
2237         hr = IDirect3DDevice9_StretchRect(device, surf_offscreen32, NULL, surf_tex_dest64, NULL, 0);
2238         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2239     }
2240
2241     /************************************************************
2242      * Tests for when the source parameter is a regular texture *
2243      ************************************************************/
2244
2245     /* Fill the surface of the regular texture with blue */
2246     if (surf_tex64 && surf_temp64) {
2247         /* Can't fill the surf_tex directly because it's created in D3DPOOL_DEFAULT */
2248         fill_surface(surf_temp64, 0xff0000ff);
2249         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp64, NULL, surf_tex64, NULL);
2250         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %s\n", DXGetErrorString9(hr));
2251     }
2252
2253     /* texture ==> offscreenplain, same size */
2254     if(surf_tex64 && surf_offscreen64) {
2255         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_offscreen64, NULL, 0);
2256         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2257     }
2258
2259     /* texture ==> rendertarget texture, same size */
2260     if(surf_tex64 && surf_tex_rt_dest64 && surf_temp64) {
2261         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_tex_rt_dest64, NULL, 0);
2262         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2263
2264         /* We can't lock rendertarget textures, so copy to our temp surface first */
2265         if (hr == D3D_OK) {
2266             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2267             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %s\n", DXGetErrorString9(hr));
2268         }
2269
2270         if (hr == D3D_OK) {
2271             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2272             ok(color == 0xff0000ff, "StretchRect texture ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xff0000ff.\n", color);
2273         }
2274     }
2275
2276     /* texture ==> rendertarget surface, same size */
2277     if(surf_tex64 && surf_rt_dest64) {
2278         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_rt_dest64, NULL, 0);
2279         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2280
2281         if (hr == D3D_OK) {
2282             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2283             ok(color == 0xff0000ff, "StretchRect texture ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xff0000ff.\n", color);
2284         }
2285     }
2286
2287     /* texture ==> texture, same size (should fail) */
2288     if(surf_tex64 && surf_tex_dest64) {
2289         hr = IDirect3DDevice9_StretchRect(device, surf_tex64, NULL, surf_tex_dest64, NULL, 0);
2290         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2291     }
2292
2293     /* Fill the surface of the smaller regular texture with red */
2294     if (surf_tex32 && surf_temp32) {
2295         /* Can't fill the surf_tex directly because it's created in D3DPOOL_DEFAULT */
2296         fill_surface(surf_temp32, 0xffff0000);
2297         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp32, NULL, surf_tex32, NULL);
2298         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %s\n", DXGetErrorString9(hr));
2299     }
2300
2301     /* texture ==> offscreenplain, scaling (should fail) */
2302     if(surf_tex32 && surf_offscreen64) {
2303         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_offscreen64, NULL, 0);
2304         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2305     }
2306
2307     /* texture ==> rendertarget texture, scaling */
2308     if(surf_tex32 && surf_tex_rt_dest64 && surf_temp64) {
2309         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_tex_rt_dest64, NULL, 0);
2310         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2311
2312         /* We can't lock rendertarget textures, so copy to our temp surface first */
2313         if (hr == D3D_OK) {
2314             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2315             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %s\n", DXGetErrorString9(hr));
2316         }
2317
2318         if (hr == D3D_OK) {
2319             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2320             ok(color == 0xffff0000, "StretchRect texture ==> rendertarget texture scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2321         }
2322     }
2323
2324     /* texture ==> rendertarget surface, scaling */
2325     if(surf_tex32 && surf_rt_dest64) {
2326         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_rt_dest64, NULL, 0);
2327         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2328
2329         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2330         ok(color == 0xffff0000, "StretchRect texture ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2331     }
2332
2333     /* texture ==> texture, scaling (should fail) */
2334     if(surf_tex32 && surf_tex_dest64) {
2335         hr = IDirect3DDevice9_StretchRect(device, surf_tex32, NULL, surf_tex_dest64, NULL, 0);
2336         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2337     }
2338
2339     /*****************************************************************
2340      * Tests for when the source parameter is a rendertarget texture *
2341      *****************************************************************/
2342
2343     /* Fill the surface of the rendertarget texture with white */
2344     if (surf_tex_rt64 && surf_temp64) {
2345         /* Can't fill the surf_tex_rt directly because it's created in D3DPOOL_DEFAULT */
2346         fill_surface(surf_temp64, 0xffffffff);
2347         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp64, NULL, surf_tex_rt64, NULL);
2348         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %s\n", DXGetErrorString9(hr));
2349     }
2350
2351     /* rendertarget texture ==> offscreenplain, same size */
2352     if(surf_tex_rt64 && surf_offscreen64) {
2353         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_offscreen64, NULL, 0);
2354         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2355     }
2356
2357     /* rendertarget texture ==> rendertarget texture, same size */
2358     if(surf_tex_rt64 && surf_tex_rt_dest64 && surf_temp64) {
2359         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_tex_rt_dest64, NULL, 0);
2360         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2361
2362         /* We can't lock rendertarget textures, so copy to our temp surface first */
2363         if (hr == D3D_OK) {
2364             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2365             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %s\n", DXGetErrorString9(hr));
2366         }
2367
2368         if (hr == D3D_OK) {
2369             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2370             ok(color == 0xffffffff, "StretchRect rendertarget texture ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xffffffff.\n", color);
2371         }
2372     }
2373
2374     /* rendertarget texture ==> rendertarget surface, same size */
2375     if(surf_tex_rt64 && surf_rt_dest64) {
2376         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_rt_dest64, NULL, 0);
2377         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2378
2379         if (hr == D3D_OK) {
2380             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2381             ok(color == 0xffffffff, "StretchRect rendertarget texture ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xffffffff.\n", color);
2382         }
2383     }
2384
2385     /* rendertarget texture ==> texture, same size (should fail) */
2386     if(surf_tex_rt64 && surf_tex_dest64) {
2387         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt64, NULL, surf_tex_dest64, NULL, 0);
2388         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2389     }
2390
2391     /* Fill the surface of the smaller rendertarget texture with red */
2392     if (surf_tex_rt32 && surf_temp32) {
2393         /* Can't fill the surf_tex_rt directly because it's created in D3DPOOL_DEFAULT */
2394         fill_surface(surf_temp32, 0xffff0000);
2395         hr = IDirect3DDevice9_UpdateSurface(device, surf_temp32, NULL, surf_tex_rt32, NULL);
2396         ok( hr == D3D_OK, "IDirect3DDevice9_UpdateSurface failed with %s\n", DXGetErrorString9(hr));
2397     }
2398
2399     /* rendertarget texture ==> offscreenplain, scaling (should fail) */
2400     if(surf_tex_rt32 && surf_offscreen64) {
2401         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_offscreen64, NULL, 0);
2402         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2403     }
2404
2405     /* rendertarget texture ==> rendertarget texture, scaling */
2406     if(surf_tex_rt32 && surf_tex_rt_dest64 && surf_temp64) {
2407         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_tex_rt_dest64, NULL, 0);
2408         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2409
2410         /* We can't lock rendertarget textures, so copy to our temp surface first */
2411         if (hr == D3D_OK) {
2412             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2413             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %s\n", DXGetErrorString9(hr));
2414         }
2415
2416         if (hr == D3D_OK) {
2417             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2418             ok(color == 0xffff0000, "StretchRect rendertarget texture ==> rendertarget texture scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2419         }
2420     }
2421
2422     /* rendertarget texture ==> rendertarget surface, scaling */
2423     if(surf_tex_rt32 && surf_rt_dest64) {
2424         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_rt_dest64, NULL, 0);
2425         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2426
2427         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2428         ok(color == 0xffff0000, "StretchRect rendertarget texture ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2429     }
2430
2431     /* rendertarget texture ==> texture, scaling (should fail) */
2432     if(surf_tex_rt32 && surf_tex_dest64) {
2433         hr = IDirect3DDevice9_StretchRect(device, surf_tex_rt32, NULL, surf_tex_dest64, NULL, 0);
2434         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2435     }
2436
2437     /*****************************************************************
2438      * Tests for when the source parameter is a rendertarget surface *
2439      *****************************************************************/
2440
2441     /* Fill the surface of the rendertarget surface with black */
2442     if (surf_rt64)
2443         fill_surface(surf_rt64, 0xff000000);
2444
2445     /* rendertarget texture ==> offscreenplain, same size */
2446     if(surf_rt64 && surf_offscreen64) {
2447         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_offscreen64, NULL, 0);
2448         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2449     }
2450
2451     /* rendertarget surface ==> rendertarget texture, same size */
2452     if(surf_rt64 && surf_tex_rt_dest64 && surf_temp64) {
2453         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_tex_rt_dest64, NULL, 0);
2454         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2455
2456         /* We can't lock rendertarget textures, so copy to our temp surface first */
2457         if (hr == D3D_OK) {
2458             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2459             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %s\n", DXGetErrorString9(hr));
2460         }
2461
2462         if (hr == D3D_OK) {
2463             color = getPixelColorFromSurface(surf_temp64, 32, 32);
2464             ok(color == 0xff000000, "StretchRect rendertarget surface ==> rendertarget texture same size failed: Got color 0x%08x, expected 0xff000000.\n", color);
2465         }
2466     }
2467
2468     /* rendertarget surface ==> rendertarget surface, same size */
2469     if(surf_rt64 && surf_rt_dest64) {
2470         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_rt_dest64, NULL, 0);
2471         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2472
2473         if (hr == D3D_OK) {
2474             color = getPixelColorFromSurface(surf_rt_dest64, 32, 32);
2475             ok(color == 0xff000000, "StretchRect rendertarget surface ==> rendertarget surface same size failed: Got color 0x%08x, expected 0xff000000.\n", color);
2476         }
2477     }
2478
2479     /* rendertarget surface ==> texture, same size (should fail) */
2480     if(surf_rt64 && surf_tex_dest64) {
2481         hr = IDirect3DDevice9_StretchRect(device, surf_rt64, NULL, surf_tex_dest64, NULL, 0);
2482         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2483     }
2484
2485     /* Fill the surface of the smaller rendertarget texture with red */
2486     if (surf_rt32)
2487         fill_surface(surf_rt32, 0xffff0000);
2488
2489     /* rendertarget surface ==> offscreenplain, scaling (should fail) */
2490     if(surf_rt32 && surf_offscreen64) {
2491         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_offscreen64, NULL, 0);
2492         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2493     }
2494
2495     /* rendertarget surface ==> rendertarget texture, scaling */
2496     if(surf_rt32 && surf_tex_rt_dest64 && surf_temp64) {
2497         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_tex_rt_dest64, NULL, 0);
2498         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2499
2500         /* We can't lock rendertarget textures, so copy to our temp surface first */
2501         if (hr == D3D_OK) {
2502             hr = IDirect3DDevice9_GetRenderTargetData(device, surf_tex_rt_dest64, surf_temp64);
2503             ok( hr == D3D_OK, "IDirect3DDevice9_GetRenderTargetData failed with %s\n", DXGetErrorString9(hr));
2504         }
2505
2506         if (hr == D3D_OK) {
2507             color = getPixelColorFromSurface(surf_temp64, 48, 48);
2508             ok(color == 0xffff0000, "StretchRect rendertarget surface ==> rendertarget texture scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2509         }
2510     }
2511
2512     /* rendertarget surface ==> rendertarget surface, scaling */
2513     if(surf_rt32 && surf_rt_dest64) {
2514         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_rt_dest64, NULL, 0);
2515         ok( hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
2516
2517         color = getPixelColorFromSurface(surf_rt_dest64, 48, 48);
2518         ok(color == 0xffff0000, "StretchRect rendertarget surface ==> rendertarget surface scaling failed: Got color 0x%08x, expected 0xffff0000.\n", color);
2519     }
2520
2521     /* rendertarget surface ==> texture, scaling (should fail) */
2522     if(surf_rt32 && surf_tex_dest64) {
2523         hr = IDirect3DDevice9_StretchRect(device, surf_rt32, NULL, surf_tex_dest64, NULL, 0);
2524         todo_wine ok( hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_StretchRect succeeded, shouldn't happen (todo)\n");
2525     }
2526
2527     /* TODO: Test when source and destination RECT parameters are given... */
2528     /* TODO: Test format conversions */
2529
2530
2531 out:
2532     /* Clean up */
2533     if (surf_rt32)
2534         IDirect3DSurface9_Release(surf_rt32);
2535     if (surf_rt64)
2536         IDirect3DSurface9_Release(surf_rt64);
2537     if (surf_rt_dest64)
2538         IDirect3DSurface9_Release(surf_rt_dest64);
2539     if (surf_temp32)
2540         IDirect3DSurface9_Release(surf_temp32);
2541     if (surf_temp64)
2542         IDirect3DSurface9_Release(surf_temp64);
2543     if (surf_offscreen32)
2544         IDirect3DSurface9_Release(surf_offscreen32);
2545     if (surf_offscreen64)
2546         IDirect3DSurface9_Release(surf_offscreen64);
2547     if (surf_offscreen_dest64)
2548         IDirect3DSurface9_Release(surf_offscreen_dest64);
2549
2550     if (tex_rt32) {
2551         if (surf_tex_rt32)
2552             IDirect3DSurface9_Release(surf_tex_rt32);
2553         IDirect3DTexture9_Release(tex_rt32);
2554     }
2555     if (tex_rt64) {
2556         if (surf_tex_rt64)
2557             IDirect3DSurface9_Release(surf_tex_rt64);
2558         IDirect3DTexture9_Release(tex_rt64);
2559     }
2560     if (tex_rt_dest64) {
2561         if (surf_tex_rt_dest64)
2562             IDirect3DSurface9_Release(surf_tex_rt_dest64);
2563         IDirect3DTexture9_Release(tex_rt_dest64);
2564     }
2565     if (tex32) {
2566         if (surf_tex32)
2567             IDirect3DSurface9_Release(surf_tex32);
2568         IDirect3DTexture9_Release(tex32);
2569     }
2570     if (tex64) {
2571         if (surf_tex64)
2572             IDirect3DSurface9_Release(surf_tex64);
2573         IDirect3DTexture9_Release(tex64);
2574     }
2575     if (tex_dest64) {
2576         if (surf_tex_dest64)
2577             IDirect3DSurface9_Release(surf_tex_dest64);
2578         IDirect3DTexture9_Release(tex_dest64);
2579     }
2580
2581     if (orig_rt) {
2582         hr = IDirect3DDevice9_SetRenderTarget(device, 0, orig_rt);
2583         ok(hr == D3D_OK, "IDirect3DSetRenderTarget failed with %s\n", DXGetErrorString9(hr));
2584         IDirect3DSurface9_Release(orig_rt);
2585     }
2586 }
2587
2588 static void maxmip_test(IDirect3DDevice9 *device)
2589 {
2590     IDirect3DTexture9 *texture = NULL;
2591     IDirect3DSurface9 *surface = NULL;
2592     HRESULT hr;
2593     DWORD color;
2594     const float quads[] = {
2595         -1.0,   -1.0,   0.0,    0.0,    0.0,
2596         -1.0,    0.0,   0.0,    0.0,    1.0,
2597          0.0,   -1.0,   0.0,    1.0,    0.0,
2598          0.0,    0.0,   0.0,    1.0,    1.0,
2599
2600          0.0,   -1.0,   0.0,    0.0,    0.0,
2601          0.0,    0.0,   0.0,    0.0,    1.0,
2602          1.0,   -1.0,   0.0,    1.0,    0.0,
2603          1.0,    0.0,   0.0,    1.0,    1.0,
2604
2605          0.0,    0.0,   0.0,    0.0,    0.0,
2606          0.0,    1.0,   0.0,    0.0,    1.0,
2607          1.0,    0.0,   0.0,    1.0,    0.0,
2608          1.0,    1.0,   0.0,    1.0,    1.0,
2609
2610         -1.0,    0.0,   0.0,    0.0,    0.0,
2611         -1.0,    1.0,   0.0,    0.0,    1.0,
2612          0.0,    0.0,   0.0,    1.0,    0.0,
2613          0.0,    1.0,   0.0,    1.0,    1.0,
2614     };
2615
2616     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
2617     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
2618
2619     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
2620                                         &texture, NULL);
2621     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %s\n", DXGetErrorString9(hr));
2622     if(!texture)
2623     {
2624         skip("Failed to create test texture\n");
2625         return;
2626     }
2627
2628     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
2629     fill_surface(surface, 0xffff0000);
2630     IDirect3DSurface9_Release(surface);
2631     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface);
2632     fill_surface(surface, 0xff00ff00);
2633     IDirect3DSurface9_Release(surface);
2634     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
2635     fill_surface(surface, 0xff0000ff);
2636     IDirect3DSurface9_Release(surface);
2637
2638     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
2639     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
2640     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2641     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2642
2643     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
2644     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
2645
2646     hr = IDirect3DDevice9_BeginScene(device);
2647     if(SUCCEEDED(hr))
2648     {
2649         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
2650         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
2651         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[ 0], 5 * sizeof(float));
2652         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2653
2654         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
2655         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
2656         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[20], 5 * sizeof(float));
2657         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2658
2659         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
2660         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
2661         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[40], 5 * sizeof(float));
2662         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2663
2664         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
2665         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
2666         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[60], 5 * sizeof(float));
2667         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2668         hr = IDirect3DDevice9_EndScene(device);
2669     }
2670
2671     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2672     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2673     /* With mipmapping disabled, the max mip level is ignored, only level 0 is used */
2674     color = getPixelColor(device, 160, 360);
2675     ok(color == 0x00FF0000, "MapMip 0, no mipfilter has color %08x\n", color);
2676     color = getPixelColor(device, 160, 120);
2677     ok(color == 0x00FF0000, "MapMip 3, no mipfilter has color %08x\n", color);
2678     color = getPixelColor(device, 480, 120);
2679     ok(color == 0x00FF0000, "MapMip 2, no mipfilter has color %08x\n", color);
2680     color = getPixelColor(device, 480, 360);
2681     ok(color == 0x00FF0000, "MapMip 1, no mipfilter has color %08x\n", color);
2682
2683     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
2684     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
2685
2686     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
2687     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
2688
2689     hr = IDirect3DDevice9_BeginScene(device);
2690     if(SUCCEEDED(hr))
2691     {
2692         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
2693         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
2694         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[ 0], 5 * sizeof(float));
2695         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2696
2697         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
2698         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
2699         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[20], 5 * sizeof(float));
2700         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2701
2702         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
2703         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
2704         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[40], 5 * sizeof(float));
2705         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2706
2707         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
2708         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
2709         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[60], 5 * sizeof(float));
2710         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2711         hr = IDirect3DDevice9_EndScene(device);
2712     }
2713
2714     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
2715     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
2716     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
2717     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
2718
2719     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2720     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2721     /* Max Mip level 0-2 sample from the specified texture level, Max Mip level 3(> levels in texture)
2722      * samples from the highest level in the texture(level 2)
2723      */
2724     color = getPixelColor(device, 160, 360);
2725     ok(color == 0x00FF0000, "MapMip 0, point mipfilter has color %08x\n", color);
2726     color = getPixelColor(device, 160, 120);
2727     ok(color == 0x000000FF, "MapMip 3, point mipfilter has color %08x\n", color);
2728     color = getPixelColor(device, 480, 120);
2729     ok(color == 0x000000FF, "MapMip 2, point mipfilter has color %08x\n", color);
2730     color = getPixelColor(device, 480, 360);
2731     ok(color == 0x0000FF00, "MapMip 1, point mipfilter has color %08x\n", color);
2732
2733     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
2734     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
2735     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
2736     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
2737     IDirect3DTexture9_Release(texture);
2738 }
2739
2740 static void release_buffer_test(IDirect3DDevice9 *device)
2741 {
2742     IDirect3DVertexBuffer9 *vb = NULL;
2743     IDirect3DIndexBuffer9 *ib = NULL;
2744     HRESULT hr;
2745     BYTE *data;
2746     long ref;
2747
2748     static const struct vertex quad[] = {
2749         {-1.0,      -1.0,       0.1,        0xffff0000},
2750         {-1.0,       1.0,       0.1,        0xffff0000},
2751         { 1.0,       1.0,       0.1,        0xffff0000},
2752
2753         {-1.0,      -1.0,       0.1,        0xff00ff00},
2754         {-1.0,       1.0,       0.1,        0xff00ff00},
2755         { 1.0,       1.0,       0.1,        0xff00ff00}
2756     };
2757     short indices[] = {3, 4, 5};
2758
2759     /* Index and vertex buffers should always be creatable */
2760     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, D3DFVF_XYZ | D3DFVF_DIFFUSE,
2761                                               D3DPOOL_MANAGED, &vb, NULL);
2762     ok(hr == D3D_OK, "CreateVertexBuffer failed with %s\n", DXGetErrorString9(hr));
2763     if(!vb) {
2764         skip("Failed to create a vertex buffer\n");
2765         return;
2766     }
2767     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, NULL);
2768     ok(hr == D3D_OK, "IDirect3DDevice9_CreateIndexBuffer failed with %s\n", DXGetErrorString9(hr));
2769     if(!ib) {
2770         skip("Failed to create an index buffer\n");
2771         return;
2772     }
2773
2774     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), (void **) &data, 0);
2775     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
2776     memcpy(data, quad, sizeof(quad));
2777     hr = IDirect3DVertexBuffer9_Unlock(vb);
2778     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr));
2779
2780     hr = IDirect3DIndexBuffer9_Lock(ib, 0, sizeof(indices), (void **) &data, 0);
2781     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
2782     memcpy(data, indices, sizeof(indices));
2783     hr = IDirect3DIndexBuffer9_Unlock(ib);
2784     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr));
2785
2786     hr = IDirect3DDevice9_SetIndices(device, ib);
2787     ok(hr == D3D_OK, "IDirect3DDevice9_SetIndices failed with %s\n", DXGetErrorString9(hr));
2788     hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad[0]));
2789     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr));
2790     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
2791     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2792
2793     /* Now destroy the bound index buffer and draw again */
2794     ref = IDirect3DIndexBuffer9_Release(ib);
2795     ok(ref == 0, "Index Buffer reference count is %08ld\n", ref);
2796
2797     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
2798     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
2799
2800     hr = IDirect3DDevice9_BeginScene(device);
2801     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
2802     if(SUCCEEDED(hr))
2803     {
2804         /* Deliberately using minvertexindex = 0 and numVertices = 6 to prevent d3d from
2805          * making assumptions about the indices or vertices
2806          */
2807         hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 3, 3, 0, 1);
2808         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitive failed with %08x\n", hr);
2809         hr = IDirect3DDevice9_EndScene(device);
2810         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
2811     }
2812
2813     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2814     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
2815
2816     hr = IDirect3DDevice9_SetIndices(device, NULL);
2817     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
2818     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
2819     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
2820
2821     /* Index buffer was already destroyed as part of the test */
2822     IDirect3DVertexBuffer9_Release(vb);
2823 }
2824
2825 static void float_texture_test(IDirect3DDevice9 *device)
2826 {
2827     IDirect3D9 *d3d = NULL;
2828     HRESULT hr;
2829     IDirect3DTexture9 *texture = NULL;
2830     D3DLOCKED_RECT lr;
2831     float *data;
2832     DWORD color;
2833     float quad[] = {
2834         -1.0,      -1.0,       0.1,     0.0,    0.0,
2835         -1.0,       1.0,       0.1,     0.0,    1.0,
2836          1.0,      -1.0,       0.1,     1.0,    0.0,
2837          1.0,       1.0,       0.1,     1.0,    1.0,
2838     };
2839
2840     memset(&lr, 0, sizeof(lr));
2841     IDirect3DDevice9_GetDirect3D(device, &d3d);
2842     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
2843                                      D3DRTYPE_TEXTURE, D3DFMT_R32F) != D3D_OK) {
2844         skip("D3DFMT_R32F textures not supported\n");
2845         goto out;
2846     }
2847
2848     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_R32F,
2849                                         D3DPOOL_MANAGED, &texture, NULL);
2850     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %s\n", DXGetErrorString9(hr));
2851     if(!texture) {
2852         skip("Failed to create R32F texture\n");
2853         goto out;
2854     }
2855
2856     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
2857     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %s\n", DXGetErrorString9(hr));
2858     data = lr.pBits;
2859     *data = 0.0;
2860     hr = IDirect3DTexture9_UnlockRect(texture, 0);
2861     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %s\n", DXGetErrorString9(hr));
2862
2863     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
2864     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
2865
2866     hr = IDirect3DDevice9_BeginScene(device);
2867     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
2868     if(SUCCEEDED(hr))
2869     {
2870         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2871         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2872
2873         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
2874         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2875
2876         hr = IDirect3DDevice9_EndScene(device);
2877         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
2878     }
2879     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
2880     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
2881
2882     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2883     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2884
2885     color = getPixelColor(device, 240, 320);
2886     ok(color == 0x0000FFFF, "R32F with value 0.0 has color %08x, expected 0x0000FFFF\n", color);
2887
2888 out:
2889     if(texture) IDirect3DTexture9_Release(texture);
2890     IDirect3D9_Release(d3d);
2891 }
2892
2893 static void g16r16_texture_test(IDirect3DDevice9 *device)
2894 {
2895     IDirect3D9 *d3d = NULL;
2896     HRESULT hr;
2897     IDirect3DTexture9 *texture = NULL;
2898     D3DLOCKED_RECT lr;
2899     DWORD *data;
2900     DWORD color, red, green, blue;
2901     float quad[] = {
2902        -1.0,      -1.0,       0.1,     0.0,    0.0,
2903        -1.0,       1.0,       0.1,     0.0,    1.0,
2904         1.0,      -1.0,       0.1,     1.0,    0.0,
2905         1.0,       1.0,       0.1,     1.0,    1.0,
2906     };
2907
2908     memset(&lr, 0, sizeof(lr));
2909     IDirect3DDevice9_GetDirect3D(device, &d3d);
2910     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
2911        D3DRTYPE_TEXTURE, D3DFMT_G16R16) != D3D_OK) {
2912            skip("D3DFMT_G16R16 textures not supported\n");
2913            goto out;
2914     }
2915
2916     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_G16R16,
2917                                         D3DPOOL_MANAGED, &texture, NULL);
2918     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %s\n", DXGetErrorString9(hr));
2919     if(!texture) {
2920         skip("Failed to create D3DFMT_G16R16 texture\n");
2921         goto out;
2922     }
2923
2924     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
2925     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %s\n", DXGetErrorString9(hr));
2926     data = lr.pBits;
2927     *data = 0x0f00f000;
2928     hr = IDirect3DTexture9_UnlockRect(texture, 0);
2929     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %s\n", DXGetErrorString9(hr));
2930
2931     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
2932     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
2933
2934     hr = IDirect3DDevice9_BeginScene(device);
2935     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
2936     if(SUCCEEDED(hr))
2937     {
2938         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2939         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2940
2941         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
2942         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2943
2944         hr = IDirect3DDevice9_EndScene(device);
2945         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
2946     }
2947     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
2948     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
2949
2950     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2951     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2952
2953     color = getPixelColor(device, 240, 320);
2954     red   = (color & 0x00ff0000) >> 16;
2955     green = (color & 0x0000ff00) >>  8;
2956     blue  = (color & 0x000000ff) >>  0;
2957     ok(blue == 0xff && red >= 0xef && red <= 0xf1 && green >= 0x0e && green <= 0x10,
2958        "D3DFMT_G16R16 with value 0x00ffff00 has color %08x, expected 0x00F00FFF\n", color);
2959
2960 out:
2961     if(texture) IDirect3DTexture9_Release(texture);
2962     IDirect3D9_Release(d3d);
2963 }
2964
2965 static void texture_transform_flags_test(IDirect3DDevice9 *device)
2966 {
2967     HRESULT hr;
2968     IDirect3D9 *d3d;
2969     D3DFORMAT fmt = D3DFMT_X8R8G8B8;
2970     D3DCAPS9 caps;
2971     IDirect3DTexture9 *texture = NULL;
2972     IDirect3DVolumeTexture9 *volume = NULL;
2973     unsigned int x, y, z;
2974     D3DLOCKED_RECT lr;
2975     D3DLOCKED_BOX lb;
2976     DWORD color;
2977     IDirect3DVertexDeclaration9 *decl, *decl2, *decl3;
2978     float identity[16] = {1.0, 0.0, 0.0, 0.0,
2979                            0.0, 1.0, 0.0, 0.0,
2980                            0.0, 0.0, 1.0, 0.0,
2981                            0.0, 0.0, 0.0, 1.0};
2982     static const D3DVERTEXELEMENT9 decl_elements[] = {
2983         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2984         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
2985         D3DDECL_END()
2986     };
2987     static const D3DVERTEXELEMENT9 decl_elements2[] = {
2988         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2989         {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
2990         D3DDECL_END()
2991     };
2992     static const D3DVERTEXELEMENT9 decl_elements3[] = {
2993         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
2994         {0, 12, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
2995         D3DDECL_END()
2996     };
2997     static const unsigned char proj_texdata[] = {0x00, 0x00, 0x00, 0x00,
2998                                                  0x00, 0xff, 0x00, 0x00,
2999                                                  0x00, 0x00, 0x00, 0x00,
3000                                                  0x00, 0x00, 0x00, 0x00};
3001
3002     memset(&lr, 0, sizeof(lr));
3003     memset(&lb, 0, sizeof(lb));
3004     IDirect3DDevice9_GetDirect3D(device, &d3d);
3005     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
3006                                      D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16) == D3D_OK) {
3007         fmt = D3DFMT_A16B16G16R16;
3008     }
3009     IDirect3D9_Release(d3d);
3010
3011     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
3012     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
3013     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements2, &decl2);
3014     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
3015     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements3, &decl3);
3016     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
3017     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, FALSE);
3018     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_SRGBTEXTURE) returned %s\n", DXGetErrorString9(hr));
3019     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
3020     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MAGFILTER) returned %s\n", DXGetErrorString9(hr));
3021     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
3022     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MINFILTER) returned %s\n", DXGetErrorString9(hr));
3023     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
3024     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MIPFILTER) returned %s\n", DXGetErrorString9(hr));
3025     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
3026     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSU) returned %s\n", DXGetErrorString9(hr));
3027     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
3028     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSV) returned %s\n", DXGetErrorString9(hr));
3029     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP);
3030     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSW) returned %s\n", DXGetErrorString9(hr));
3031     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
3032     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState(D3DRS_LIGHTING) returned %s\n", DXGetErrorString9(hr));
3033     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
3034     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
3035
3036     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
3037     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %s\n", DXGetErrorString9(hr));
3038     hr = IDirect3DDevice9_CreateTexture(device, caps.MaxTextureWidth, caps.MaxTextureHeight, 1,
3039                                         0, fmt, D3DPOOL_MANAGED, &texture, NULL);
3040     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %s\n", DXGetErrorString9(hr));
3041     if(!texture) {
3042         skip("Failed to create the test texture\n");
3043         return;
3044     }
3045
3046     /* Unfortunately there is no easy way to set up a texture coordinate passthrough
3047      * in d3d fixed function pipeline, so create a texture that has a gradient from 0.0 to
3048      * 1.0 in red and green for the x and y coords
3049      */
3050     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
3051     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %s\n", DXGetErrorString9(hr));
3052     for(y = 0; y < caps.MaxTextureHeight; y++) {
3053         for(x = 0; x < caps.MaxTextureWidth; x++) {
3054             double r_f = (double) y / (double) caps.MaxTextureHeight;
3055             double g_f = (double) x / (double) caps.MaxTextureWidth;
3056             if(fmt == D3DFMT_A16B16G16R16) {
3057                 unsigned short r, g;
3058                 unsigned short *dst = (unsigned short *) (((char *) lr.pBits) + y * lr.Pitch + x * 8);
3059                 r = (unsigned short) (r_f * 65536.0);
3060                 g = (unsigned short) (g_f * 65536.0);
3061                 dst[0] = r;
3062                 dst[1] = g;
3063                 dst[2] = 0;
3064                 dst[3] = 65535;
3065             } else {
3066                 unsigned char *dst = ((unsigned char *) lr.pBits) + y * lr.Pitch + x * 4;
3067                 unsigned char r = (unsigned char) (r_f * 255.0);
3068                 unsigned char g = (unsigned char) (g_f * 255.0);
3069                 dst[0] = 0;
3070                 dst[1] = g;
3071                 dst[2] = r;
3072                 dst[3] = 255;
3073             }
3074         }
3075     }
3076     hr = IDirect3DTexture9_UnlockRect(texture, 0);
3077     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect returned %s\n", DXGetErrorString9(hr));
3078     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3079     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
3080
3081     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3082     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
3083     hr = IDirect3DDevice9_BeginScene(device);
3084     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
3085     if(SUCCEEDED(hr))
3086     {
3087         float quad1[] = {
3088             -1.0,      -1.0,       0.1,     1.0,    1.0,
3089             -1.0,       0.0,       0.1,     1.0,    1.0,
3090              0.0,      -1.0,       0.1,     1.0,    1.0,
3091              0.0,       0.0,       0.1,     1.0,    1.0,
3092         };
3093         float quad2[] = {
3094             -1.0,       0.0,       0.1,     1.0,    1.0,
3095             -1.0,       1.0,       0.1,     1.0,    1.0,
3096              0.0,       0.0,       0.1,     1.0,    1.0,
3097              0.0,       1.0,       0.1,     1.0,    1.0,
3098         };
3099         float quad3[] = {
3100              0.0,       0.0,       0.1,     0.5,    0.5,
3101              0.0,       1.0,       0.1,     0.5,    0.5,
3102              1.0,       0.0,       0.1,     0.5,    0.5,
3103              1.0,       1.0,       0.1,     0.5,    0.5,
3104         };
3105         float quad4[] = {
3106              320,       480,       0.1,     1.0,    0.0,    1.0,
3107              320,       240,       0.1,     1.0,    0.0,    1.0,
3108              640,       480,       0.1,     1.0,    0.0,    1.0,
3109              640,       240,       0.1,     1.0,    0.0,    1.0,
3110         };
3111         float mat[16] = {0.0, 0.0, 0.0, 0.0,
3112                           0.0, 0.0, 0.0, 0.0,
3113                           0.0, 0.0, 0.0, 0.0,
3114                           0.0, 0.0, 0.0, 0.0};
3115
3116         /* What happens with the texture matrix if D3DTSS_TEXTURETRANSFORMFLAGS is disabled? */
3117         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3118         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
3119         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
3120         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3121
3122         /* What happens with transforms enabled? */
3123         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3124         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3125         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
3126         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3127
3128         /* What happens if 4 coords are used, but only 2 given ?*/
3129         mat[8] = 1.0;
3130         mat[13] = 1.0;
3131         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3132         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
3133         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
3134         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3135         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
3136         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3137
3138         /* What happens with transformed geometry? This setup lead to 0/0 coords with untransformed
3139          * geometry. If the same applies to transformed vertices, the quad will be black, otherwise red,
3140          * due to the coords in the vertices. (turns out red, indeed)
3141          */
3142         memset(mat, 0, sizeof(mat));
3143         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3144         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
3145         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_TEX1);
3146         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3147         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3148         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
3149         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
3150         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3151
3152         hr = IDirect3DDevice9_EndScene(device);
3153         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
3154     }
3155     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3156     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3157     color = getPixelColor(device, 160, 360);
3158     ok(color == 0x00FFFF00 || color == 0x00FEFE00, "quad 1 has color %08x, expected 0x00FFFF00\n", color);
3159     color = getPixelColor(device, 160, 120);
3160     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
3161     color = getPixelColor(device, 480, 120);
3162     ok(color == 0x0000FF00 || color == 0x0000FE00, "quad 3 has color %08x, expected 0x0000FF00\n", color);
3163     color = getPixelColor(device, 480, 360);
3164     ok(color == 0x00FF0000 || 0x00FE0000, "quad 4 has color %08x, expected 0x00FF0000\n", color);
3165
3166     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
3167     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
3168
3169     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3170     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
3171     hr = IDirect3DDevice9_BeginScene(device);
3172     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
3173     if(SUCCEEDED(hr))
3174     {
3175         float quad1[] = {
3176             -1.0,      -1.0,       0.1,     0.8,    0.2,
3177             -1.0,       0.0,       0.1,     0.8,    0.2,
3178              0.0,      -1.0,       0.1,     0.8,    0.2,
3179              0.0,       0.0,       0.1,     0.8,    0.2,
3180         };
3181         float quad2[] = {
3182             -1.0,       0.0,       0.1,     0.5,    1.0,
3183             -1.0,       1.0,       0.1,     0.5,    1.0,
3184              0.0,       0.0,       0.1,     0.5,    1.0,
3185              0.0,       1.0,       0.1,     0.5,    1.0,
3186         };
3187         float quad3[] = {
3188              0.0,       0.0,       0.1,     0.5,    1.0,
3189              0.0,       1.0,       0.1,     0.5,    1.0,
3190              1.0,       0.0,       0.1,     0.5,    1.0,
3191              1.0,       1.0,       0.1,     0.5,    1.0,
3192         };
3193         float quad4[] = {
3194              0.0,      -1.0,       0.1,     0.8,    0.2,
3195              0.0,       0.0,       0.1,     0.8,    0.2,
3196              1.0,      -1.0,       0.1,     0.8,    0.2,
3197              1.0,       0.0,       0.1,     0.8,    0.2,
3198         };
3199         float mat[16] = {0.0, 0.0, 0.0, 0.0,
3200                           0.0, 0.0, 0.0, 0.0,
3201                           0.0, 1.0, 0.0, 0.0,
3202                           0.0, 0.0, 0.0, 0.0};
3203
3204         /* What happens to the default 1 in the 3rd coordinate if it is disabled?
3205          */
3206         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3207         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
3208         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3209         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3210
3211         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
3212         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3213
3214         /* D3DTFF_COUNT1 does not work on Nvidia drivers. It behaves like D3DTTFF_DISABLE. On ATI drivers
3215          * it behaves like COUNT2 because normal textures require 2 coords
3216          */
3217         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
3218         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3219         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 5 * sizeof(float));
3220         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3221
3222         /* Just to be sure, the same as quad2 above */
3223         memset(mat, 0, sizeof(mat));
3224         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
3225         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
3226         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3227         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3228         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
3229         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3230
3231         /* Now, what happens to the 2nd coordinate(that is disabled in the matrix) if it is not
3232          * used? And what happens to the first?
3233          */
3234         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
3235         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3236         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
3237         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3238
3239         hr = IDirect3DDevice9_EndScene(device);
3240         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
3241     }
3242     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3243     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3244     color = getPixelColor(device, 160, 360);
3245     ok(color == 0x00FF0000 || color == 0x00FE0000, "quad 1 has color %08x, expected 0x00FF0000\n", color);
3246     color = getPixelColor(device, 160, 120);
3247     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
3248     color = getPixelColor(device, 480, 120);
3249     ok(color == 0x00ff8000 || color == 0x00fe7f00 || color == 0x00000000,
3250        "quad 3 has color %08x, expected 0x00ff8000\n", color);
3251     color = getPixelColor(device, 480, 360);
3252     ok(color == 0x0033cc00 || color == 0x0032cb00 || color == 0x00FF0000 || color == 0x00FE0000,
3253        "quad 4 has color %08x, expected 0x0033cc00\n", color);
3254
3255     IDirect3DTexture9_Release(texture);
3256
3257     /* Test projected textures, without any fancy matrices */
3258     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff203040, 0.0, 0);
3259     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
3260     hr = IDirect3DDevice9_CreateTexture(device, 4, 4, 1, 0, D3DFMT_L8, D3DPOOL_MANAGED, &texture, NULL);
3261     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %s\n", DXGetErrorString9(hr));
3262     hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &identity);
3263     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
3264     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl3);
3265     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
3266
3267     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
3268     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %s\n", DXGetErrorString9(hr));
3269     for(x = 0; x < 4; x++) {
3270         memcpy(((BYTE *) lr.pBits) + lr.Pitch * x, proj_texdata + 4 * x, 4 * sizeof(proj_texdata[0]));
3271     }
3272     hr = IDirect3DTexture9_UnlockRect(texture, 0);
3273     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %s\n", DXGetErrorString9(hr));
3274     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
3275     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
3276
3277     hr = IDirect3DDevice9_BeginScene(device);
3278     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
3279     if(SUCCEEDED(hr))
3280     {
3281         const float proj_quads[] = {
3282            -1.0,   -1.0,    0.1,    0.0,    0.0,    4.0,    6.0,
3283             1.0,   -1.0,    0.1,    4.0,    0.0,    4.0,    6.0,
3284            -1.0,    0.0,    0.1,    0.0,    4.0,    4.0,    6.0,
3285             1.0,    0.0,    0.1,    4.0,    4.0,    4.0,    6.0,
3286            -1.0,    0.0,    0.1,    0.0,    0.0,    4.0,    6.0,
3287             1.0,    0.0,    0.1,    4.0,    0.0,    4.0,    6.0,
3288            -1.0,    1.0,    0.1,    0.0,    4.0,    4.0,    6.0,
3289             1.0,    1.0,    0.1,    4.0,    4.0,    4.0,    6.0,
3290         };
3291
3292         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4 | D3DTTFF_PROJECTED);
3293         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3294         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &proj_quads[0*7], 7 * sizeof(float));
3295         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3296
3297         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3 | D3DTTFF_PROJECTED);
3298         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3299         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &proj_quads[4*7], 7 * sizeof(float));
3300         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
3301
3302         hr = IDirect3DDevice9_EndScene(device);
3303         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
3304     }
3305
3306     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3307     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
3308     IDirect3DTexture9_Release(texture);
3309
3310     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3311     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3312     color = getPixelColor(device, 158, 118);
3313     ok(color == 0x00000000, "proj: Pixel 158/118 has color 0x%08x, expected 0x00000000\n", color);
3314     color = getPixelColor(device, 162, 118);
3315     ok(color == 0x00000000, "proj: Pixel 162/118 has color 0x%08x, expected 0x00000000\n", color);
3316     color = getPixelColor(device, 158, 122);
3317     ok(color == 0x00000000, "proj: Pixel 158/122 has color 0x%08x, expected 0x00000000\n", color);
3318     color = getPixelColor(device, 162, 122);
3319     ok(color == 0x00FFFFFF, "proj: Pixel 162/122 has color 0x%08x, expected 0x00FFFFFF\n", color);
3320
3321     color = getPixelColor(device, 158, 178);
3322     ok(color == 0x00000000, "proj: Pixel 158/178 has color 0x%08x, expected 0x00000000\n", color);
3323     color = getPixelColor(device, 162, 178);
3324     ok(color == 0x00FFFFFF, "proj: Pixel 158/178 has color 0x%08x, expected 0x00FFFFFF\n", color);
3325     color = getPixelColor(device, 158, 182);
3326     ok(color == 0x00000000, "proj: Pixel 158/182 has color 0x%08x, expected 0x00000000\n", color);
3327     color = getPixelColor(device, 162, 182);
3328     ok(color == 0x00000000, "proj: Pixel 158/182 has color 0x%08x, expected 0x00000000\n", color);
3329
3330     color = getPixelColor(device, 318, 118);
3331     ok(color == 0x00000000, "proj: Pixel 318/118 has color 0x%08x, expected 0x00000000\n", color);
3332     color = getPixelColor(device, 322, 118);
3333     ok(color == 0x00000000, "proj: Pixel 322/118 has color 0x%08x, expected 0x00000000\n", color);
3334     color = getPixelColor(device, 318, 122);
3335     ok(color == 0x00FFFFFF, "proj: Pixel 318/122 has color 0x%08x, expected 0x00FFFFFF\n", color);
3336     color = getPixelColor(device, 322, 122);
3337     ok(color == 0x00000000, "proj: Pixel 322/122 has color 0x%08x, expected 0x00000000\n", color);
3338
3339     color = getPixelColor(device, 318, 178);
3340     ok(color == 0x00FFFFFF, "proj: Pixel 318/178 has color 0x%08x, expected 0x00FFFFFF\n", color);
3341     color = getPixelColor(device, 322, 178);
3342     ok(color == 0x00000000, "proj: Pixel 322/178 has color 0x%08x, expected 0x00000000\n", color);
3343     color = getPixelColor(device, 318, 182);
3344     ok(color == 0x00000000, "proj: Pixel 318/182 has color 0x%08x, expected 0x00000000\n", color);
3345     color = getPixelColor(device, 322, 182);
3346     ok(color == 0x00000000, "proj: Pixel 322/182 has color 0x%08x, expected 0x00000000\n", color);
3347
3348     color = getPixelColor(device, 238, 298);
3349     ok(color == 0x00000000, "proj: Pixel 238/298 has color 0x%08x, expected 0x00000000\n", color);
3350     color = getPixelColor(device, 242, 298);
3351     ok(color == 0x00000000, "proj: Pixel 242/298 has color 0x%08x, expected 0x00000000\n", color);
3352     color = getPixelColor(device, 238, 302);
3353     ok(color == 0x00000000, "proj: Pixel 238/302 has color 0x%08x, expected 0x00000000\n", color);
3354     color = getPixelColor(device, 242, 302);
3355     ok(color == 0x00FFFFFF, "proj: Pixel 242/302 has color 0x%08x, expected 0x00FFFFFF\n", color);
3356
3357     color = getPixelColor(device, 238, 388);
3358     ok(color == 0x00000000, "proj: Pixel 238/388 has color 0x%08x, expected 0x00000000\n", color);
3359     color = getPixelColor(device, 242, 388);
3360     ok(color == 0x00FFFFFF, "proj: Pixel 242/388 has color 0x%08x, expected 0x00FFFFFF\n", color);
3361     color = getPixelColor(device, 238, 392);
3362     ok(color == 0x00000000, "proj: Pixel 238/392 has color 0x%08x, expected 0x00000000\n", color);
3363     color = getPixelColor(device, 242, 392);
3364     ok(color == 0x00000000, "proj: Pixel 242/392 has color 0x%08x, expected 0x00000000\n", color);
3365
3366     color = getPixelColor(device, 478, 298);
3367     ok(color == 0x00000000, "proj: Pixel 478/298 has color 0x%08x, expected 0x00000000\n", color);
3368     color = getPixelColor(device, 482, 298);
3369     ok(color == 0x00000000, "proj: Pixel 482/298 has color 0x%08x, expected 0x00000000\n", color);
3370     color = getPixelColor(device, 478, 302);
3371     ok(color == 0x00FFFFFF, "proj: Pixel 478/302 has color 0x%08x, expected 0x00FFFFFF\n", color);
3372     color = getPixelColor(device, 482, 302);
3373     ok(color == 0x00000000, "proj: Pixel 482/302 has color 0x%08x, expected 0x00000000\n", color);
3374
3375     color = getPixelColor(device, 478, 388);
3376     ok(color == 0x00FFFFFF, "proj: Pixel 478/388 has color 0x%08x, expected 0x00FFFFFF\n", color);
3377     color = getPixelColor(device, 482, 388);
3378     ok(color == 0x00000000, "proj: Pixel 482/388 has color 0x%08x, expected 0x00000000\n", color);
3379     color = getPixelColor(device, 478, 392);
3380     ok(color == 0x00000000, "proj: Pixel 478/392 has color 0x%08x, expected 0x00000000\n", color);
3381     color = getPixelColor(device, 482, 392);
3382     ok(color == 0x00000000, "proj: Pixel 482/392 has color 0x%08x, expected 0x00000000\n", color);
3383
3384     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff203040, 0.0, 0);
3385     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
3386     /* Use a smaller volume texture than the biggest possible size for memory and performance reasons
3387      * Thus watch out if sampling from texels between 0 and 1.
3388      */
3389     hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 32, 1, 0, fmt, D3DPOOL_MANAGED, &volume, 0);
3390     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
3391        "IDirect3DDevice9_CreateVolumeTexture failed with %s\n", DXGetErrorString9(hr));
3392     if(!volume) {
3393         skip("Failed to create a volume texture\n");
3394         goto out;
3395     }
3396
3397     hr = IDirect3DVolumeTexture9_LockBox(volume, 0, &lb, NULL, 0);
3398     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_LockBox failed with %s\n", DXGetErrorString9(hr));
3399     for(z = 0; z < 32; z++) {
3400         for(y = 0; y < 32; y++) {
3401             for(x = 0; x < 32; x++) {
3402                 char size = (fmt == D3DFMT_A16B16G16R16 ? 8 : 4);
3403                 void *mem = ((char *)  lb.pBits) + y * lb.RowPitch + z * lb.SlicePitch + x * size;
3404                 float r_f = (float) x / 31.0;
3405                 float g_f = (float) y / 31.0;
3406                 float b_f = (float) z / 31.0;
3407
3408                 if(fmt == D3DFMT_A16B16G16R16) {
3409                     unsigned short *mem_s = mem;
3410                     mem_s[0]  = r_f * 65535.0;
3411                     mem_s[1]  = g_f * 65535.0;
3412                     mem_s[2]  = b_f * 65535.0;
3413                     mem_s[3]  = 65535;
3414                 } else {
3415                     unsigned char *mem_c = mem;
3416                     mem_c[0]  = b_f * 255.0;
3417                     mem_c[1]  = g_f * 255.0;
3418                     mem_c[2]  = r_f * 255.0;
3419                     mem_c[3]  = 255;
3420                 }
3421             }
3422         }
3423     }
3424     hr = IDirect3DVolumeTexture9_UnlockBox(volume, 0);
3425     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %s\n", DXGetErrorString9(hr));
3426
3427     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) volume);
3428     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %s\n", DXGetErrorString9(hr));
3429
3430     hr = IDirect3DDevice9_BeginScene(device);
3431     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
3432     if(SUCCEEDED(hr))
3433     {
3434         float quad1[] = {
3435             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3436             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
3437              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3438              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
3439         };
3440         float quad2[] = {
3441             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
3442             -1.0,       1.0,       0.1,     1.0,    1.0,    1.0,
3443              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
3444              0.0,       1.0,       0.1,     1.0,    1.0,    1.0
3445         };
3446         float quad3[] = {
3447              0.0,       0.0,       0.1,     0.0,    0.0,
3448              0.0,       1.0,       0.1,     0.0,    0.0,
3449              1.0,       0.0,       0.1,     0.0,    0.0,
3450              1.0,       1.0,       0.1,     0.0,    0.0
3451         };
3452         float quad4[] = {
3453              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3454              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
3455              1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3456              1.0,       0.0,       0.1,     1.0,    1.0,    1.0
3457         };
3458         float mat[16] = {1.0, 0.0, 0.0, 0.0,
3459                          0.0, 0.0, 1.0, 0.0,
3460                          0.0, 1.0, 0.0, 0.0,
3461                          0.0, 0.0, 0.0, 1.0};
3462         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3463         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
3464
3465         /* Draw a quad with all 3 coords enabled. Nothing fancy. v and w are swapped, but have the same
3466          * values
3467          */
3468         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
3469         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
3470         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
3471         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3472         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
3473         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3474
3475         /* Now disable the w coordinate. Does that change the input, or the output. The coordinates
3476          * are swapped by the matrix. If it changes the input, the v coord will be missing(green),
3477          * otherwise the w will be missing(blue).
3478          * turns out that on nvidia cards the blue color is missing, so it is an output modification.
3479          * On ATI cards the COUNT2 is ignored, and it behaves in the same way as COUNT3.
3480          */
3481         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
3482         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3483         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
3484         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3485
3486         /* default values? Set up the identity matrix, pass in 2 vertex coords, and enable 4 */
3487         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
3488         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
3489         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
3490         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3491         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
3492         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
3493         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
3494         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3495
3496         /* D3DTTFF_COUNT1. Set a NULL matrix, and count1, pass in all values as 1.0. Nvidia has count1 ==
3497          * disable. ATI extends it up to the amount of values needed for the volume texture
3498          */
3499         memset(mat, 0, sizeof(mat));
3500         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
3501         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
3502         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
3503         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3504         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3505         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
3506         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
3507         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3508
3509         hr = IDirect3DDevice9_EndScene(device);
3510         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
3511     }
3512     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3513     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3514
3515     color = getPixelColor(device, 160, 360);
3516     ok(color == 0x00ffffff, "quad 1 has color %08x, expected 0x00ffffff\n", color);
3517     color = getPixelColor(device, 160, 120);
3518     ok(color == 0x00ffff00 /* NV*/ || color == 0x00ffffff /* ATI */,
3519        "quad 2 has color %08x, expected 0x00ffff00\n", color);
3520     color = getPixelColor(device, 480, 120);
3521     ok(color == 0x000000ff, "quad 3 has color %08x, expected 0x000000ff\n", color);
3522     color = getPixelColor(device, 480, 360);
3523     ok(color == 0x00ffffff || color == 0x0000ff00, "quad 4 has color %08x, expected 0x00ffffff\n", color);
3524
3525     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff303030, 0.0, 0);
3526     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
3527     hr = IDirect3DDevice9_BeginScene(device);
3528     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
3529     if(SUCCEEDED(hr))
3530     {
3531         float quad1[] = {
3532             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3533             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
3534              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
3535              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
3536         };
3537         float quad2[] = {
3538             -1.0,       0.0,       0.1,
3539             -1.0,       1.0,       0.1,
3540              0.0,       0.0,       0.1,
3541              0.0,       1.0,       0.1,
3542         };
3543         float quad3[] = {
3544              0.0,       0.0,       0.1,     1.0,
3545              0.0,       1.0,       0.1,     1.0,
3546              1.0,       0.0,       0.1,     1.0,
3547              1.0,       1.0,       0.1,     1.0
3548         };
3549         float mat[16] =  {0.0, 0.0, 0.0, 0.0,
3550                            0.0, 0.0, 0.0, 0.0,
3551                            0.0, 0.0, 0.0, 0.0,
3552                            0.0, 1.0, 0.0, 0.0};
3553         float mat2[16] = {0.0, 0.0, 0.0, 1.0,
3554                            1.0, 0.0, 0.0, 0.0,
3555                            0.0, 1.0, 0.0, 0.0,
3556                            0.0, 0.0, 1.0, 0.0};
3557         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
3558         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
3559
3560         /* Default values? 4 coords used, 3 passed. What happens to the 4th?
3561          */
3562         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
3563         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
3564         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
3565         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3566         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
3567         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3568
3569         /* None passed */
3570         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
3571         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
3572         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
3573         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
3574         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
3575         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3576
3577         /* 4 used, 1 passed */
3578         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl2);
3579         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
3580         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat2);
3581         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
3582         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 4 * sizeof(float));
3583         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3584
3585         hr = IDirect3DDevice9_EndScene(device);
3586         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
3587     }
3588     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3589     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3590     color = getPixelColor(device, 160, 360);
3591     ok(color == 0x0000ff00, "quad 1 has color %08x, expected 0x0000ff00\n", color);
3592     color = getPixelColor(device, 160, 120);
3593     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x00000000\n", color);
3594     color = getPixelColor(device, 480, 120);
3595     ok(color == 0x00ff0000, "quad 3 has color %08x, expected 0x00ff0000\n", color);
3596     /* Quad4: unused */
3597
3598     IDirect3DVolumeTexture9_Release(volume);
3599
3600     out:
3601     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
3602     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
3603     IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
3604     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
3605     hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &identity);
3606     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
3607     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
3608     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
3609     IDirect3DVertexDeclaration9_Release(decl);
3610     IDirect3DVertexDeclaration9_Release(decl2);
3611     IDirect3DVertexDeclaration9_Release(decl3);
3612 }
3613
3614 static void texdepth_test(IDirect3DDevice9 *device)
3615 {
3616     IDirect3DPixelShader9 *shader;
3617     HRESULT hr;
3618     const float texdepth_test_data1[] = { 0.25,  2.0, 0.0, 0.0};
3619     const float texdepth_test_data2[] = { 0.25,  0.5, 0.0, 0.0};
3620     const float texdepth_test_data3[] = {-1.00,  0.1, 0.0, 0.0};
3621     const float texdepth_test_data4[] = {-0.25, -0.5, 0.0, 0.0};
3622     const float texdepth_test_data5[] = { 1.00, -0.1, 0.0, 0.0};
3623     const float texdepth_test_data6[] = { 1.00,  0.5, 0.0, 0.0};
3624     const float texdepth_test_data7[] = { 0.50,  0.0, 0.0, 0.0};
3625     DWORD shader_code[] = {
3626         0xffff0104,                                                                 /* ps_1_4               */
3627         0x00000051, 0xa00f0001, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000,     /* def c1, 0, 0, 1, 1   */
3628         0x00000001, 0x800f0005, 0xa0e40000,                                         /* mov r5, c0           */
3629         0x0000fffd,                                                                 /* phase                */
3630         0x00000057, 0x800f0005,                                                     /* texdepth r5          */
3631         0x00000001, 0x800f0000, 0xa0e40001,                                         /* mov r0, c1           */
3632         0x0000ffff                                                                  /* end                  */
3633     };
3634     DWORD color;
3635     float vertex[] = {
3636        -1.0,   -1.0,    0.0,
3637         1.0,   -1.0,    1.0,
3638        -1.0,    1.0,    0.0,
3639         1.0,    1.0,    1.0
3640     };
3641
3642     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
3643     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
3644
3645     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffff00, 0.0, 0);
3646     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
3647     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
3648     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
3649     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
3650     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
3651     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
3652     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
3653     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
3654
3655     /* Fill the depth buffer with a gradient */
3656     hr = IDirect3DDevice9_BeginScene(device);
3657     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
3658     if(SUCCEEDED(hr))
3659     {
3660         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3661         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3662         hr = IDirect3DDevice9_EndScene(device);
3663         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3664     }
3665
3666     /* Now perform the actual tests. Same geometry, but with the shader */
3667     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
3668     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
3669     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
3670     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
3671     hr = IDirect3DDevice9_SetPixelShader(device, shader);
3672     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
3673
3674     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data1, 1);
3675     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
3676     hr = IDirect3DDevice9_BeginScene(device);
3677     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
3678     if(SUCCEEDED(hr))
3679     {
3680         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3681         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3682
3683         hr = IDirect3DDevice9_EndScene(device);
3684         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3685     }
3686
3687     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3688     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3689     color = getPixelColor(device, 158, 240);
3690     ok(color == 0x000000ff, "Pixel 158(25%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
3691     color = getPixelColor(device, 162, 240);
3692     ok(color == 0x00ffffff, "Pixel 158(25%% + 2 pixel) has color %08x, expected 0x00ffffff\n", color);
3693
3694     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
3695
3696     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data2, 1);
3697     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
3698     hr = IDirect3DDevice9_BeginScene(device);
3699     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
3700     if(SUCCEEDED(hr))
3701     {
3702         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3703         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3704
3705         hr = IDirect3DDevice9_EndScene(device);
3706         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3707     }
3708
3709     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3710     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3711     color = getPixelColor(device, 318, 240);
3712     ok(color == 0x000000ff, "Pixel 318(50%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
3713     color = getPixelColor(device, 322, 240);
3714     ok(color == 0x00ffff00, "Pixel 322(50%% + 2 pixel) has color %08x, expected 0x00ffff00\n", color);
3715
3716     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
3717
3718     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data3, 1);
3719     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
3720     hr = IDirect3DDevice9_BeginScene(device);
3721     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
3722     if(SUCCEEDED(hr))
3723     {
3724         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3725         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3726
3727         hr = IDirect3DDevice9_EndScene(device);
3728         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3729     }
3730     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3731     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3732
3733     color = getPixelColor(device, 1, 240);
3734     ok(color == 0x00ff0000, "Pixel 1(0%% + 2 pixel) has color %08x, expected 0x00ff0000\n", color);
3735
3736     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
3737
3738     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data4, 1);
3739     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
3740     hr = IDirect3DDevice9_BeginScene(device);
3741     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
3742     if(SUCCEEDED(hr))
3743     {
3744         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3745         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3746
3747         hr = IDirect3DDevice9_EndScene(device);
3748         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3749     }
3750     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3751     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3752     color = getPixelColor(device, 318, 240);
3753     ok(color == 0x000000ff, "Pixel 318(50%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
3754     color = getPixelColor(device, 322, 240);
3755     ok(color == 0x0000ff00, "Pixel 322(50%% + 2 pixel) has color %08x, expected 0x0000ff00\n", color);
3756
3757     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
3758
3759     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data5, 1);
3760     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
3761     hr = IDirect3DDevice9_BeginScene(device);
3762     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
3763     if(SUCCEEDED(hr))
3764     {
3765         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3766         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3767
3768         hr = IDirect3DDevice9_EndScene(device);
3769         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3770     }
3771     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3772     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3773
3774     color = getPixelColor(device, 1, 240);
3775     ok(color == 0x00ffff00, "Pixel 1(0%% + 2 pixel) has color %08x, expected 0x00ffff00\n", color);
3776
3777     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
3778
3779     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data6, 1);
3780     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
3781     hr = IDirect3DDevice9_BeginScene(device);
3782     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
3783     if(SUCCEEDED(hr))
3784     {
3785         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
3786         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3787
3788         hr = IDirect3DDevice9_EndScene(device);
3789         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3790     }
3791     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3792     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3793
3794     color = getPixelColor(device, 638, 240);
3795     ok(color == 0x000000ff, "Pixel 638(100%% + 2 pixel) has color %08x, expected 0x000000ff\n", color);
3796
3797     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
3798
3799     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data7, 1);
3800     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
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, vertex, 3 * sizeof(float));
3806         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3807
3808         hr = IDirect3DDevice9_EndScene(device);
3809         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3810     }
3811     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3812     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3813
3814     color = getPixelColor(device, 638, 240);
3815     ok(color == 0x000000ff, "Pixel 638(100%% + 2 pixel) has color %08x, expected 0x000000ff\n", color);
3816
3817     /* Cleanup */
3818     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
3819     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
3820     IDirect3DPixelShader9_Release(shader);
3821
3822     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
3823     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
3824     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
3825     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
3826 }
3827
3828 static void texkill_test(IDirect3DDevice9 *device)
3829 {
3830     IDirect3DPixelShader9 *shader;
3831     HRESULT hr;
3832     DWORD color;
3833
3834     const float vertex[] = {
3835     /*                          bottom  top    right    left */
3836         -1.0,   -1.0,   1.0,   -0.1,    0.9,    0.9,   -0.1,
3837          1.0,   -1.0,   0.0,    0.9,   -0.1,    0.9,   -0.1,
3838         -1.0,    1.0,   1.0,   -0.1,    0.9,   -0.1,    0.9,
3839          1.0,    1.0,   0.0,    0.9,   -0.1,   -0.1,    0.9,
3840     };
3841
3842     DWORD shader_code_11[] = {
3843     0xffff0101,                                                             /* ps_1_1                     */
3844     0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0 */
3845     0x00000041, 0xb00f0000,                                                 /* texkill t0                 */
3846     0x00000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                 */
3847     0x0000ffff                                                              /* end                        */
3848     };
3849     DWORD shader_code_20[] = {
3850     0xffff0200,                                                             /* ps_2_0                     */
3851     0x0200001f, 0x80000000, 0xb00f0000,                                     /* dcl t0                     */
3852     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c0, 0.0, 0.0, 1.0, 1.0 */
3853     0x01000041, 0xb00f0000,                                                 /* texkill t0                 */
3854     0x02000001, 0x800f0800, 0xa0e40000,                                     /* mov oC0, c0                */
3855     0x0000ffff                                                              /* end                        */
3856     };
3857
3858     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
3859     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
3860     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader);
3861     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
3862
3863     hr = IDirect3DDevice9_SetPixelShader(device, shader);
3864     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
3865     hr = IDirect3DDevice9_BeginScene(device);
3866     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
3867     if(SUCCEEDED(hr))
3868     {
3869         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1);
3870         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
3871         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 7 * sizeof(float));
3872         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3873         hr = IDirect3DDevice9_EndScene(device);
3874         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3875     }
3876     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3877     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3878     color = getPixelColor(device, 63, 46);
3879     ok(color == 0x0000ff00, "Pixel 63/46 has color %08x, expected 0x0000ff00\n", color);
3880     color = getPixelColor(device, 66, 46);
3881     ok(color == 0x0000ff00, "Pixel 66/64 has color %08x, expected 0x0000ff00\n", color);
3882     color = getPixelColor(device, 63, 49);
3883     ok(color == 0x0000ff00, "Pixel 63/49 has color %08x, expected 0x0000ff00\n", color);
3884     color = getPixelColor(device, 66, 49);
3885     ok(color == 0x00ff0000, "Pixel 66/49 has color %08x, expected 0x00ff0000\n", color);
3886
3887     color = getPixelColor(device, 578, 46);
3888     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
3889     color = getPixelColor(device, 575, 46);
3890     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
3891     color = getPixelColor(device, 578, 49);
3892     ok(color == 0x0000ff00, "Pixel 578/49 has color %08x, expected 0x0000ff00\n", color);
3893     color = getPixelColor(device, 575, 49);
3894     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
3895
3896     color = getPixelColor(device, 63, 430);
3897     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
3898     color = getPixelColor(device, 63, 433);
3899     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
3900     color = getPixelColor(device, 66, 433);
3901     ok(color == 0x00ff0000, "Pixel 578/49 has color %08x, expected 0x00ff0000\n", color);
3902     color = getPixelColor(device, 66, 430);
3903     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
3904
3905     color = getPixelColor(device, 578, 430);
3906     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
3907     color = getPixelColor(device, 578, 433);
3908     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
3909     color = getPixelColor(device, 575, 433);
3910     ok(color == 0x00ff0000, "Pixel 578/49 has color %08x, expected 0x00ff0000\n", color);
3911     color = getPixelColor(device, 575, 430);
3912     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
3913
3914     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
3915     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
3916     IDirect3DPixelShader9_Release(shader);
3917
3918     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
3919     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
3920     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_20, &shader);
3921     if(FAILED(hr)) {
3922         skip("Failed to create 2.0 test shader, most likely not supported\n");
3923         return;
3924     }
3925
3926     hr = IDirect3DDevice9_SetPixelShader(device, shader);
3927     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
3928     hr = IDirect3DDevice9_BeginScene(device);
3929     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
3930     if(SUCCEEDED(hr))
3931     {
3932         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 7 * sizeof(float));
3933         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
3934         hr = IDirect3DDevice9_EndScene(device);
3935         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
3936     }
3937     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
3938
3939     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
3940     color = getPixelColor(device, 63, 46);
3941     ok(color == 0x00ffff00, "Pixel 63/46 has color %08x, expected 0x00ffff00\n", color);
3942     color = getPixelColor(device, 66, 46);
3943     ok(color == 0x00ffff00, "Pixel 66/64 has color %08x, expected 0x00ffff00\n", color);
3944     color = getPixelColor(device, 63, 49);
3945     ok(color == 0x00ffff00, "Pixel 63/49 has color %08x, expected 0x00ffff00\n", color);
3946     color = getPixelColor(device, 66, 49);
3947     ok(color == 0x000000ff, "Pixel 66/49 has color %08x, expected 0x000000ff\n", color);
3948
3949     color = getPixelColor(device, 578, 46);
3950     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
3951     color = getPixelColor(device, 575, 46);
3952     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
3953     color = getPixelColor(device, 578, 49);
3954     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
3955     color = getPixelColor(device, 575, 49);
3956     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
3957
3958     color = getPixelColor(device, 63, 430);
3959     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
3960     color = getPixelColor(device, 63, 433);
3961     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
3962     color = getPixelColor(device, 66, 433);
3963     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
3964     color = getPixelColor(device, 66, 430);
3965     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
3966
3967     color = getPixelColor(device, 578, 430);
3968     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
3969     color = getPixelColor(device, 578, 433);
3970     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
3971     color = getPixelColor(device, 575, 433);
3972     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
3973     color = getPixelColor(device, 575, 430);
3974     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
3975
3976     /* Cleanup */
3977     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
3978     ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
3979     IDirect3DPixelShader9_Release(shader);
3980 }
3981
3982 static void x8l8v8u8_test(IDirect3DDevice9 *device)
3983 {
3984     IDirect3D9 *d3d9;
3985     HRESULT hr;
3986     IDirect3DTexture9 *texture;
3987     IDirect3DPixelShader9 *shader;
3988     IDirect3DPixelShader9 *shader2;
3989     D3DLOCKED_RECT lr;
3990     DWORD color;
3991     DWORD shader_code[] = {
3992         0xffff0101,                             /* ps_1_1       */
3993         0x00000042, 0xb00f0000,                 /* tex t0       */
3994         0x00000001, 0x800f0000, 0xb0e40000,     /* mov r0, t0   */
3995         0x0000ffff                              /* end          */
3996     };
3997     DWORD shader_code2[] = {
3998         0xffff0101,                             /* ps_1_1       */
3999         0x00000042, 0xb00f0000,                 /* tex t0       */
4000         0x00000001, 0x800f0000, 0xb0ff0000,     /* mov r0, t0.w */
4001         0x0000ffff                              /* end          */
4002     };
4003
4004     float quad[] = {
4005        -1.0,   -1.0,   0.1,     0.5,    0.5,
4006         1.0,   -1.0,   0.1,     0.5,    0.5,
4007        -1.0,    1.0,   0.1,     0.5,    0.5,
4008         1.0,    1.0,   0.1,     0.5,    0.5,
4009     };
4010
4011     memset(&lr, 0, sizeof(lr));
4012     IDirect3DDevice9_GetDirect3D(device, &d3d9);
4013     hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4014                                       0,  D3DRTYPE_TEXTURE, D3DFMT_X8L8V8U8);
4015     IDirect3D9_Release(d3d9);
4016     if(FAILED(hr)) {
4017         skip("No D3DFMT_X8L8V8U8 support\n");
4018     };
4019
4020     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
4021     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
4022
4023     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_X8L8V8U8, D3DPOOL_MANAGED, &texture, NULL);
4024     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed (%08x)\n", hr);
4025     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
4026     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed (%08x)\n", hr);
4027     *((DWORD *) lr.pBits) = 0x11ca3141;
4028     hr = IDirect3DTexture9_UnlockRect(texture, 0);
4029     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed (%08x)\n", hr);
4030
4031     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
4032     ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr);
4033     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code2, &shader2);
4034     ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr);
4035
4036     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4037     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed (%08x)\n", hr);
4038     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4039     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4040     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
4041     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
4042
4043     hr = IDirect3DDevice9_BeginScene(device);
4044     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4045     if(SUCCEEDED(hr))
4046     {
4047         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
4048         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4049
4050         hr = IDirect3DDevice9_EndScene(device);
4051         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4052     }
4053     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4054     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4055     color = getPixelColor(device, 578, 430);
4056     ok(color == 0x008262ca || color == 0x008363ca || color == 0x008362ca,
4057        "D3DFMT_X8L8V8U8 = 0x112131ca returns color %08x, expected 0x008262ca\n", color);
4058
4059     hr = IDirect3DDevice9_SetPixelShader(device, shader2);
4060     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4061     hr = IDirect3DDevice9_BeginScene(device);
4062     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4063     if(SUCCEEDED(hr))
4064     {
4065         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
4066         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4067
4068         hr = IDirect3DDevice9_EndScene(device);
4069         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
4070     }
4071     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4072     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4073     color = getPixelColor(device, 578, 430);
4074     ok(color == 0x00ffffff, "w component of D3DFMT_X8L8V8U8 = 0x11ca3141 returns color %08x\n", color);
4075
4076     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4077     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
4078     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4079     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
4080     IDirect3DPixelShader9_Release(shader);
4081     IDirect3DPixelShader9_Release(shader2);
4082     IDirect3DTexture9_Release(texture);
4083 }
4084
4085 static void autogen_mipmap_test(IDirect3DDevice9 *device)
4086 {
4087     HRESULT hr;
4088     IDirect3D9 *d3d;
4089     IDirect3DTexture9 *texture = NULL;
4090     IDirect3DSurface9 *surface;
4091     DWORD color;
4092     const RECT r1 = {256, 256, 512, 512};
4093     const RECT r2 = {512, 256, 768, 512};
4094     const RECT r3 = {256, 512, 512, 768};
4095     const RECT r4 = {512, 512, 768, 768};
4096     unsigned int x, y;
4097     D3DLOCKED_RECT lr;
4098     memset(&lr, 0, sizeof(lr));
4099
4100     IDirect3DDevice9_GetDirect3D(device, &d3d);
4101     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
4102        D3DUSAGE_AUTOGENMIPMAP,  D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8) != D3D_OK) {
4103         skip("No autogenmipmap support\n");
4104         IDirect3D9_Release(d3d);
4105         return;
4106     }
4107     IDirect3D9_Release(d3d);
4108
4109     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
4110     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
4111
4112     /* Make the mipmap big, so that a smaller mipmap is used
4113      */
4114     hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 0, D3DUSAGE_AUTOGENMIPMAP,
4115                                         D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
4116     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %s\n", DXGetErrorString9(hr));
4117
4118     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
4119     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel returned %s\n", DXGetErrorString9(hr));
4120     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
4121     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %s\n", DXGetErrorString9(hr));
4122     for(y = 0; y < 1024; y++) {
4123         for(x = 0; x < 1024; x++) {
4124             DWORD *dst = (DWORD *) (((BYTE *) lr.pBits) + y * lr.Pitch + x * 4);
4125             POINT pt;
4126
4127             pt.x = x;
4128             pt.y = y;
4129             if(PtInRect(&r1, pt)) {
4130                 *dst = 0xffff0000;
4131             } else if(PtInRect(&r2, pt)) {
4132                 *dst = 0xff00ff00;
4133             } else if(PtInRect(&r3, pt)) {
4134                 *dst = 0xff0000ff;
4135             } else if(PtInRect(&r4, pt)) {
4136                 *dst = 0xff000000;
4137             } else {
4138                 *dst = 0xffffffff;
4139             }
4140         }
4141     }
4142     hr = IDirect3DSurface9_UnlockRect(surface);
4143     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect returned %s\n", DXGetErrorString9(hr));
4144     IDirect3DSurface9_Release(surface);
4145
4146     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
4147     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
4148     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
4149     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
4150
4151     hr = IDirect3DDevice9_BeginScene(device);
4152     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
4153     if(SUCCEEDED(hr)) {
4154         const float quad[] =  {
4155            -0.5,   -0.5,    0.1,    0.0,    0.0,
4156            -0.5,    0.5,    0.1,    0.0,    1.0,
4157             0.5,   -0.5,    0.1,    1.0,    0.0,
4158             0.5,    0.5,    0.1,    1.0,    1.0
4159         };
4160
4161         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4162         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
4163         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
4164         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4165         hr = IDirect3DDevice9_EndScene(device);
4166         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
4167     }
4168     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
4169     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
4170     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
4171     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
4172     IDirect3DTexture9_Release(texture);
4173
4174     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4175     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4176     color = getPixelColor(device, 200, 200);
4177     ok(color == 0x00ffffff, "pixel 200/200 has color %08x, expected 0x00ffffff\n", color);
4178     color = getPixelColor(device, 280, 200);
4179     ok(color == 0x000000ff, "pixel 280/200 has color %08x, expected 0x000000ff\n", color);
4180     color = getPixelColor(device, 360, 200);
4181     ok(color == 0x00000000, "pixel 360/200 has color %08x, expected 0x00000000\n", color);
4182     color = getPixelColor(device, 440, 200);
4183     ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
4184     color = getPixelColor(device, 200, 270);
4185     ok(color == 0x00ffffff, "pixel 200/270 has color %08x, expected 0x00ffffff\n", color);
4186     color = getPixelColor(device, 280, 270);
4187     ok(color == 0x00ff0000, "pixel 280/270 has color %08x, expected 0x00ff0000\n", color);
4188     color = getPixelColor(device, 360, 270);
4189     ok(color == 0x0000ff00, "pixel 360/270 has color %08x, expected 0x0000ff00\n", color);
4190     color = getPixelColor(device, 440, 270);
4191     ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
4192 }
4193
4194 static void test_constant_clamp_vs(IDirect3DDevice9 *device)
4195 {
4196     IDirect3DVertexShader9 *shader_11, *shader_11_2, *shader_20, *shader_20_2;
4197     IDirect3DVertexDeclaration9 *decl;
4198     HRESULT hr;
4199     DWORD color;
4200     DWORD shader_code_11[] =  {
4201         0xfffe0101,                                         /* vs_1_1           */
4202         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4203         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4204         0x00000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4205         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4206         0x0000ffff                                          /* end              */
4207     };
4208     DWORD shader_code_11_2[] =  {
4209         0xfffe0101,                                         /* vs_1_1           */
4210         0x00000051, 0xa00f0001, 0x3fa00000, 0xbf000000, 0xbfc00000, 0x3f800000, /* dcl ... */
4211         0x00000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000, /* dcl ... */
4212         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4213         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4214         0x00000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4215         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4216         0x0000ffff                                          /* end              */
4217     };
4218     DWORD shader_code_20[] =  {
4219         0xfffe0200,                                         /* vs_2_0           */
4220         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4221         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4222         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4223         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4224         0x0000ffff                                          /* end              */
4225     };
4226     DWORD shader_code_20_2[] =  {
4227         0xfffe0200,                                         /* vs_2_0           */
4228         0x05000051, 0xa00f0001, 0x3fa00000, 0xbf000000, 0xbfc00000, 0x3f800000,
4229         0x05000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000,
4230         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0  */
4231         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4232         0x03000002, 0xd00f0000, 0x80e40001, 0xa0e40002,     /* add oD0, r1, c2  */
4233         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0     */
4234         0x0000ffff                                          /* end              */
4235     };
4236     static const D3DVERTEXELEMENT9 decl_elements[] = {
4237         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
4238         D3DDECL_END()
4239     };
4240     float quad1[] = {
4241         -1.0,   -1.0,   0.1,
4242          0.0,   -1.0,   0.1,
4243         -1.0,    0.0,   0.1,
4244          0.0,    0.0,   0.1
4245     };
4246     float quad2[] = {
4247          0.0,   -1.0,   0.1,
4248          1.0,   -1.0,   0.1,
4249          0.0,    0.0,   0.1,
4250          1.0,    0.0,   0.1
4251     };
4252     float quad3[] = {
4253          0.0,    0.0,   0.1,
4254          1.0,    0.0,   0.1,
4255          0.0,    1.0,   0.1,
4256          1.0,    1.0,   0.1
4257     };
4258     float quad4[] = {
4259         -1.0,    0.0,   0.1,
4260          0.0,    0.0,   0.1,
4261         -1.0,    1.0,   0.1,
4262          0.0,    1.0,   0.1
4263     };
4264     float test_data_c1[4] = {  1.25, -0.50, -1.50, 1.0};
4265     float test_data_c2[4] = { -0.50,  1.25,  2.00, 1.0};
4266
4267     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
4268     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
4269
4270     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_11, &shader_11);
4271     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4272     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_11_2, &shader_11_2);
4273     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
4274     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_20, &shader_20);
4275     if(FAILED(hr)) shader_20 = NULL;
4276     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code_20_2, &shader_20_2);
4277     if(FAILED(hr)) shader_20_2 = NULL;
4278     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
4279     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4280
4281     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, test_data_c1, 1);
4282     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned %s\n", DXGetErrorString9(hr));
4283     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 2, test_data_c2, 1);
4284     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShaderConstantF returned %s\n", DXGetErrorString9(hr));
4285     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
4286     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4287
4288     hr = IDirect3DDevice9_BeginScene(device);
4289     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
4290     if(SUCCEEDED(hr))
4291     {
4292         hr = IDirect3DDevice9_SetVertexShader(device, shader_11);
4293         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4294         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 3 * sizeof(float));
4295         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4296
4297         hr = IDirect3DDevice9_SetVertexShader(device, shader_11_2);
4298         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4299         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
4300         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4301
4302         if(shader_20) {
4303             hr = IDirect3DDevice9_SetVertexShader(device, shader_20);
4304             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4305             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 3 * sizeof(float));
4306             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4307         }
4308
4309         if(shader_20_2) {
4310             hr = IDirect3DDevice9_SetVertexShader(device, shader_20_2);
4311             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4312             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 3 * sizeof(float));
4313             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4314         }
4315
4316         hr = IDirect3DDevice9_EndScene(device);
4317         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
4318     }
4319     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4320     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4321
4322     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
4323     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4324     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
4325     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
4326
4327     color = getPixelColor(device, 160, 360);
4328     ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
4329        "quad 1 has color %08x, expected 0x00bfbf80\n", color);
4330     color = getPixelColor(device, 480, 360);
4331     ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
4332        "quad 2 has color %08x, expected 0x00bfbf80\n", color);
4333     if(shader_20) {
4334         color = getPixelColor(device, 160, 120);
4335         ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
4336            "quad 3 has color %08x, expected 0x00bfbf80\n", color);
4337     }
4338     if(shader_20_2) {
4339         color = getPixelColor(device, 480, 120);
4340         ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
4341            "quad 4 has color %08x, expected 0x00bfbf80\n", color);
4342     }
4343
4344     IDirect3DVertexDeclaration9_Release(decl);
4345     if(shader_20_2) IDirect3DVertexShader9_Release(shader_20_2);
4346     if(shader_20) IDirect3DVertexShader9_Release(shader_20);
4347     IDirect3DVertexShader9_Release(shader_11_2);
4348     IDirect3DVertexShader9_Release(shader_11);
4349 }
4350
4351 static void constant_clamp_ps_test(IDirect3DDevice9 *device)
4352 {
4353     IDirect3DPixelShader9 *shader_11, *shader_12, *shader_14, *shader_20;
4354     HRESULT hr;
4355     DWORD color;
4356     DWORD shader_code_11[] =  {
4357         0xffff0101,                                         /* ps_1_1           */
4358         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4359         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
4360         0x0000ffff                                          /* end              */
4361     };
4362     DWORD shader_code_12[] =  {
4363         0xffff0102,                                         /* ps_1_2           */
4364         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4365         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
4366         0x0000ffff                                          /* end              */
4367     };
4368     /* Skip 1.3 shaders because we have only 4 quads(ok, could make them smaller if needed).
4369      * 1.2 and 1.4 shaders behave the same, so it's unlikely that 1.3 shaders are different.
4370      * During development of this test, 1.3 shaders were verified too
4371      */
4372     DWORD shader_code_14[] =  {
4373         0xffff0104,                                         /* ps_1_4           */
4374         /* Try to make one constant local. It gets clamped too, although the binary contains
4375          * the bigger numbers
4376          */
4377         0x00000051, 0xa00f0002, 0xbf000000, 0x3fa00000, 0x40000000, 0x3f800000, /* def c2, -0.5, 1.25, 2, 1 */
4378         0x00000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4379         0x00000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
4380         0x0000ffff                                          /* end              */
4381     };
4382     DWORD shader_code_20[] =  {
4383         0xffff0200,                                         /* ps_2_0           */
4384         0x02000001, 0x800f0001, 0xa0e40001,                 /* mov r1, c1       */
4385         0x03000002, 0x800f0000, 0x80e40001, 0xa0e40002,     /* add r0, r1, c2   */
4386         0x02000001, 0x800f0800, 0x80e40000,                 /* mov oC0, r0      */
4387         0x0000ffff                                          /* end              */
4388     };
4389     float quad1[] = {
4390         -1.0,   -1.0,   0.1,
4391          0.0,   -1.0,   0.1,
4392         -1.0,    0.0,   0.1,
4393          0.0,    0.0,   0.1
4394     };
4395     float quad2[] = {
4396          0.0,   -1.0,   0.1,
4397          1.0,   -1.0,   0.1,
4398          0.0,    0.0,   0.1,
4399          1.0,    0.0,   0.1
4400     };
4401     float quad3[] = {
4402          0.0,    0.0,   0.1,
4403          1.0,    0.0,   0.1,
4404          0.0,    1.0,   0.1,
4405          1.0,    1.0,   0.1
4406     };
4407     float quad4[] = {
4408         -1.0,    0.0,   0.1,
4409          0.0,    0.0,   0.1,
4410         -1.0,    1.0,   0.1,
4411          0.0,    1.0,   0.1
4412     };
4413     float test_data_c1[4] = {  1.25, -0.50, -1.50, 1.0};
4414     float test_data_c2[4] = { -0.50,  1.25,  2.00, 1.0};
4415
4416     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
4417     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
4418
4419     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader_11);
4420     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4421     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12, &shader_12);
4422     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4423     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14, &shader_14);
4424     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4425     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_20, &shader_20);
4426     if(FAILED(hr)) shader_20 = NULL;
4427
4428     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1, 1);
4429     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
4430     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2, 1);
4431     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
4432     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4433     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
4434
4435     hr = IDirect3DDevice9_BeginScene(device);
4436     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
4437     if(SUCCEEDED(hr))
4438     {
4439         hr = IDirect3DDevice9_SetPixelShader(device, shader_11);
4440         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4441         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 3 * sizeof(float));
4442         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4443
4444         hr = IDirect3DDevice9_SetPixelShader(device, shader_12);
4445         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4446         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
4447         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4448
4449         hr = IDirect3DDevice9_SetPixelShader(device, shader_14);
4450         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4451         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 3 * sizeof(float));
4452         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4453
4454         if(shader_20) {
4455             hr = IDirect3DDevice9_SetPixelShader(device, shader_20);
4456             ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4457             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 3 * sizeof(float));
4458             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4459         }
4460
4461         hr = IDirect3DDevice9_EndScene(device);
4462         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
4463     }
4464     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4465     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4466
4467     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4468     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4469
4470     color = getPixelColor(device, 160, 360);
4471     ok(color == 0x00808000 || color == 0x007f7f00 || color == 0x00818100,
4472        "quad 1 has color %08x, expected 0x00808000\n", color);
4473     color = getPixelColor(device, 480, 360);
4474     ok(color == 0x00808000 || color == 0x007f7f00 || color == 0x00818100,
4475        "quad 2 has color %08x, expected 0x00808000\n", color);
4476     color = getPixelColor(device, 480, 120);
4477     ok(color == 0x00808000 || color == 0x007f7f00 || color == 0x00818100,
4478        "quad 3 has color %08x, expected 0x00808000\n", color);
4479     if(shader_20) {
4480         color = getPixelColor(device, 160, 120);
4481         ok(color == 0x00bfbf80 || color == 0x00bfbf7f || color == 0x00bfbf81,
4482            "quad 4 has color %08x, expected 0x00bfbf80\n", color);
4483     }
4484
4485     if(shader_20) IDirect3DPixelShader9_Release(shader_20);
4486     IDirect3DPixelShader9_Release(shader_14);
4487     IDirect3DPixelShader9_Release(shader_12);
4488     IDirect3DPixelShader9_Release(shader_11);
4489 }
4490
4491 static void dp2add_ps_test(IDirect3DDevice9 *device)
4492 {
4493     IDirect3DPixelShader9 *shader_dp2add = NULL;
4494     IDirect3DPixelShader9 *shader_dp2add_sat = NULL;
4495     HRESULT hr;
4496     DWORD color;
4497
4498     /* DP2ADD is defined as:  (src0.r * src1.r) + (src0.g * src1.g) + src2.
4499      * One D3D restriction of all shader instructions except SINCOS is that no more than 2
4500      * source tokens can be constants.  So, for this exercise, we move contents of c0 to
4501      * r0 first.
4502      * The result here for the r,g,b components should be roughly 0.5:
4503      *   (0.5 * 0.5) + (0.5 * 0.5) + 0.0 = 0.5 */
4504     static const DWORD shader_code_dp2add[] =  {
4505         0xffff0200,                                                             /* ps_2_0                       */
4506         0x05000051, 0xa00f0000, 0x3f000000, 0x3f000000, 0x3f800000, 0x00000000, /* def c0, 0.5, 0.5, 1.0, 0     */
4507
4508         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                   */
4509         0x0400005a, 0x80070000, 0x80000000, 0x80000000, 0x80ff0000,             /* dp2add r0.rgb, r0, r0, r0.a  */
4510
4511         0x02000001, 0x80080000, 0xa0aa0000,                                     /* mov r0.a, c0.b               */
4512         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
4513         0x0000ffff                                                              /* end                          */
4514     };
4515
4516     /* Test the _sat modifier, too.  Result here should be:
4517      *   DP2: (-0.5 * -0.5) + (-0.5 * -0.5) + 2.0 = 2.5
4518      *      _SAT: ==> 1.0
4519      *   ADD: (1.0 + -0.5) = 0.5
4520      */
4521     static const DWORD shader_code_dp2add_sat[] =  {
4522         0xffff0200,                                                             /* ps_2_0                           */
4523         0x05000051, 0xa00f0000, 0xbf000000, 0xbf000000, 0x3f800000, 0x40000000, /* def c0, -0.5, -0.5, 1.0, 2.0     */
4524
4525         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                       */
4526         0x0400005a, 0x80170000, 0x80000000, 0x80000000, 0x80ff0000,             /* dp2add_sat r0.rgb, r0, r0, r0.a  */
4527         0x03000002, 0x80070000, 0x80e40000, 0xa0000000,                         /* add r0.rgb, r0, c0.r             */
4528
4529         0x02000001, 0x80080000, 0xa0aa0000,                                     /* mov r0.a, c0.b                   */
4530         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                      */
4531         0x0000ffff                                                              /* end                              */
4532     };
4533
4534     const float quad[] = {
4535         -1.0,   -1.0,   0.1,
4536          1.0,   -1.0,   0.1,
4537         -1.0,    1.0,   0.1,
4538          1.0,    1.0,   0.1
4539     };
4540
4541
4542     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
4543     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
4544
4545     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_dp2add, &shader_dp2add);
4546     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4547
4548     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_dp2add_sat, &shader_dp2add_sat);
4549     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4550
4551     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4552     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
4553
4554     if (shader_dp2add) {
4555
4556         hr = IDirect3DDevice9_SetPixelShader(device, shader_dp2add);
4557         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4558
4559         hr = IDirect3DDevice9_BeginScene(device);
4560         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
4561         if(SUCCEEDED(hr))
4562         {
4563             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
4564             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4565
4566             hr = IDirect3DDevice9_EndScene(device);
4567             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
4568         }
4569         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4570         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4571
4572         color = getPixelColor(device, 360, 240);
4573         ok(color == 0x007f7f7f || color == 0x00808080, "dp2add pixel has color %08x, expected ~0x007f7f7f\n", color);
4574
4575         IDirect3DPixelShader9_Release(shader_dp2add);
4576     } else {
4577         skip("dp2add shader creation failed\n");
4578     }
4579
4580     if (shader_dp2add_sat) {
4581
4582         hr = IDirect3DDevice9_SetPixelShader(device, shader_dp2add_sat);
4583         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(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_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
4590             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4591
4592             hr = IDirect3DDevice9_EndScene(device);
4593             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
4594         }
4595         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4596         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4597
4598         color = getPixelColor(device, 360, 240);
4599         ok(color == 0x007f7f7f || color == 0x00808080, "dp2add pixel has color %08x, expected ~0x007f7f7f\n", color);
4600
4601         IDirect3DPixelShader9_Release(shader_dp2add_sat);
4602     } else {
4603         skip("dp2add shader creation failed\n");
4604     }
4605
4606     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4607     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4608 }
4609
4610 static void cnd_test(IDirect3DDevice9 *device)
4611 {
4612     IDirect3DPixelShader9 *shader_11, *shader_12, *shader_13, *shader_14;
4613     IDirect3DPixelShader9 *shader_11_coissue, *shader_12_coissue, *shader_13_coissue, *shader_14_coissue;
4614     HRESULT hr;
4615     DWORD color;
4616     /* ps 1.x shaders are rather picky with writemasks and source swizzles. The dp3 is
4617      * used to copy r0.r to all components of r1, then copy r1.a to c0.a. Essentially it
4618      * does a mov r0.a, r0.r, which isn't allowed as-is in 1.x pixel shaders.
4619      */
4620     DWORD shader_code_11[] =  {
4621         0xffff0101,                                                                 /* ps_1_1               */
4622         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
4623         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
4624         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, ???(t0)      */
4625         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3 r1, r0, c0       */
4626         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
4627         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
4628         0x0000ffff                                                                  /* end                  */
4629     };
4630     DWORD shader_code_12[] =  {
4631         0xffff0102,                                                                 /* ps_1_2               */
4632         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
4633         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
4634         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, t0           */
4635         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3 r1, r0, c0       */
4636         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
4637         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
4638         0x0000ffff                                                                  /* end                  */
4639     };
4640     DWORD shader_code_13[] =  {
4641         0xffff0103,                                                                 /* ps_1_3               */
4642         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000,     /* def c0, 1, 0, 0, 0   */
4643         0x00000040, 0xb00f0000,                                                     /* texcoord t0          */
4644         0x00000001, 0x800f0000, 0xb0e40000,                                         /* mov r0, t0           */
4645         0x00000008, 0x800f0001, 0x80e40000, 0xa0e40000,                             /* dp3, r1, r0, c0      */
4646         0x00000001, 0x80080000, 0x80ff0001,                                         /* mov r0.a, r1.a       */
4647         0x00000050, 0x800f0000, 0x80ff0000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0.a, c1, c2 */
4648         0x0000ffff                                                                  /* end                  */
4649     };
4650     DWORD shader_code_14[] =  {
4651         0xffff0104,                                                                 /* ps_1_3               */
4652         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000,     /* def c0, 0, 0, 0, 1   */
4653         0x00000040, 0x80070000, 0xb0e40000,                                         /* texcrd r0, t0        */
4654         0x00000001, 0x80080000, 0xa0ff0000,                                         /* mov r0.a, c0.a       */
4655         0x00000050, 0x800f0000, 0x80e40000, 0xa0e40001, 0xa0e40002,                 /* cnd r0, r0, c1, c2   */
4656         0x0000ffff                                                                  /* end                  */
4657     };
4658
4659     /* Special fun: The coissue flag on cnd: Apparently cnd always selects the 2nd source,
4660      * as if the src0 comparison against 0.5 always evaluates to true. The coissue flag isn't
4661      * set by the compiler, it was added manually after compilation. It isn't always allowed,
4662      * only if there's a mov r0.a, XXXX, and the cnd instruction writes to r0.xyz, otherwise
4663      * native CreatePixelShader returns an error.
4664      *
4665      * The shader attempts to test the range [-1;1] against coissued cnd, which is a bit tricky.
4666      * The input from t0 is [0;1]. 0.5 is substracted, then we have to multiply with 2. Since
4667      * constants are clamped to [-1;1], a 2.0 is constructed by adding c0.r(=1.0) to c0.r into r1.r,
4668      * then r1(2.0, 0.0, 0.0, 0.0) is passed to dp3(explained above).
4669      */
4670     DWORD shader_code_11_coissue[] =  {
4671         0xffff0101,                                                             /* ps_1_1                   */
4672         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
4673         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
4674         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
4675         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
4676         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
4677         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
4678         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
4679         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
4680         /* 0x40000000 = D3DSI_COISSUE */
4681         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
4682         0x0000ffff                                                              /* end                      */
4683     };
4684     DWORD shader_code_12_coissue[] =  {
4685         0xffff0102,                                                             /* ps_1_2                   */
4686         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
4687         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
4688         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
4689         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
4690         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
4691         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
4692         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
4693         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
4694         /* 0x40000000 = D3DSI_COISSUE */
4695         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
4696         0x0000ffff                                                              /* end                      */
4697     };
4698     DWORD shader_code_13_coissue[] =  {
4699         0xffff0103,                                                             /* ps_1_3                   */
4700         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1, 0, 0, 0       */
4701         0x00000051, 0xa00f0003, 0x3f000000, 0x3f000000, 0x3f000000, 0x00000000, /* def c3, 0.5, 0.5, 0.5, 0 */
4702         0x00000040, 0xb00f0000,                                                 /* texcoord t0              */
4703         0x00000001, 0x800f0000, 0xb0e40000,                                     /* mov r0, t0               */
4704         0x00000003, 0x800f0000, 0x80e40000, 0xa0e40003,                         /* sub r0, r0, c3           */
4705         0x00000002, 0x800f0001, 0xa0e40000, 0xa0e40000,                         /* add r1, c0, c0           */
4706         0x00000008, 0x800f0001, 0x80e40000, 0x80e40001,                         /* dp3, r1, r0, r1          */
4707         0x00000001, 0x80080000, 0x80ff0001,                                     /* mov r0.a, r1.a           */
4708         /* 0x40000000 = D3DSI_COISSUE */
4709         0x40000050, 0x80070000, 0x80ff0000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0.a, c1, c2 */
4710         0x0000ffff                                                              /* end                      */
4711     };
4712     /* ps_1_4 does not have a different cnd behavior, just pass the [0;1] texcrd result to cnd, it will
4713      * compare against 0.5
4714      */
4715     DWORD shader_code_14_coissue[] =  {
4716         0xffff0104,                                                             /* ps_1_4                   */
4717         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0, 0, 0, 1       */
4718         0x00000040, 0x80070000, 0xb0e40000,                                     /* texcrd r0, t0            */
4719         0x00000001, 0x80080000, 0xa0ff0000,                                     /* mov r0.a, c0.a           */
4720         /* 0x40000000 = D3DSI_COISSUE */
4721         0x40000050, 0x80070000, 0x80e40000, 0xa0e40001, 0xa0e40002,             /* cnd r0.xyz, r0, c1, c2   */
4722         0x0000ffff                                                              /* end                      */
4723     };
4724     float quad1[] = {
4725         -1.0,   -1.0,   0.1,     0.0,    0.0,    1.0,
4726          0.0,   -1.0,   0.1,     1.0,    0.0,    1.0,
4727         -1.0,    0.0,   0.1,     0.0,    1.0,    0.0,
4728          0.0,    0.0,   0.1,     1.0,    1.0,    0.0
4729     };
4730     float quad2[] = {
4731          0.0,   -1.0,   0.1,     0.0,    0.0,    1.0,
4732          1.0,   -1.0,   0.1,     1.0,    0.0,    1.0,
4733          0.0,    0.0,   0.1,     0.0,    1.0,    0.0,
4734          1.0,    0.0,   0.1,     1.0,    1.0,    0.0
4735     };
4736     float quad3[] = {
4737          0.0,    0.0,   0.1,     0.0,    0.0,    1.0,
4738          1.0,    0.0,   0.1,     1.0,    0.0,    1.0,
4739          0.0,    1.0,   0.1,     0.0,    1.0,    0.0,
4740          1.0,    1.0,   0.1,     1.0,    1.0,    0.0
4741     };
4742     float quad4[] = {
4743         -1.0,    0.0,   0.1,     0.0,    0.0,    1.0,
4744          0.0,    0.0,   0.1,     1.0,    0.0,    1.0,
4745         -1.0,    1.0,   0.1,     0.0,    1.0,    0.0,
4746          0.0,    1.0,   0.1,     1.0,    1.0,    0.0
4747     };
4748     float test_data_c1[4] = {  0.0, 0.0, 0.0, 0.0};
4749     float test_data_c2[4] = {  1.0, 1.0, 1.0, 1.0};
4750     float test_data_c1_coi[4] = {  0.0, 1.0, 0.0, 0.0};
4751     float test_data_c2_coi[4] = {  1.0, 0.0, 1.0, 1.0};
4752
4753     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
4754     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
4755
4756     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader_11);
4757     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4758     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12, &shader_12);
4759     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4760     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_13, &shader_13);
4761     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4762     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14, &shader_14);
4763     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4764     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11_coissue, &shader_11_coissue);
4765     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4766     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_12_coissue, &shader_12_coissue);
4767     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4768     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_13_coissue, &shader_13_coissue);
4769     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4770     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_14_coissue, &shader_14_coissue);
4771     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
4772
4773     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1, 1);
4774     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
4775     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2, 1);
4776     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
4777     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
4778     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
4779
4780     hr = IDirect3DDevice9_BeginScene(device);
4781     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
4782     if(SUCCEEDED(hr))
4783     {
4784         hr = IDirect3DDevice9_SetPixelShader(device, shader_11);
4785         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4786         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
4787         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4788
4789         hr = IDirect3DDevice9_SetPixelShader(device, shader_12);
4790         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4791         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
4792         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4793
4794         hr = IDirect3DDevice9_SetPixelShader(device, shader_13);
4795         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4796         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 6 * sizeof(float));
4797         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4798
4799         hr = IDirect3DDevice9_SetPixelShader(device, shader_14);
4800         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4801         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
4802         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4803
4804         hr = IDirect3DDevice9_EndScene(device);
4805         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
4806     }
4807     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4808     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4809
4810     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
4811     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
4812
4813     /* This is the 1.4 test. Each component(r, g, b) is tested separately against 0.5 */
4814     color = getPixelColor(device, 158, 118);
4815     ok(color == 0x00ff00ff, "pixel 158, 118 has color %08x, expected 0x00ff00ff\n", color);
4816     color = getPixelColor(device, 162, 118);
4817     ok(color == 0x000000ff, "pixel 162, 118 has color %08x, expected 0x000000ff\n", color);
4818     color = getPixelColor(device, 158, 122);
4819     ok(color == 0x00ffffff, "pixel 162, 122 has color %08x, expected 0x00ffffff\n", color);
4820     color = getPixelColor(device, 162, 122);
4821     ok(color == 0x0000ffff, "pixel 162, 122 has color %08x, expected 0x0000ffff\n", color);
4822
4823     /* 1.1 shader. All 3 components get set, based on the .w comparison */
4824     color = getPixelColor(device, 158, 358);
4825     ok(color == 0x00ffffff, "pixel 158, 358 has color %08x, expected 0x00ffffff\n", color);
4826     color = getPixelColor(device, 162, 358);
4827     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4828         "pixel 162, 358 has color %08x, expected 0x00000000\n", color);
4829     color = getPixelColor(device, 158, 362);
4830     ok(color == 0x00ffffff, "pixel 158, 362 has color %08x, expected 0x00ffffff\n", color);
4831     color = getPixelColor(device, 162, 362);
4832     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4833         "pixel 162, 362 has color %08x, expected 0x00000000\n", color);
4834
4835     /* 1.2 shader */
4836     color = getPixelColor(device, 478, 358);
4837     ok(color == 0x00ffffff, "pixel 478, 358 has color %08x, expected 0x00ffffff\n", color);
4838     color = getPixelColor(device, 482, 358);
4839     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4840         "pixel 482, 358 has color %08x, expected 0x00000000\n", color);
4841     color = getPixelColor(device, 478, 362);
4842     ok(color == 0x00ffffff, "pixel 478, 362 has color %08x, expected 0x00ffffff\n", color);
4843     color = getPixelColor(device, 482, 362);
4844     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4845         "pixel 482, 362 has color %08x, expected 0x00000000\n", color);
4846
4847     /* 1.3 shader */
4848     color = getPixelColor(device, 478, 118);
4849     ok(color == 0x00ffffff, "pixel 478, 118 has color %08x, expected 0x00ffffff\n", color);
4850     color = getPixelColor(device, 482, 118);
4851     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4852         "pixel 482, 118 has color %08x, expected 0x00000000\n", color);
4853     color = getPixelColor(device, 478, 122);
4854     ok(color == 0x00ffffff, "pixel 478, 122 has color %08x, expected 0x00ffffff\n", color);
4855     color = getPixelColor(device, 482, 122);
4856     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) <= 0x01) && ((color & 0x000000ff) <= 0x01),
4857         "pixel 482, 122 has color %08x, expected 0x00000000\n", color);
4858
4859     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
4860     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
4861     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 1, test_data_c1_coi, 1);
4862     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
4863     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 2, test_data_c2_coi, 1);
4864     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
4865
4866     hr = IDirect3DDevice9_BeginScene(device);
4867     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
4868     if(SUCCEEDED(hr))
4869     {
4870         hr = IDirect3DDevice9_SetPixelShader(device, shader_11_coissue);
4871         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4872         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
4873         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4874
4875         hr = IDirect3DDevice9_SetPixelShader(device, shader_12_coissue);
4876         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4877         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
4878         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4879
4880         hr = IDirect3DDevice9_SetPixelShader(device, shader_13_coissue);
4881         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4882         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 6 * sizeof(float));
4883         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4884
4885         hr = IDirect3DDevice9_SetPixelShader(device, shader_14_coissue);
4886         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
4887         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
4888         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
4889
4890         hr = IDirect3DDevice9_EndScene(device);
4891         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
4892     }
4893     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
4894     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
4895
4896     /* This is the 1.4 test. The coissue doesn't change the behavior here, but keep in mind
4897      * that we swapped the values in c1 and c2 to make the other tests return some color
4898      */
4899     color = getPixelColor(device, 158, 118);
4900     ok(color == 0x00ffffff, "pixel 158, 118 has color %08x, expected 0x00ffffff\n", color);
4901     color = getPixelColor(device, 162, 118);
4902     ok(color == 0x0000ffff, "pixel 162, 118 has color %08x, expected 0x0000ffff\n", color);
4903     color = getPixelColor(device, 158, 122);
4904     ok(color == 0x00ff00ff, "pixel 162, 122 has color %08x, expected 0x00ff00ff\n", color);
4905     color = getPixelColor(device, 162, 122);
4906     ok(color == 0x000000ff, "pixel 162, 122 has color %08x, expected 0x000000ff\n", color);
4907
4908     /* 1.1 shader. coissue flag changed the semantic of cnd, c1 is always selected */
4909     color = getPixelColor(device, 158, 358);
4910     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4911         "pixel 158, 358 has color %08x, expected 0x0000ff00\n", color);
4912     color = getPixelColor(device, 162, 358);
4913     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4914         "pixel 162, 358 has color %08x, expected 0x0000ff00\n", color);
4915     color = getPixelColor(device, 158, 362);
4916     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4917         "pixel 158, 362 has color %08x, expected 0x0000ff00\n", color);
4918     color = getPixelColor(device, 162, 362);
4919     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4920         "pixel 162, 362 has color %08x, expected 0x0000ff00\n", color);
4921
4922     /* 1.2 shader */
4923     color = getPixelColor(device, 478, 358);
4924     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4925         "pixel 478, 358 has color %08x, expected 0x0000ff00\n", color);
4926     color = getPixelColor(device, 482, 358);
4927     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4928         "pixel 482, 358 has color %08x, expected 0x0000ff00\n", color);
4929     color = getPixelColor(device, 478, 362);
4930     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4931         "pixel 478, 362 has color %08x, expected 0x0000ff00\n", color);
4932     color = getPixelColor(device, 482, 362);
4933     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4934         "pixel 482, 362 has color %08x, expected 0x0000ff00\n", color);
4935
4936     /* 1.3 shader */
4937     color = getPixelColor(device, 478, 118);
4938     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4939         "pixel 478, 118 has color %08x, expected 0x0000ff00\n", color);
4940     color = getPixelColor(device, 482, 118);
4941     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4942         "pixel 482, 118 has color %08x, expected 0x0000ff00\n", color);
4943     color = getPixelColor(device, 478, 122);
4944     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4945         "pixel 478, 122 has color %08x, expected 0x0000ff00\n", color);
4946     color = getPixelColor(device, 482, 122);
4947     ok( (((color & 0x00ff0000) >> 16) <= 0x01) && (((color & 0x0000ff00) >> 8) == 0xff) && ((color & 0x000000ff) <= 0x01),
4948         "pixel 482, 122 has color %08x, expected 0x0000ff00\n", color);
4949
4950     IDirect3DPixelShader9_Release(shader_14_coissue);
4951     IDirect3DPixelShader9_Release(shader_13_coissue);
4952     IDirect3DPixelShader9_Release(shader_12_coissue);
4953     IDirect3DPixelShader9_Release(shader_11_coissue);
4954     IDirect3DPixelShader9_Release(shader_14);
4955     IDirect3DPixelShader9_Release(shader_13);
4956     IDirect3DPixelShader9_Release(shader_12);
4957     IDirect3DPixelShader9_Release(shader_11);
4958 }
4959
4960 static void nested_loop_test(IDirect3DDevice9 *device) {
4961     const DWORD shader_code[] = {
4962         0xffff0300,                                                             /* ps_3_0               */
4963         0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 0, 0, 0, 1   */
4964         0x05000051, 0xa00f0001, 0x3d000000, 0x00000000, 0x00000000, 0x00000000, /* def c1, 1/32, 0, 0, 0*/
4965         0x05000030, 0xf00f0000, 0x00000004, 0x00000000, 0x00000002, 0x00000000, /* defi i0, 4, 0, 2, 0  */
4966         0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0           */
4967         0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0          */
4968         0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0          */
4969         0x03000002, 0x800f0000, 0x80e40000, 0xa0e40001,                         /* add r0, r0, c1       */
4970         0x0000001d,                                                             /* endloop              */
4971         0x0000001d,                                                             /* endloop              */
4972         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0          */
4973         0x0000ffff                                                              /* end                  */
4974     };
4975     IDirect3DPixelShader9 *shader;
4976     HRESULT hr;
4977     DWORD color;
4978     const float quad[] = {
4979         -1.0,   -1.0,   0.1,
4980          1.0,   -1.0,   0.1,
4981         -1.0,    1.0,   0.1,
4982          1.0,    1.0,   0.1
4983     };
4984
4985     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
4986     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed with %s\n", DXGetErrorString9(hr));
4987     hr = IDirect3DDevice9_SetPixelShader(device, shader);
4988     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with %s\n", DXGetErrorString9(hr));
4989     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
4990     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
4991     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x0000ff00, 0.0, 0);
4992     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
4993
4994     hr = IDirect3DDevice9_BeginScene(device);
4995     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
4996     if(SUCCEEDED(hr))
4997     {
4998         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
4999         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5000         hr = IDirect3DDevice9_EndScene(device);
5001         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
5002     }
5003     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5004     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
5005
5006     color = getPixelColor(device, 360, 240);
5007     ok(color == 0x007f0000 || color == 0x00800000 || color == 0x00810000,
5008        "Nested loop test returned color 0x%08x, expected 0x00800000\n", color);
5009
5010     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5011     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed with %s\n", DXGetErrorString9(hr));
5012     IDirect3DPixelShader9_Release(shader);
5013 }
5014
5015 struct varying_test_struct
5016 {
5017     const DWORD             *shader_code;
5018     IDirect3DPixelShader9   *shader;
5019     DWORD                   color, color_rhw;
5020     const char              *name;
5021     BOOL                    todo, todo_rhw;
5022 };
5023
5024 struct hugeVertex
5025 {
5026     float pos_x,        pos_y,      pos_z,      rhw;
5027     float weight_1,     weight_2,   weight_3,   weight_4;
5028     float index_1,      index_2,    index_3,    index_4;
5029     float normal_1,     normal_2,   normal_3,   normal_4;
5030     float fog_1,        fog_2,      fog_3,      fog_4;
5031     float texcoord_1,   texcoord_2, texcoord_3, texcoord_4;
5032     float tangent_1,    tangent_2,  tangent_3,  tangent_4;
5033     float binormal_1,   binormal_2, binormal_3, binormal_4;
5034     float depth_1,      depth_2,    depth_3,    depth_4;
5035     DWORD diffuse, specular;
5036 };
5037
5038 static void fixed_function_varying_test(IDirect3DDevice9 *device) {
5039     /* dcl_position: fails to compile */
5040     const DWORD blendweight_code[] = {
5041         0xffff0300,                             /* ps_3_0                   */
5042         0x0200001f, 0x80000001, 0x900f0000,     /* dcl_blendweight, v0      */
5043         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5044         0x0000ffff                              /* end                      */
5045     };
5046     const DWORD blendindices_code[] = {
5047         0xffff0300,                             /* ps_3_0                   */
5048         0x0200001f, 0x80000002, 0x900f0000,     /* dcl_blendindices, v0     */
5049         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5050         0x0000ffff                              /* end                      */
5051     };
5052     const DWORD normal_code[] = {
5053         0xffff0300,                             /* ps_3_0                   */
5054         0x0200001f, 0x80000003, 0x900f0000,     /* dcl_normal, v0           */
5055         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5056         0x0000ffff                              /* end                      */
5057     };
5058     /* psize: fails? */
5059     const DWORD texcoord0_code[] = {
5060         0xffff0300,                             /* ps_3_0                   */
5061         0x0200001f, 0x80000005, 0x900f0000,     /* dcl_texcoord0, v0        */
5062         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5063         0x0000ffff                              /* end                      */
5064     };
5065     const DWORD tangent_code[] = {
5066         0xffff0300,                             /* ps_3_0                   */
5067         0x0200001f, 0x80000006, 0x900f0000,     /* dcl_tangent, v0          */
5068         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5069         0x0000ffff                              /* end                      */
5070     };
5071     const DWORD binormal_code[] = {
5072         0xffff0300,                             /* ps_3_0                   */
5073         0x0200001f, 0x80000007, 0x900f0000,     /* dcl_binormal, v0         */
5074         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5075         0x0000ffff                              /* end                      */
5076     };
5077     /* tessfactor: fails */
5078     /* positiont: fails */
5079     const DWORD color_code[] = {
5080         0xffff0300,                             /* ps_3_0                   */
5081         0x0200001f, 0x8000000a, 0x900f0000,     /* dcl_color0, v0           */
5082         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5083         0x0000ffff                              /* end                      */
5084     };
5085     const DWORD fog_code[] = {
5086         0xffff0300,                             /* ps_3_0                   */
5087         0x0200001f, 0x8000000b, 0x900f0000,     /* dcl_fog, v0              */
5088         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5089         0x0000ffff                              /* end                      */
5090     };
5091     const DWORD depth_code[] = {
5092         0xffff0300,                             /* ps_3_0                   */
5093         0x0200001f, 0x8000000c, 0x900f0000,     /* dcl_depth, v0            */
5094         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5095         0x0000ffff                              /* end                      */
5096     };
5097     const DWORD specular_code[] = {
5098         0xffff0300,                             /* ps_3_0                   */
5099         0x0200001f, 0x8001000a, 0x900f0000,     /* dcl_color1, v0           */
5100         0x02000001, 0x800f0800, 0x90e40000,     /* mov oC0, v0              */
5101         0x0000ffff                              /* end                      */
5102     };
5103     /* sample: fails */
5104
5105     struct varying_test_struct tests[] = {
5106        {blendweight_code,       NULL,       0x00000000,     0x00191919,     "blendweight"   ,   FALSE,  TRUE  },
5107        {blendindices_code,      NULL,       0x00000000,     0x00000000,     "blendindices"  ,   FALSE,  FALSE },
5108        {normal_code,            NULL,       0x00000000,     0x004c4c4c,     "normal"        ,   FALSE,  TRUE  },
5109        /* Why does dx not forward the texcoord? */
5110        {texcoord0_code,         NULL,       0x00000000,     0x00808c8c,     "texcoord0"     ,   FALSE,  FALSE },
5111        {tangent_code,           NULL,       0x00000000,     0x00999999,     "tangent"       ,   FALSE,  TRUE  },
5112        {binormal_code,          NULL,       0x00000000,     0x00b2b2b2,     "binormal"      ,   FALSE,  TRUE  },
5113        {color_code,             NULL,       0x00e6e6e6,     0x00e6e6e6,     "color"         ,   FALSE,  FALSE },
5114        {fog_code,               NULL,       0x00000000,     0x00666666,     "fog"           ,   FALSE,  TRUE  },
5115        {depth_code,             NULL,       0x00000000,     0x00cccccc,     "depth"         ,   FALSE,  TRUE  },
5116        {specular_code,          NULL,       0x004488ff,     0x004488ff,     "specular"      ,   FALSE,  FALSE }
5117     };
5118     /* Declare a monster vertex type :-) */
5119     static const D3DVERTEXELEMENT9 decl_elements[] = {
5120         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
5121         {0,  16,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT,    0},
5122         {0,  32,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES,   0},
5123         {0,  48,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,         0},
5124         {0,  64,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_FOG,            0},
5125         {0,  80,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
5126         {0,  96,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT,        0},
5127         {0, 112,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL,       0},
5128         {0, 128,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_DEPTH,          0},
5129         {0, 144,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
5130         {0, 148,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          1},
5131         D3DDECL_END()
5132     };
5133     static const D3DVERTEXELEMENT9 decl_elements2[] = {
5134         {0,   0,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT,      0},
5135         {0,  16,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT,    0},
5136         {0,  32,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES,   0},
5137         {0,  48,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,         0},
5138         {0,  64,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_FOG,            0},
5139         {0,  80,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
5140         {0,  96,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TANGENT,        0},
5141         {0, 112,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BINORMAL,       0},
5142         {0, 128,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_DEPTH,          0},
5143         {0, 144,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
5144         {0, 148,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          1},
5145         D3DDECL_END()
5146     };
5147     struct hugeVertex data[4] = {
5148         {
5149             -1.0,   -1.0,   0.1,    1.0,
5150              0.1,    0.1,   0.1,    0.1,
5151              0.2,    0.2,   0.2,    0.2,
5152              0.3,    0.3,   0.3,    0.3,
5153              0.4,    0.4,   0.4,    0.4,
5154              0.50,   0.55,  0.55,   0.55,
5155              0.6,    0.6,   0.6,    0.7,
5156              0.7,    0.7,   0.7,    0.6,
5157              0.8,    0.8,   0.8,    0.8,
5158              0xe6e6e6e6, /* 0.9 * 256 */
5159              0x224488ff  /* Nothing special */
5160         },
5161         {
5162              1.0,   -1.0,   0.1,    1.0,
5163              0.1,    0.1,   0.1,    0.1,
5164              0.2,    0.2,   0.2,    0.2,
5165              0.3,    0.3,   0.3,    0.3,
5166              0.4,    0.4,   0.4,    0.4,
5167              0.50,   0.55,  0.55,   0.55,
5168              0.6,    0.6,   0.6,    0.7,
5169              0.7,    0.7,   0.7,    0.6,
5170              0.8,    0.8,   0.8,    0.8,
5171              0xe6e6e6e6, /* 0.9 * 256 */
5172              0x224488ff /* Nothing special */
5173         },
5174         {
5175             -1.0,    1.0,   0.1,    1.0,
5176              0.1,    0.1,   0.1,    0.1,
5177              0.2,    0.2,   0.2,    0.2,
5178              0.3,    0.3,   0.3,    0.3,
5179              0.4,    0.4,   0.4,    0.4,
5180              0.50,   0.55,  0.55,   0.55,
5181              0.6,    0.6,   0.6,    0.7,
5182              0.7,    0.7,   0.7,    0.6,
5183              0.8,    0.8,   0.8,    0.8,
5184              0xe6e6e6e6, /* 0.9 * 256 */
5185              0x224488ff /* Nothing special */
5186         },
5187         {
5188              1.0,    1.0,   0.1,    1.0,
5189              0.1,    0.1,   0.1,    0.1,
5190              0.2,    0.2,   0.2,    0.2,
5191              0.3,    0.3,   0.3,    0.3,
5192              0.4,    0.4,   0.4,    0.4,
5193              0.50,   0.55,  0.55,   0.55,
5194              0.6,    0.6,   0.6,    0.7,
5195              0.7,    0.7,   0.7,    0.6,
5196              0.8,    0.8,   0.8,    0.8,
5197              0xe6e6e6e6, /* 0.9 * 256 */
5198              0x224488ff /* Nothing special */
5199         },
5200     };
5201     struct hugeVertex data2[4];
5202     IDirect3DVertexDeclaration9 *decl;
5203     IDirect3DVertexDeclaration9 *decl2;
5204     HRESULT hr;
5205     unsigned int i;
5206     DWORD color, r, g, b, r_e, g_e, b_e;
5207     BOOL drawok;
5208
5209     memcpy(data2, data, sizeof(data2));
5210     data2[0].pos_x = 0;     data2[0].pos_y = 0;
5211     data2[1].pos_x = 640;   data2[1].pos_y = 0;
5212     data2[2].pos_x = 0;     data2[2].pos_y = 480;
5213     data2[3].pos_x = 640;   data2[3].pos_y = 480;
5214
5215     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
5216     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
5217     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements2, &decl2);
5218     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
5219     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
5220     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
5221
5222     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
5223     {
5224         hr = IDirect3DDevice9_CreatePixelShader(device, tests[i].shader_code, &tests[i].shader);
5225         ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed for shader %s, hr = %s\n",
5226            tests[i].name, DXGetErrorString9(hr));
5227     }
5228
5229     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
5230     {
5231         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
5232         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
5233
5234         IDirect3DDevice9_SetPixelShader(device, tests[i].shader);
5235         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
5236
5237         hr = IDirect3DDevice9_BeginScene(device);
5238         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
5239         drawok = FALSE;
5240         if(SUCCEEDED(hr))
5241         {
5242             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, data, sizeof(data[0]));
5243             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed (%08x)\n", hr);
5244             drawok = SUCCEEDED(hr);
5245             hr = IDirect3DDevice9_EndScene(device);
5246             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
5247         }
5248         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5249         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
5250
5251         /* Some drivers reject the combination of ps_3_0 and fixed function vertex processing. Accept
5252          * the failure and do not check the color if it failed
5253          */
5254         if(!drawok) {
5255             continue;
5256         }
5257
5258         color = getPixelColor(device, 360, 240);
5259         r = color & 0x00ff0000 >> 16;
5260         g = color & 0x0000ff00 >>  8;
5261         b = color & 0x000000ff;
5262         r_e = tests[i].color & 0x00ff0000 >> 16;
5263         g_e = tests[i].color & 0x0000ff00 >>  8;
5264         b_e = tests[i].color & 0x000000ff;
5265
5266         if(tests[i].todo) {
5267             todo_wine ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
5268                          "Test %s returned color 0x%08x, expected 0x%08x(todo)\n",
5269                          tests[i].name, color, tests[i].color);
5270         } else {
5271             ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
5272                "Test %s returned color 0x%08x, expected 0x%08x\n",
5273                tests[i].name, color, tests[i].color);
5274         }
5275     }
5276
5277     hr = IDirect3DDevice9_SetVertexDeclaration(device, decl2);
5278     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
5279     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
5280     {
5281         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
5282         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
5283
5284         IDirect3DDevice9_SetPixelShader(device, tests[i].shader);
5285         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
5286
5287         hr = IDirect3DDevice9_BeginScene(device);
5288         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
5289         if(SUCCEEDED(hr))
5290         {
5291             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, data2, sizeof(data2[0]));
5292             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5293             hr = IDirect3DDevice9_EndScene(device);
5294             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
5295         }
5296         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5297         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
5298
5299         color = getPixelColor(device, 360, 240);
5300         r = color & 0x00ff0000 >> 16;
5301         g = color & 0x0000ff00 >>  8;
5302         b = color & 0x000000ff;
5303         r_e = tests[i].color_rhw & 0x00ff0000 >> 16;
5304         g_e = tests[i].color_rhw & 0x0000ff00 >>  8;
5305         b_e = tests[i].color_rhw & 0x000000ff;
5306
5307         if(tests[i].todo_rhw) {
5308             /* This isn't a weekend's job to fix, ignore the problem for now. Needs a replacement
5309              * pipeline
5310              */
5311             todo_wine ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
5312                          "Test %s returned color 0x%08x, expected 0x%08x(todo)\n",
5313                          tests[i].name, color, tests[i].color_rhw);
5314         } else {
5315             ok(abs(r - r_e) <= 1 && abs(g - g_e) <= 1 && abs(b - b_e) <= 1,
5316                "Test %s returned color 0x%08x, expected 0x%08x\n",
5317                tests[i].name, color, tests[i].color_rhw);
5318         }
5319     }
5320
5321     for(i = 0; i < sizeof(tests) / sizeof(tests[0]); i++)
5322     {
5323         IDirect3DPixelShader9_Release(tests[i].shader);
5324     }
5325
5326     IDirect3DVertexDeclaration9_Release(decl2);
5327     IDirect3DVertexDeclaration9_Release(decl);
5328 }
5329
5330 static void vshader_version_varying_test(IDirect3DDevice9 *device) {
5331     static const DWORD ps_code[] = {
5332     0xffff0300,                                                             /* ps_3_0                       */
5333     0x05000030, 0xf00f0000, 0x00000003, 0x00000003, 0x00000001, 0x00000000, /* defi i0, 3, 3, 1, 0          */
5334     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0   */
5335     0x0200001f, 0x8001000a, 0x900f0003,                                     /* dcl_color1 v3                */
5336     0x0200001f, 0x8000000b, 0x900f0004,                                     /* dcl_fog v4                   */
5337     0x0200001f, 0x80030005, 0x900f0005,                                     /* dcl_texcoord3 v5             */
5338     0x0200001f, 0x80000003, 0x900f0006,
5339     0x0200001f, 0x80000006, 0x900f0007,
5340     0x0200001f, 0x80000001, 0x900f0008,
5341     0x0200001f, 0x8000000c, 0x900f0009,
5342
5343     0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                   */
5344     0x0200001b, 0xf0e40800, 0xf0e40000,                                     /* loop aL, i0                  */
5345     0x04000002, 0x800f0000, 0x80e40000, 0x90e42000, 0xf0e40800,             /* add r0, r0, v0[aL]           */
5346     0x0000001d,                                                             /* endloop                      */
5347     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
5348     0x0000ffff                                                              /* end                          */
5349     };
5350     static const DWORD vs_1_code[] = {
5351     0xfffe0101,                                                             /* vs_1_1                       */
5352     0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
5353     0x00000051, 0xa00f0000, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.1, 0.0, 0.0, 0.0   */
5354     0x00000051, 0xa00f0001, 0x00000000, 0x3e4ccccd, 0x00000000, 0x00000000, /* def c1, 0.0, 0.2, 0.0, 0.0   */
5355     0x00000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3ecccccd, 0x00000000, /* def c2, 0.0, 0.0, 0.4, 0.0   */
5356     0x00000051, 0xa00f0003, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 1.0, 1.0, 1.0, 1.0   */
5357     0x00000001, 0xd00f0000, 0xa0e40002,                                     /* mov oD0, c2                  */
5358     0x00000001, 0xd00f0001, 0xa0e40000,                                     /* mov oD1, c0                  */
5359     0x00000001, 0xc00f0001, 0xa0550001,                                     /* mov oFog, c1.g               */
5360     0x00000001, 0xe00f0000, 0xa0e40003,                                     /* mov oT0, c3                  */
5361     0x00000001, 0xe00f0001, 0xa0e40003,                                     /* mov oT1, c3                  */
5362     0x00000001, 0xe00f0002, 0xa0e40003,                                     /* mov oT2, c3                  */
5363     0x00000001, 0xe00f0003, 0xa0e40002,                                     /* mov oT3, c2                  */
5364     0x00000001, 0xe00f0004, 0xa0e40003,                                     /* mov oT4, c3                  */
5365     0x00000001, 0xe00f0005, 0xa0e40003,                                     /* mov oT5, c3                  */
5366     0x00000001, 0xe00f0006, 0xa0e40003,                                     /* mov oT6, c3                  */
5367     0x00000001, 0xe00f0007, 0xa0e40003,                                     /* mov oT7, c3                  */
5368     0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
5369     0x0000ffff
5370     };
5371     DWORD vs_2_code[] = {
5372     0xfffe0200,                                                             /* vs_2_0                       */
5373     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
5374     0x05000051, 0xa00f0000, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.5, 0.0, 0.0, 0.0   */
5375     0x05000051, 0xa00f0001, 0x00000000, 0x3e4ccccd, 0x00000000, 0x00000000, /* def c1, 0.0, 0.5, 0.0, 0.0   */
5376     0x05000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3ecccccd, 0x00000000, /* def c2, 0.0, 0.0, 0.5, 0.0   */
5377     0x05000051, 0xa00f0003, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 1.0, 1.0, 1.0, 1.0   */
5378     0x02000001, 0xd00f0000, 0xa0e40002,                                     /* mov oD0, c2                  */
5379     0x02000001, 0xd00f0001, 0xa0e40000,                                     /* mov oD1, c0                  */
5380     0x02000001, 0xc00f0001, 0xa0550001,                                     /* mov oFog, c1.g               */
5381     0x02000001, 0xe00f0000, 0xa0e40003,                                     /* mov oT0, c3                  */
5382     0x02000001, 0xe00f0001, 0xa0e40003,                                     /* mov oT1, c3                  */
5383     0x02000001, 0xe00f0002, 0xa0e40003,                                     /* mov oT2, c3                  */
5384     0x02000001, 0xe00f0003, 0xa0e40002,                                     /* mov oT3, c2                  */
5385     0x02000001, 0xe00f0004, 0xa0e40003,                                     /* mov oT4, c3                  */
5386     0x02000001, 0xe00f0005, 0xa0e40003,                                     /* mov oT5, c3                  */
5387     0x02000001, 0xe00f0006, 0xa0e40003,                                     /* mov oT6, c3                  */
5388     0x02000001, 0xe00f0007, 0xa0e40003,                                     /* mov oT7, c3                  */
5389     0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
5390     0x0000ffff                                                              /* end                          */
5391     };
5392     /* TODO: Define normal, tangent, blendweight and depth here */
5393     static const DWORD vs_3_code[] = {
5394     0xfffe0300,                                                             /* vs_3_0                       */
5395     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
5396     0x0200001f, 0x8001000a, 0xe00f0009,                                     /* dcl_color1 o9                */
5397     0x0200001f, 0x8000000b, 0xe00f0002,                                     /* dcl_fog o2                   */
5398     0x0200001f, 0x80030005, 0xe00f0005,                                     /* dcl_texcoord3 o5             */
5399     0x0200001f, 0x80000000, 0xe00f000b,                                     /* dcl_position o11             */
5400     0x05000051, 0xa00f0000, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.1, 0.0, 0.0, 0.0   */
5401     0x05000051, 0xa00f0001, 0x00000000, 0x3e4ccccd, 0x00000000, 0x00000000, /* def c1, 0.0, 0.2, 0.0, 0.0   */
5402     0x05000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3ecccccd, 0x00000000, /* def c2, 0.0, 0.0, 0.4, 0.0   */
5403     0x05000051, 0xa00f0003, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 1.0, 1.0, 1.0, 1.0   */
5404     0x02000001, 0xe00f0009, 0xa0e40000,                                     /* mov o9, c0                   */
5405     0x02000001, 0xe00f0002, 0xa0e40001,                                     /* mov o2, c1                   */
5406     0x02000001, 0xe00f0005, 0xa0e40002,                                     /* mov o5, c2                   */
5407     0x02000001, 0xe00f000b, 0x90e40000,                                     /* mov o11, v0                  */
5408     0x0000ffff                                                              /* end                          */
5409     };
5410     float quad1[] =  {
5411         -1.0,   -1.0,   0.1,
5412          0.0,   -1.0,   0.1,
5413         -1.0,    0.0,   0.1,
5414          0.0,    0.0,   0.1
5415     };
5416     float quad2[] =  {
5417          0.0,   -1.0,   0.1,
5418          1.0,   -1.0,   0.1,
5419          0.0,    0.0,   0.1,
5420          1.0,    0.0,   0.1
5421     };
5422     float quad3[] =  {
5423         -1.0,    0.0,   0.1,
5424          0.0,    0.0,   0.1,
5425         -1.0,    1.0,   0.1,
5426          0.0,    1.0,   0.1
5427     };
5428
5429     HRESULT hr;
5430     DWORD color;
5431     IDirect3DPixelShader9 *pixelshader = NULL;
5432     IDirect3DVertexShader9 *vs_1_shader = NULL;
5433     IDirect3DVertexShader9 *vs_2_shader = NULL;
5434     IDirect3DVertexShader9 *vs_3_shader = NULL;
5435
5436     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff110000, 0.0, 0);
5437
5438     hr = IDirect3DDevice9_CreatePixelShader(device, ps_code, &pixelshader);
5439     ok(hr == D3D_OK, "IDirect3DDevice_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
5440     hr = IDirect3DDevice9_CreateVertexShader(device, vs_1_code, &vs_1_shader);
5441     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
5442     hr = IDirect3DDevice9_CreateVertexShader(device, vs_2_code, &vs_2_shader);
5443     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
5444     hr = IDirect3DDevice9_CreateVertexShader(device, vs_3_code, &vs_3_shader);
5445     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
5446     hr = IDirect3DDevice9_SetPixelShader(device, pixelshader);
5447     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
5448     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5449
5450     hr = IDirect3DDevice9_BeginScene(device);
5451     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
5452     if(SUCCEEDED(hr))
5453     {
5454         hr = IDirect3DDevice9_SetVertexShader(device, vs_1_shader);
5455         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5456         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 3);
5457         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5458
5459         hr = IDirect3DDevice9_SetVertexShader(device, vs_2_shader);
5460         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5461         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2,  quad2, sizeof(float) * 3);
5462         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5463
5464         hr = IDirect3DDevice9_SetVertexShader(device, vs_3_shader);
5465         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5466         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 3);
5467         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5468
5469         hr = IDirect3DDevice9_EndScene(device);
5470         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
5471     }
5472     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5473     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
5474
5475     color = getPixelColor(device, 160, 120);
5476     ok((color & 0x00ff0000) >= 0x00190000 && (color & 0x00ff0000) <= 0x00210000 &&
5477        (color & 0x0000ff00) >= 0x00003300 && (color & 0x0000ff00) <= 0x00003500 &&
5478        (color & 0x000000ff) >= 0x00000066 && (color & 0x000000ff) <= 0x00000068,
5479        "vs_3_0 returned color 0x%08x, expected 0x00203366\n", color);
5480     color = getPixelColor(device, 160, 360);
5481     ok((color & 0x00ff0000) >= 0x003c0000 && (color & 0x00ff0000) <= 0x004e0000 &&
5482        (color & 0x0000ff00) >= 0x00000000 && (color & 0x0000ff00) <= 0x00000000 &&
5483        (color & 0x000000ff) >= 0x00000066 && (color & 0x000000ff) <= 0x00000068,
5484        "vs_1_1 returned color 0x%08x, expected 0x004c0066\n", color);
5485     color = getPixelColor(device, 480, 360);
5486     ok((color & 0x00ff0000) >= 0x003c0000 && (color & 0x00ff0000) <= 0x004e0000 &&
5487        (color & 0x0000ff00) >= 0x00000000 && (color & 0x0000ff00) <= 0x00000000 &&
5488        (color & 0x000000ff) >= 0x00000066 && (color & 0x000000ff) <= 0x00000068,
5489        "vs_2_0 returned color 0x%08x, expected 0x004c0066\n", color);
5490
5491     /* cleanup */
5492     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5493     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
5494     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
5495     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5496     if(pixelshader) IDirect3DPixelShader9_Release(pixelshader);
5497     if(vs_1_shader) IDirect3DVertexShader9_Release(vs_1_shader);
5498     if(vs_2_shader) IDirect3DVertexShader9_Release(vs_2_shader);
5499     if(vs_3_shader) IDirect3DVertexShader9_Release(vs_3_shader);
5500 }
5501
5502 static void pshader_version_varying_test(IDirect3DDevice9 *device) {
5503     static const DWORD vs_code[] = {
5504     0xfffe0300,                                                             /* vs_3_0                       */
5505     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
5506     0x0200001f, 0x80000000, 0xe00f0000,                                     /* dcl_position o0              */
5507     0x0200001f, 0x8000000a, 0xe00f0001,                                     /* dcl_color0 o1                */
5508     0x0200001f, 0x80000005, 0xe00f0002,                                     /* dcl_texcoord0 o2             */
5509     0x0200001f, 0x8000000b, 0xe00f0003,                                     /* dcl_fog o3                   */
5510     0x0200001f, 0x80000003, 0xe00f0004,                                     /* dcl_normal o4                */
5511     0x0200001f, 0x8000000c, 0xe00f0005,                                     /* dcl_depth o5                 */
5512     0x0200001f, 0x80000006, 0xe00f0006,                                     /* dcl_tangent o6               */
5513     0x0200001f, 0x80000001, 0xe00f0007,                                     /* dcl_blendweight o7           */
5514     0x05000051, 0xa00f0001, 0x3dcccccd, 0x00000000, 0x00000000, 0x00000000, /* def c1, 0.1, 0.0, 0.0, 0.0   */
5515     0x05000051, 0xa00f0002, 0x00000000, 0x3e4ccccd, 0x00000000, 0x3f800000, /* def c2, 0.0, 0.2, 0.0, 1.0   */
5516     0x05000051, 0xa00f0003, 0x3ecccccd, 0x3f59999a, 0x3f666666, 0x00000000, /* def c3, 0.4, 0.85,0.9, 0.0   */
5517     0x05000051, 0xa00f0000, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c0, 1.0, 1.0, 1.0, 1.0   */
5518
5519     0x02000001, 0xe00f0000, 0x90e40000,                                     /* mov o0, v0                   */
5520     0x02000001, 0xe00f0001, 0xa0e40001,                                     /* mov o1, c1                   */
5521     0x02000001, 0xe00f0002, 0xa0e40002,                                     /* mov o2, c2                   */
5522     0x02000001, 0xe00f0003, 0xa0e40003,                                     /* mov o3, c3                   */
5523     0x02000001, 0xe00f0004, 0xa0e40000,                                     /* mov o4, c0                   */
5524     0x02000001, 0xe00f0005, 0xa0e40000,                                     /* mov o5, c0                   */
5525     0x02000001, 0xe00f0006, 0xa0e40000,                                     /* mov o6, c0                   */
5526     0x02000001, 0xe00f0007, 0xa0e40000,                                     /* mov o7, c0                   */
5527     0x0000ffff                                                              /* end                          */
5528     };
5529     static const DWORD ps_1_code[] = {
5530     0xffff0104,                                                             /* ps_1_4                       */
5531     0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0   */
5532     0x00000040, 0x80070001, 0xb0e40000,                                     /* texcrd r1.xyz, t0            */
5533     0x00000001, 0x80080001, 0xa0ff0000,                                     /* mov r1.a, c0.a               */
5534     0x00000002, 0x800f0000, 0x90e40000, 0x80e40001,                         /* add r0, v0, r1               */
5535     0x0000ffff                                                              /* end                          */
5536     };
5537     static const DWORD ps_2_code[] = {
5538     0xffff0200,                                                             /* ps_2_0                       */
5539     0x0200001f, 0x80000000, 0xb00f0000,                                     /* dcl t0                       */
5540     0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl v0                       */
5541     0x0200001f, 0x80000000, 0x900f0001,                                     /* dcl v1                       */
5542
5543     0x02000001, 0x800f0000, 0x90e40000,                                     /* mov r0, v0                   */
5544     0x03000002, 0x800f0000, 0x80e40000,0xb0e40000,                          /* add r0, r0, t0               */
5545     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
5546     0x0000ffff                                                              /* end                          */
5547     };
5548     static const DWORD ps_3_code[] = {
5549     0xffff0300,                                                             /* ps_3_0                       */
5550     0x0200001f, 0x80000005, 0x900f0000,                                     /* dcl_texcoord0 v0             */
5551     0x0200001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                */
5552     0x0200001f, 0x8000000b, 0x900f0002,                                     /* dcl_fog v2                   */
5553
5554     0x02000001, 0x800f0000, 0x90e40000,                                     /* mov r0, v0                   */
5555     0x03000002, 0x800f0000, 0x80e40000, 0x90e40001,                         /* add r0, r0, v1               */
5556     0x03000002, 0x800f0000, 0x80e40000, 0x90e40002,                         /* mov r0, r0, v2               */
5557     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                  */
5558     0x0000ffff                                                              /* end                          */
5559     };
5560
5561     float quad1[] =  {
5562         -1.0,   -1.0,   0.1,
5563          0.0,   -1.0,   0.1,
5564         -1.0,    0.0,   0.1,
5565          0.0,    0.0,   0.1
5566     };
5567     float quad2[] =  {
5568          0.0,   -1.0,   0.1,
5569          1.0,   -1.0,   0.1,
5570          0.0,    0.0,   0.1,
5571          1.0,    0.0,   0.1
5572     };
5573     float quad3[] =  {
5574         -1.0,    0.0,   0.1,
5575          0.0,    0.0,   0.1,
5576         -1.0,    1.0,   0.1,
5577          0.0,    1.0,   0.1
5578     };
5579     float quad4[] =  {
5580          0.0,    0.0,   0.1,
5581          1.0,    0.0,   0.1,
5582          0.0,    1.0,   0.1,
5583          1.0,    1.0,   0.1
5584     };
5585
5586     HRESULT hr;
5587     DWORD color;
5588     IDirect3DVertexShader9 *vertexshader = NULL;
5589     IDirect3DPixelShader9 *ps_1_shader = NULL;
5590     IDirect3DPixelShader9 *ps_2_shader = NULL;
5591     IDirect3DPixelShader9 *ps_3_shader = NULL;
5592     IDirect3DTexture9 *texture = NULL;
5593     D3DLOCKED_RECT lr;
5594     unsigned int x, y;
5595
5596     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
5597
5598     hr = IDirect3DDevice9_CreateTexture(device, 512,  512, 1, 0, D3DFMT_A16B16G16R16, D3DPOOL_MANAGED, &texture, NULL);
5599     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %s\n", DXGetErrorString9(hr));
5600     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
5601     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %s\n", DXGetErrorString9(hr));
5602     for(y = 0; y < 512; y++) {
5603         for(x = 0; x < 512; x++) {
5604             double r_f = (double) x / (double) 512;
5605             double g_f = (double) y / (double) 512;
5606             unsigned short *dst = (unsigned short *) (((unsigned char *) lr.pBits) + y * lr.Pitch + x * 8);
5607             unsigned short r = (unsigned short) (r_f * 65535.0);
5608             unsigned short g = (unsigned short) (g_f * 65535.0);
5609             dst[0] = r;
5610             dst[1] = g;
5611             dst[2] = 0;
5612             dst[3] = 65535;
5613         }
5614     }
5615     hr = IDirect3DTexture9_UnlockRect(texture, 0);
5616     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect returned %s\n", DXGetErrorString9(hr));
5617
5618     hr = IDirect3DDevice9_CreateVertexShader(device, vs_code, &vertexshader);
5619     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
5620     hr = IDirect3DDevice9_CreatePixelShader(device, ps_1_code, &ps_1_shader);
5621     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
5622     hr = IDirect3DDevice9_CreatePixelShader(device, ps_2_code, &ps_2_shader);
5623     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
5624     hr = IDirect3DDevice9_CreatePixelShader(device, ps_3_code, &ps_3_shader);
5625     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
5626     hr = IDirect3DDevice9_SetVertexShader(device, vertexshader);
5627     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5628     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5629
5630     hr = IDirect3DDevice9_BeginScene(device);
5631     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
5632     if(SUCCEEDED(hr))
5633     {
5634         hr = IDirect3DDevice9_SetPixelShader(device, ps_1_shader);
5635         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
5636         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 3);
5637         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5638
5639         hr = IDirect3DDevice9_SetPixelShader(device, ps_2_shader);
5640         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
5641         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2,  quad2, sizeof(float) * 3);
5642         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5643
5644         hr = IDirect3DDevice9_SetPixelShader(device, ps_3_shader);
5645         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
5646         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 3);
5647         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5648
5649         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5650         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
5651         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
5652         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
5653         hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
5654         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_ADD);
5655         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
5656         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
5657         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 3);
5658         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5659
5660         hr = IDirect3DDevice9_EndScene(device);
5661         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
5662     }
5663     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5664     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
5665
5666     color = getPixelColor(device, 160, 120);
5667     ok((color & 0x00ff0000) >= 0x00790000 && (color & 0x00ff0000) <= 0x00810000 &&
5668        (color & 0x0000ff00) == 0x0000ff00 &&
5669        (color & 0x000000ff) >= 0x000000e4 && (color & 0x000000ff) <= 0x000000e6,
5670        "ps_3_0 returned color 0x%08x, expected 0x0080ffe5\n", color);
5671     color = getPixelColor(device, 160, 360);
5672     ok((color & 0x00ff0000) >= 0x00190000 && (color & 0x00ff0000) <= 0x00210000 &&
5673        (color & 0x0000ff00) >= 0x00003300 && (color & 0x0000ff00) <= 0x00003400 &&
5674        (color & 0x000000ff) == 0x00000000,
5675        "ps_1_4 returned color 0x%08x, expected 0x00203300\n", color);
5676     color = getPixelColor(device, 480, 360);
5677     ok((color & 0x00ff0000) >= 0x00190000 && (color & 0x00ff0000) <= 0x00210000 &&
5678        (color & 0x0000ff00) >= 0x00003200 && (color & 0x0000ff00) <= 0x00003400 &&
5679        (color & 0x000000ff) == 0x00000000,
5680        "ps_2_0 returned color 0x%08x, expected 0x00203300\n", color);
5681     color = getPixelColor(device, 480, 160);
5682     ok( color == 0x00ffffff /* Nvidia driver garbage with HW vp */ || (
5683        (color & 0x00ff0000) >= 0x00190000 && (color & 0x00ff0000) <= 0x00210000 &&
5684        (color & 0x0000ff00) >= 0x00003200 && (color & 0x0000ff00) <= 0x00003400 &&
5685        (color & 0x000000ff) == 0x00000000),
5686        "fixed function fragment processing returned color 0x%08x, expected 0x00203300\n", color);
5687
5688     /* cleanup */
5689     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
5690     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
5691     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
5692     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
5693     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
5694     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5695     if(vertexshader) IDirect3DVertexShader9_Release(vertexshader);
5696     if(ps_1_shader) IDirect3DPixelShader9_Release(ps_1_shader);
5697     if(ps_2_shader) IDirect3DPixelShader9_Release(ps_2_shader);
5698     if(ps_3_shader) IDirect3DPixelShader9_Release(ps_3_shader);
5699     if(texture) IDirect3DTexture9_Release(texture);
5700 }
5701
5702 void test_compare_instructions(IDirect3DDevice9 *device)
5703 {
5704     DWORD shader_sge_vec_code[] = {
5705         0xfffe0101,                                         /* vs_1_1                   */
5706         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
5707         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
5708         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
5709         0x0000000d, 0xd00f0000, 0x80e40000, 0xa0e40001,     /* sge oD0, r0, c1          */
5710         0x0000ffff                                          /* end                      */
5711     };
5712     DWORD shader_slt_vec_code[] = {
5713         0xfffe0101,                                         /* vs_1_1                   */
5714         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
5715         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
5716         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
5717         0x0000000c, 0xd00f0000, 0x80e40000, 0xa0e40001,     /* slt oD0, r0, c1          */
5718         0x0000ffff                                          /* end                      */
5719     };
5720     DWORD shader_sge_scalar_code[] = {
5721         0xfffe0101,                                         /* vs_1_1                   */
5722         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
5723         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
5724         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
5725         0x0000000d, 0xd0010000, 0x80000000, 0xa0550001,     /* slt oD0.r, r0.r, c1.b    */
5726         0x0000000d, 0xd0020000, 0x80550000, 0xa0aa0001,     /* slt oD0.g, r0.g, c1.r    */
5727         0x0000000d, 0xd0040000, 0x80aa0000, 0xa0000001,     /* slt oD0.b, r0.b, c1.g    */
5728         0x0000ffff                                          /* end                      */
5729     };
5730     DWORD shader_slt_scalar_code[] = {
5731         0xfffe0101,                                         /* vs_1_1                   */
5732         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0          */
5733         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0             */
5734         0x00000001, 0x800f0000, 0xa0e40000,                 /* mov r0, c0               */
5735         0x0000000c, 0xd0010000, 0x80000000, 0xa0aa0001,     /* slt oD0.r, r0.r, c1.b    */
5736         0x0000000c, 0xd0020000, 0x80550000, 0xa0000001,     /* slt oD0.g, r0.g, c1.r    */
5737         0x0000000c, 0xd0040000, 0x80aa0000, 0xa0550001,     /* slt oD0.b, r0.b, c1.g    */
5738         0x0000ffff                                          /* end                      */
5739     };
5740     IDirect3DVertexShader9 *shader_sge_vec;
5741     IDirect3DVertexShader9 *shader_slt_vec;
5742     IDirect3DVertexShader9 *shader_sge_scalar;
5743     IDirect3DVertexShader9 *shader_slt_scalar;
5744     HRESULT hr, color;
5745     float quad1[] =  {
5746         -1.0,   -1.0,   0.1,
5747          0.0,   -1.0,   0.1,
5748         -1.0,    0.0,   0.1,
5749          0.0,    0.0,   0.1
5750     };
5751     float quad2[] =  {
5752          0.0,   -1.0,   0.1,
5753          1.0,   -1.0,   0.1,
5754          0.0,    0.0,   0.1,
5755          1.0,    0.0,   0.1
5756     };
5757     float quad3[] =  {
5758         -1.0,    0.0,   0.1,
5759          0.0,    0.0,   0.1,
5760         -1.0,    1.0,   0.1,
5761          0.0,    1.0,   0.1
5762     };
5763     float quad4[] =  {
5764          0.0,    0.0,   0.1,
5765          1.0,    0.0,   0.1,
5766          0.0,    1.0,   0.1,
5767          1.0,    1.0,   0.1
5768     };
5769     const float const0[4] = {0.8, 0.2, 0.2, 0.2};
5770     const float const1[4] = {0.2, 0.8, 0.2, 0.2};
5771
5772     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
5773
5774     hr = IDirect3DDevice9_CreateVertexShader(device, shader_sge_vec_code, &shader_sge_vec);
5775     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
5776     hr = IDirect3DDevice9_CreateVertexShader(device, shader_slt_vec_code, &shader_slt_vec);
5777     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
5778     hr = IDirect3DDevice9_CreateVertexShader(device, shader_sge_scalar_code, &shader_sge_scalar);
5779     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
5780     hr = IDirect3DDevice9_CreateVertexShader(device, shader_slt_scalar_code, &shader_slt_scalar);
5781     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
5782     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, const0, 1);
5783     ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
5784     hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 1, const1, 1);
5785     ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
5786     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
5787     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetFVF failed (%08x)\n", hr);
5788
5789     hr = IDirect3DDevice9_BeginScene(device);
5790     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
5791     if(SUCCEEDED(hr))
5792     {
5793         hr = IDirect3DDevice9_SetVertexShader(device, shader_sge_vec);
5794         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5795         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 3);
5796         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5797
5798         hr = IDirect3DDevice9_SetVertexShader(device, shader_slt_vec);
5799         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5800         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2,  quad2, sizeof(float) * 3);
5801         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5802
5803         hr = IDirect3DDevice9_SetVertexShader(device, shader_sge_scalar);
5804         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5805         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 3);
5806         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5807
5808         hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, const0, 1);
5809         ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
5810
5811         hr = IDirect3DDevice9_SetVertexShader(device, shader_slt_scalar);
5812         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
5813         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 3);
5814         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
5815
5816         hr = IDirect3DDevice9_EndScene(device);
5817         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
5818     }
5819
5820     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
5821     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
5822
5823     color = getPixelColor(device, 160, 360);
5824     ok(color == 0x00FF00FF, "Compare test: Quad 1(sge vec) returned color 0x%08x, expected 0x00FF00FF\n", color);
5825     color = getPixelColor(device, 480, 360);
5826     ok(color == 0x0000FF00, "Compare test: Quad 2(slt vec) returned color 0x%08x, expected 0x0000FF00\n", color);
5827     color = getPixelColor(device, 160, 120);
5828     ok(color == 0x00FFFFFF, "Compare test: Quad 3(sge scalar) returned color 0x%08x, expected 0x00FFFFFF\n", color);
5829     color = getPixelColor(device, 480, 160);
5830     ok(color == 0x000000ff, "Compare test: Quad 4(slt scalar) returned color 0x%08x, expected 0x000000ff\n", color);
5831
5832     IDirect3DVertexShader9_Release(shader_sge_vec);
5833     IDirect3DVertexShader9_Release(shader_slt_vec);
5834     IDirect3DVertexShader9_Release(shader_sge_scalar);
5835     IDirect3DVertexShader9_Release(shader_slt_scalar);
5836 }
5837
5838 void test_vshader_input(IDirect3DDevice9 *device)
5839 {
5840     DWORD swapped_shader_code_3[] = {
5841         0xfffe0300,                                         /* vs_3_0               */
5842         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
5843         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
5844         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5845         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
5846         0x0200001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
5847         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
5848         0x02000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
5849         0x03000002, 0xe00f0001, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
5850         0x0000ffff                                          /* end                  */
5851     };
5852     DWORD swapped_shader_code_1[] = {
5853         0xfffe0101,                                         /* vs_1_1               */
5854         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5855         0x0000001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
5856         0x0000001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
5857         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov o0, v0           */
5858         0x00000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
5859         0x00000002, 0xd00f0000, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
5860         0x0000ffff                                          /* end                  */
5861     };
5862     DWORD swapped_shader_code_2[] = {
5863         0xfffe0200,                                         /* vs_2_0               */
5864         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5865         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord0 v1     */
5866         0x0200001f, 0x80010005, 0x900f0002,                 /* dcl_texcoord1 v2     */
5867         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov o0, v0           */
5868         0x02000001, 0x800f0001, 0x90e40001,                 /* mov r1, v1           */
5869         0x03000002, 0xd00f0000, 0x80e40001, 0x91e40002,     /* sub o1, r1, v2       */
5870         0x0000ffff                                          /* end                  */
5871     };
5872     DWORD texcoord_color_shader_code_3[] = {
5873         0xfffe0300,                                         /* vs_3_0               */
5874         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
5875         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
5876         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5877         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
5878         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
5879         0x02000001, 0xe00f0001, 0x90e40001,                 /* mov o1, v1           */
5880         0x0000ffff                                          /* end                  */
5881     };
5882     DWORD texcoord_color_shader_code_2[] = {
5883         0xfffe0200,                                         /* vs_2_0               */
5884         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5885         0x0200001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
5886         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
5887         0x02000001, 0xd00f0000, 0x90e40001,                 /* mov oD0, v1          */
5888         0x0000ffff                                          /* end                  */
5889     };
5890     DWORD texcoord_color_shader_code_1[] = {
5891         0xfffe0101,                                         /* vs_1_1               */
5892         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5893         0x0000001f, 0x80000005, 0x900f0001,                 /* dcl_texcoord v1      */
5894         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
5895         0x00000001, 0xd00f0000, 0x90e40001,                 /* mov oD0, v1          */
5896         0x0000ffff                                          /* end                  */
5897     };
5898     DWORD color_color_shader_code_3[] = {
5899         0xfffe0300,                                         /* vs_3_0               */
5900         0x0200001f, 0x80000000, 0xe00f0000,                 /* dcl_position o0      */
5901         0x0200001f, 0x8000000a, 0xe00f0001,                 /* dcl_color o1         */
5902         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5903         0x0200001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
5904         0x02000001, 0xe00f0000, 0x90e40000,                 /* mov o0, v0           */
5905         0x03000005, 0xe00f0001, 0xa0e40000, 0x90e40001,     /* mul o1, c0, v1       */
5906         0x0000ffff                                          /* end                  */
5907     };
5908     DWORD color_color_shader_code_2[] = {
5909         0xfffe0200,                                         /* vs_2_0               */
5910         0x0200001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5911         0x0200001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
5912         0x02000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
5913         0x03000005, 0xd00f0000, 0xa0e40000, 0x90e40001,     /* mul oD0, c0, v1       */
5914         0x0000ffff                                          /* end                  */
5915     };
5916     DWORD color_color_shader_code_1[] = {
5917         0xfffe0101,                                         /* vs_1_1               */
5918         0x0000001f, 0x80000000, 0x900f0000,                 /* dcl_position v0      */
5919         0x0000001f, 0x8000000a, 0x900f0001,                 /* dcl_color v1         */
5920         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0         */
5921         0x00000005, 0xd00f0000, 0xa0e40000, 0x90e40001,     /* mul oD0, c0, v1       */
5922         0x0000ffff                                          /* end                  */
5923     };
5924     IDirect3DVertexShader9 *swapped_shader, *texcoord_color_shader, *color_color_shader;
5925     HRESULT hr;
5926     DWORD color, r, g, b;
5927     float quad1[] =  {
5928         -1.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
5929          0.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
5930         -1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
5931          0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
5932     };
5933     float quad2[] =  {
5934          0.0,   -1.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
5935          1.0,   -1.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
5936          0.0,    0.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
5937          1.0,    0.0,   0.1,    1.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
5938     };
5939     float quad3[] =  {
5940         -1.0,    0.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    1.0,    -1.0,   0.0,    0.0,
5941          0.0,    0.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    1.0,     0.0,   0.0,    0.0,
5942         -1.0,    1.0,   0.1,   -1.0,    0.0,    0.0,    0.0,    0.0,    -1.0,   1.0,    0.0,
5943          0.0,    1.0,   0.1,   -1.0,    0.0,    0.0,    0.0,   -1.0,     0.0,   0.0,    0.0,
5944     };
5945     float quad4[] =  {
5946          0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
5947          1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
5948          0.0,    1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
5949          1.0,    1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.5,    0.0,
5950     };
5951     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd[] = {
5952         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
5953         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
5954         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
5955         D3DDECL_END()
5956     };
5957     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd_rightorder[] = {
5958         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
5959         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
5960         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
5961         D3DDECL_END()
5962     };
5963     static const D3DVERTEXELEMENT9 decl_elements_onetexcrd[] = {
5964         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
5965         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
5966         D3DDECL_END()
5967     };
5968     static const D3DVERTEXELEMENT9 decl_elements_twotexcrd_wrongidx[] = {
5969         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
5970         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       1},
5971         {0,  28,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       2},
5972         D3DDECL_END()
5973     };
5974     static const D3DVERTEXELEMENT9 decl_elements_texcoord_color[] = {
5975         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
5976         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,       0},
5977         D3DDECL_END()
5978     };
5979     static const D3DVERTEXELEMENT9 decl_elements_color_color[] = {
5980         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
5981         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
5982         D3DDECL_END()
5983     };
5984     static const D3DVERTEXELEMENT9 decl_elements_color_ubyte[] = {
5985         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
5986         {0,  12,  D3DDECLTYPE_UBYTE4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
5987         D3DDECL_END()
5988     };
5989     static const D3DVERTEXELEMENT9 decl_elements_color_float[] = {
5990         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
5991         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
5992         D3DDECL_END()
5993     };
5994     IDirect3DVertexDeclaration9 *decl_twotexcrd, *decl_onetexcrd, *decl_twotex_wrongidx, *decl_twotexcrd_rightorder;
5995     IDirect3DVertexDeclaration9 *decl_texcoord_color, *decl_color_color, *decl_color_ubyte, *decl_color_float;
5996     unsigned int i;
5997     float normalize[4] = {1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0};
5998     float no_normalize[4] = {1.0, 1.0, 1.0, 1.0};
5999
6000     struct vertex quad1_color[] =  {
6001        {-1.0,   -1.0,   0.1,    0x00ff8040},
6002        { 0.0,   -1.0,   0.1,    0x00ff8040},
6003        {-1.0,    0.0,   0.1,    0x00ff8040},
6004        { 0.0,    0.0,   0.1,    0x00ff8040}
6005     };
6006     struct vertex quad2_color[] =  {
6007        { 0.0,   -1.0,   0.1,    0x00ff8040},
6008        { 1.0,   -1.0,   0.1,    0x00ff8040},
6009        { 0.0,    0.0,   0.1,    0x00ff8040},
6010        { 1.0,    0.0,   0.1,    0x00ff8040}
6011     };
6012     struct vertex quad3_color[] =  {
6013        {-1.0,    0.0,   0.1,    0x00ff8040},
6014        { 0.0,    0.0,   0.1,    0x00ff8040},
6015        {-1.0,    1.0,   0.1,    0x00ff8040},
6016        { 0.0,    1.0,   0.1,    0x00ff8040}
6017     };
6018     float quad4_color[] =  {
6019          0.0,    0.0,   0.1,    1.0,    1.0,    0.0,    0.0,
6020          1.0,    0.0,   0.1,    1.0,    1.0,    0.0,    1.0,
6021          0.0,    1.0,   0.1,    1.0,    1.0,    0.0,    0.0,
6022          1.0,    1.0,   0.1,    1.0,    1.0,    0.0,    1.0,
6023     };
6024
6025     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd, &decl_twotexcrd);
6026     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6027     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_onetexcrd, &decl_onetexcrd);
6028     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6029     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd_wrongidx, &decl_twotex_wrongidx);
6030     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6031     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_twotexcrd_rightorder, &decl_twotexcrd_rightorder);
6032     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6033
6034     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_texcoord_color, &decl_texcoord_color);
6035     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6036     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_color, &decl_color_color);
6037     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6038     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_ubyte, &decl_color_ubyte);
6039     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6040     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_color_float, &decl_color_float);
6041     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6042
6043     for(i = 1; i <= 3; i++) {
6044         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
6045         if(i == 3) {
6046             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_3, &swapped_shader);
6047             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
6048         } else if(i == 2){
6049             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_2, &swapped_shader);
6050             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
6051         } else if(i == 1) {
6052             hr = IDirect3DDevice9_CreateVertexShader(device, swapped_shader_code_1, &swapped_shader);
6053             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
6054         }
6055
6056         hr = IDirect3DDevice9_BeginScene(device);
6057         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
6058         if(SUCCEEDED(hr))
6059         {
6060             hr = IDirect3DDevice9_SetVertexShader(device, swapped_shader);
6061             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
6062
6063             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd);
6064             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6065             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(float) * 11);
6066             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6067
6068             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_onetexcrd);
6069             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6070             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(float) * 11);
6071             if(i == 3 || i == 2) {
6072                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
6073             } else if(i == 1) {
6074                 /* Succeeds or fails, depending on SW or HW vertex processing */
6075                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x), i = 1\n", hr);
6076             }
6077
6078             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd_rightorder);
6079             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6080             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(float) * 11);
6081             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6082
6083             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotex_wrongidx);
6084             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6085             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(float) * 11);
6086             if(i == 3 || i == 2) {
6087                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
6088             } else if(i == 1) {
6089                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = 1\n", hr);
6090             }
6091
6092             hr = IDirect3DDevice9_EndScene(device);
6093             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
6094         }
6095
6096         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6097         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
6098
6099         if(i == 3 || i == 2) {
6100             color = getPixelColor(device, 160, 360);
6101             ok(color == 0x00FFFF80 || color == 0x00FFFF7f || color == 0x00FFFF81,
6102                "Input test: Quad 1(2crd) returned color 0x%08x, expected 0x00FFFF80\n", color);
6103
6104             /* The last value of the read but undefined stream is used, it is 0x00. The defined input is vec4(1, 0, 0, 0) */
6105             color = getPixelColor(device, 480, 360);
6106             ok(color == 0x00FFFF00 || color ==0x00FF0000,
6107                "Input test: Quad 2(1crd) returned color 0x%08x, expected 0x00FFFF00\n", color);
6108             color = getPixelColor(device, 160, 120);
6109             /* Same as above, accept both the last used value and 0.0 for the undefined streams */
6110             ok(color == 0x00FF0080 || color == 0x00FF007f || color == 0x00FF0081 || color == 0x00FF0000,
6111                "Input test: Quad 3(2crd-wrongidx) returned color 0x%08x, expected 0x00FF0080\n", color);
6112
6113             color = getPixelColor(device, 480, 160);
6114             ok(color == 0x00000000, "Input test: Quad 4(2crd-rightorder) returned color 0x%08x, expected 0x00000000\n", color);
6115         } else if(i == 1) {
6116             color = getPixelColor(device, 160, 360);
6117             ok(color == 0x00FFFF80 || color == 0x00FFFF7f || color == 0x00FFFF81,
6118                "Input test: Quad 1(2crd) returned color 0x%08x, expected 0x00FFFF80\n", color);
6119             color = getPixelColor(device, 480, 360);
6120             /* Accept the clear color as well in this case, since SW VP returns an error */
6121             ok(color == 0x00FFFF00 || color == 0x00FF0000, "Input test: Quad 2(1crd) returned color 0x%08x, expected 0x00FFFF00\n", color);
6122             color = getPixelColor(device, 160, 120);
6123             ok(color == 0x00FF0080 || color == 0x00FF0000 || color == 0x00FF007f || color == 0x00FF0081,
6124                "Input test: Quad 3(2crd-wrongidx) returned color 0x%08x, expected 0x00FF0080\n", color);
6125             color = getPixelColor(device, 480, 160);
6126             ok(color == 0x00000000, "Input test: Quad 4(2crd-rightorder) returned color 0x%08x, expected 0x00000000\n", color);
6127         }
6128
6129         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff808080, 0.0, 0);
6130         ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
6131
6132         /* Now find out if the whole streams are re-read, or just the last active value for the
6133          * vertices is used.
6134          */
6135         hr = IDirect3DDevice9_BeginScene(device);
6136         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
6137         if(SUCCEEDED(hr))
6138         {
6139             float quad1_modified[] =  {
6140                 -1.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,   -1.0,     0.0,   0.0,    0.0,
6141                  0.0,   -1.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,    -1.0,   0.0,    0.0,
6142                 -1.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,    0.0,     0.0,  -1.0,    0.0,
6143                  0.0,    0.0,   0.1,    1.0,    0.0,    1.0,    0.0,   -1.0,    -1.0,  -1.0,    0.0,
6144             };
6145             float quad2_modified[] =  {
6146                  0.0,   -1.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6147                  1.0,   -1.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6148                  0.0,    0.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6149                  1.0,    0.0,   0.1,    0.0,    0.0,    0.0,    0.0,    0.0,     0.0,   0.0,    0.0,
6150             };
6151
6152             hr = IDirect3DDevice9_SetVertexShader(device, swapped_shader);
6153             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
6154
6155             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_twotexcrd);
6156             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6157             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 3, quad1_modified, sizeof(float) * 11);
6158             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6159
6160             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_onetexcrd);
6161             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6162             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2_modified, sizeof(float) * 11);
6163             if(i == 3 || i == 2) {
6164                 ok(hr == D3D_OK, "DrawPrimitiveUP returned (%08x) i = %d\n", hr, i);
6165             } else if(i == 1) {
6166                 /* Succeeds or fails, depending on SW or HW vertex processing */
6167                 ok(hr == D3DERR_INVALIDCALL || hr == D3D_OK, "DrawPrimitiveUP returned (%08x), i = 1\n", hr);
6168             }
6169
6170             hr = IDirect3DDevice9_EndScene(device);
6171             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
6172         }
6173         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6174         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
6175
6176         color = getPixelColor(device, 480, 350);
6177         /* vs_1_1 may fail, accept the clear color. Some drivers also set the undefined streams to 0, accept that
6178          * as well.
6179          *
6180          * NOTE: This test fails on the reference rasterizer. In the refrast, the 4 vertices have different colors,
6181          * i.e., the whole old stream is read, and not just the last used attribute. Some games require that this
6182          * does *not* happen, otherwise they can crash because of a read from a bad pointer, so do not accept the
6183          * refrast's result.
6184          *
6185          * A test app for this behavior is Half Life 2 Episode 2 in dxlevel 95, and related games(Portal, TF2).
6186          */
6187         ok(color == 0x000000FF || color == 0x00808080 || color == 0x00000000,
6188            "Input test: Quad 2(different colors) returned color 0x%08x, expected 0x000000FF, 0x00808080 or 0x00000000\n", color);
6189         color = getPixelColor(device, 160, 120);
6190
6191         IDirect3DDevice9_SetVertexShader(device, NULL);
6192         IDirect3DDevice9_SetVertexDeclaration(device, NULL);
6193
6194         IDirect3DVertexShader9_Release(swapped_shader);
6195     }
6196
6197     for(i = 1; i <= 3; i++) {
6198         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
6199         if(i == 3) {
6200             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_3, &texcoord_color_shader);
6201             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
6202             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_3, &color_color_shader);
6203             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
6204         } else if(i == 2){
6205             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_2, &texcoord_color_shader);
6206             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
6207             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_2, &color_color_shader);
6208             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
6209         } else if(i == 1) {
6210             hr = IDirect3DDevice9_CreateVertexShader(device, texcoord_color_shader_code_1, &texcoord_color_shader);
6211             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
6212             hr = IDirect3DDevice9_CreateVertexShader(device, color_color_shader_code_1, &color_color_shader);
6213             ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
6214         }
6215
6216         hr = IDirect3DDevice9_BeginScene(device);
6217         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
6218         if(SUCCEEDED(hr))
6219         {
6220             hr = IDirect3DDevice9_SetVertexShader(device, texcoord_color_shader);
6221             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
6222             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_texcoord_color);
6223             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6224             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1_color, sizeof(quad1_color[0]));
6225             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6226
6227             hr = IDirect3DDevice9_SetVertexShader(device, color_color_shader);
6228             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
6229
6230             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, normalize, 1);
6231             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
6232             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_ubyte);
6233             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6234             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2_color, sizeof(quad2_color[0]));
6235             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6236
6237             hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 0, no_normalize, 1);
6238             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
6239             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_color);
6240             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6241             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3_color, sizeof(quad3_color[0]));
6242             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6243
6244             hr = IDirect3DDevice9_SetVertexDeclaration(device, decl_color_float);
6245             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
6246             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4_color, sizeof(float) * 7);
6247             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6248
6249             hr = IDirect3DDevice9_EndScene(device);
6250             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
6251         }
6252         IDirect3DDevice9_SetVertexShader(device, NULL);
6253         IDirect3DDevice9_SetVertexDeclaration(device, NULL);
6254
6255         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6256         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
6257
6258         color = getPixelColor(device, 160, 360);
6259         r = (color & 0x00ff0000) >> 16;
6260         g = (color & 0x0000ff00) >>  8;
6261         b = (color & 0x000000ff) >>  0;
6262         ok(r >= 0xfe && r <= 0xff && g >= 0x7f && g <= 0x81 && b >= 0x3f && b <= 0x41,
6263            "Input test: Quad 1(color-texcoord) returned color 0x%08x, expected 0x00ff8040\n", color);
6264         color = getPixelColor(device, 480, 360);
6265         r = (color & 0x00ff0000) >> 16;
6266         g = (color & 0x0000ff00) >>  8;
6267         b = (color & 0x000000ff) >>  0;
6268         ok(r >= 0x3f && r <= 0x41 && g >= 0x7f && g <= 0x81 && b >= 0xfe && b <= 0xff,
6269            "Input test: Quad 2(color-ubyte) returned color 0x%08x, expected 0x004080ff\n", color);
6270         color = getPixelColor(device, 160, 120);
6271         r = (color & 0x00ff0000) >> 16;
6272         g = (color & 0x0000ff00) >>  8;
6273         b = (color & 0x000000ff) >>  0;
6274         ok(r >= 0xfe && r <= 0xff && g >= 0x7f && g <= 0x81 && b >= 0x3f && b <= 0x41,
6275            "Input test: Quad 3(color-color) returned color 0x%08x, expected 0x00ff8040\n", color);
6276         color = getPixelColor(device, 480, 160);
6277         r = (color & 0x00ff0000) >> 16;
6278         g = (color & 0x0000ff00) >>  8;
6279         b = (color & 0x000000ff) >>  0;
6280         ok(r >= 0xfe && r <= 0xff && g >= 0xfe && g <= 0xff && b <= 0x01,
6281            "Input test: Quad 4(color-float) returned color 0x%08x, expected 0x00FFFF00\n", color);
6282
6283         IDirect3DVertexShader9_Release(texcoord_color_shader);
6284         IDirect3DVertexShader9_Release(color_color_shader);
6285     }
6286
6287     IDirect3DVertexDeclaration9_Release(decl_twotexcrd);
6288     IDirect3DVertexDeclaration9_Release(decl_onetexcrd);
6289     IDirect3DVertexDeclaration9_Release(decl_twotex_wrongidx);
6290     IDirect3DVertexDeclaration9_Release(decl_twotexcrd_rightorder);
6291
6292     IDirect3DVertexDeclaration9_Release(decl_texcoord_color);
6293     IDirect3DVertexDeclaration9_Release(decl_color_color);
6294     IDirect3DVertexDeclaration9_Release(decl_color_ubyte);
6295     IDirect3DVertexDeclaration9_Release(decl_color_float);
6296 }
6297
6298 static void srgbtexture_test(IDirect3DDevice9 *device)
6299 {
6300     /* Fill a texture with 0x7f (~ .5), and then turn on the D3DSAMP_SRGBTEXTURE
6301      * texture stage state to render a quad using that texture.  The resulting
6302      * color components should be 0x36 (~ 0.21), per this formula:
6303      *    linear_color = ((srgb_color + 0.055) / 1.055) ^ 2.4
6304      * This is true where srgb_color > 0.04045.
6305      */
6306     IDirect3D9 *d3d = NULL;
6307     HRESULT hr;
6308     LPDIRECT3DTEXTURE9 texture = NULL;
6309     LPDIRECT3DSURFACE9 surface = NULL;
6310     D3DLOCKED_RECT lr;
6311     DWORD color;
6312     float quad[] = {
6313         -1.0,       1.0,       0.0,     0.0,    0.0,
6314          1.0,       1.0,       0.0,     1.0,    0.0,
6315         -1.0,      -1.0,       0.0,     0.0,    1.0,
6316          1.0,      -1.0,       0.0,     1.0,    1.0,
6317     };
6318
6319
6320     memset(&lr, 0, sizeof(lr));
6321     IDirect3DDevice9_GetDirect3D(device, &d3d);
6322     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6323                                     D3DUSAGE_QUERY_SRGBREAD, D3DRTYPE_TEXTURE,
6324                                     D3DFMT_A8R8G8B8) != D3D_OK) {
6325         skip("D3DFMT_A8R8G8B8 textures with SRGBREAD not supported\n");
6326         goto out;
6327     }
6328
6329     hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, 0,
6330                                         D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
6331                                         &texture, NULL);
6332     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %s\n", DXGetErrorString9(hr));
6333     if(!texture) {
6334         skip("Failed to create A8R8G8B8 texture with SRGBREAD\n");
6335         goto out;
6336     }
6337     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
6338     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %s\n", DXGetErrorString9(hr));
6339
6340     fill_surface(surface, 0xff7f7f7f);
6341     IDirect3DSurface9_Release(surface);
6342
6343     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
6344     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
6345     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
6346     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
6347
6348     hr = IDirect3DDevice9_BeginScene(device);
6349     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
6350     if(SUCCEEDED(hr))
6351     {
6352         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, TRUE);
6353         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
6354
6355         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
6356         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
6357
6358
6359         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
6360         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
6361
6362         hr = IDirect3DDevice9_EndScene(device);
6363         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
6364     }
6365
6366     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6367     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
6368     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, FALSE);
6369     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
6370
6371     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6372     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
6373
6374     color = getPixelColor(device, 320, 240);
6375     ok(color == 0x00363636 || color == 0x00373737, "srgb quad has color %08x, expected 0x00363636\n", color);
6376
6377 out:
6378     if(texture) IDirect3DTexture9_Release(texture);
6379     IDirect3D9_Release(d3d);
6380 }
6381
6382 /* Return true if color is near the expected value */
6383 static int color_near(DWORD color, DWORD expected)
6384 {
6385     const BYTE slop = 2;
6386
6387     BYTE r, g, b;
6388     BYTE rx, gx, bx;
6389     r = (color & 0x00ff0000) >> 16;
6390     g = (color & 0x0000ff00) >>  8;
6391     b = (color & 0x000000ff);
6392     rx = (expected & 0x00ff0000) >> 16;
6393     gx = (expected & 0x0000ff00) >>  8;
6394     bx = (expected & 0x000000ff);
6395
6396     return
6397       ((r >= (rx - slop)) && (r <= (rx + slop))) &&
6398       ((g >= (gx - slop)) && (g <= (gx + slop))) &&
6399       ((b >= (bx - slop)) && (b <= (bx + slop)));
6400 }
6401
6402 static void shademode_test(IDirect3DDevice9 *device)
6403 {
6404     /* Render a quad and try all of the different fixed function shading models. */
6405     HRESULT hr;
6406     DWORD color0, color1;
6407     DWORD color0_gouraud = 0, color1_gouraud = 0;
6408     DWORD shademode = D3DSHADE_FLAT;
6409     DWORD primtype = D3DPT_TRIANGLESTRIP;
6410     LPVOID data = NULL;
6411     LPDIRECT3DVERTEXBUFFER9 vb_strip = NULL;
6412     LPDIRECT3DVERTEXBUFFER9 vb_list = NULL;
6413     UINT i, j;
6414     struct vertex quad_strip[] =
6415     {
6416         {-1.0f, -1.0f,  0.0f, 0xffff0000  },
6417         {-1.0f,  1.0f,  0.0f, 0xff00ff00  },
6418         { 1.0f, -1.0f,  0.0f, 0xff0000ff  },
6419         { 1.0f,  1.0f,  0.0f, 0xffffffff  }
6420     };
6421     struct vertex quad_list[] =
6422     {
6423         {-1.0f, -1.0f,  0.0f, 0xffff0000  },
6424         {-1.0f,  1.0f,  0.0f, 0xff00ff00  },
6425         { 1.0f, -1.0f,  0.0f, 0xff0000ff  },
6426
6427         {-1.0f,  1.0f,  0.0f, 0xff00ff00  },
6428         { 1.0f, -1.0f,  0.0f, 0xff0000ff  },
6429         { 1.0f,  1.0f,  0.0f, 0xffffffff  }
6430     };
6431
6432     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad_strip),
6433                                              0, 0, D3DPOOL_MANAGED, &vb_strip, NULL);
6434     ok(hr == D3D_OK, "CreateVertexBuffer failed with %s\n", DXGetErrorString9(hr));
6435     if (FAILED(hr)) goto bail;
6436
6437     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad_list),
6438                                              0, 0, D3DPOOL_MANAGED, &vb_list, NULL);
6439     ok(hr == D3D_OK, "CreateVertexBuffer failed with %s\n", DXGetErrorString9(hr));
6440     if (FAILED(hr)) goto bail;
6441
6442     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
6443     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
6444
6445     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
6446     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
6447
6448     hr = IDirect3DVertexBuffer9_Lock(vb_strip, 0, sizeof(quad_strip), (void **) &data, 0);
6449     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
6450     memcpy(data, quad_strip, sizeof(quad_strip));
6451     hr = IDirect3DVertexBuffer9_Unlock(vb_strip);
6452     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr));
6453
6454     hr = IDirect3DVertexBuffer9_Lock(vb_list, 0, sizeof(quad_list), (void **) &data, 0);
6455     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
6456     memcpy(data, quad_list, sizeof(quad_list));
6457     hr = IDirect3DVertexBuffer9_Unlock(vb_list);
6458     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr));
6459
6460     /* Try it first with a TRIANGLESTRIP.  Do it with different geometry because
6461      * the color fixups we have to do for FLAT shading will be dependent on that. */
6462     hr = IDirect3DDevice9_SetStreamSource(device, 0, vb_strip, 0, sizeof(quad_strip[0]));
6463     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr));
6464
6465     /* First loop uses a TRIANGLESTRIP geometry, 2nd uses a TRIANGLELIST */
6466     for (j=0; j<2; j++) {
6467
6468         /* Inner loop just changes the D3DRS_SHADEMODE */
6469         for (i=0; i<3; i++) {
6470             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
6471             ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
6472
6473             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SHADEMODE, shademode);
6474             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
6475
6476             hr = IDirect3DDevice9_BeginScene(device);
6477             ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
6478             if(SUCCEEDED(hr))
6479             {
6480                 hr = IDirect3DDevice9_DrawPrimitive(device, primtype, 0, 2);
6481                 ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed with %s\n", DXGetErrorString9(hr));
6482
6483                 hr = IDirect3DDevice9_EndScene(device);
6484                 ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
6485             }
6486
6487             hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6488             ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
6489
6490             /* Sample two spots from the output */
6491             color0 = getPixelColor(device, 100, 100); /* Inside first triangle */
6492             color1 = getPixelColor(device, 500, 350); /* Inside second triangle */
6493             switch(shademode) {
6494                 case D3DSHADE_FLAT:
6495                     /* Should take the color of the first vertex of each triangle */
6496                     todo_wine ok(color0 == 0x00ff0000, "FLAT shading has color0 %08x, expected 0x00ff0000 (todo)\n", color0);
6497                     todo_wine ok(color1 == 0x0000ff00, "FLAT shading has color1 %08x, expected 0x0000ff00 (todo)\n", color1);
6498                     shademode = D3DSHADE_GOURAUD;
6499                     break;
6500                 case D3DSHADE_GOURAUD:
6501                     /* Should be an interpolated blend */
6502
6503                     ok(color_near(color0, 0x000dca28),
6504                        "GOURAUD shading has color0 %08x, expected 0x00dca28\n", color0);
6505                     ok(color_near(color1, 0x000d45c7),
6506                        "GOURAUD shading has color1 %08x, expected 0x000d45c7\n", color1);
6507
6508                     color0_gouraud = color0;
6509                     color1_gouraud = color1;
6510
6511                     shademode = D3DSHADE_PHONG;
6512                     break;
6513                 case D3DSHADE_PHONG:
6514                     /* Should be the same as GOURAUD, since no hardware implements this */
6515                     ok(color_near(color0, 0x000dca28),
6516                        "PHONG shading has color0 %08x, expected 0x000dca28\n", color0);
6517                     ok(color_near(color1, 0x000d45c7),
6518                        "PHONG shading has color1 %08x, expected 0x000d45c7\n", color1);
6519
6520                     ok(color0 == color0_gouraud, "difference between GOURAUD and PHONG shading detected: %08x %08x\n",
6521                             color0_gouraud, color0);
6522                     ok(color1 == color1_gouraud, "difference between GOURAUD and PHONG shading detected: %08x %08x\n",
6523                             color1_gouraud, color1);
6524                     break;
6525             }
6526         }
6527         /* Now, do it all over again with a TRIANGLELIST */
6528         hr = IDirect3DDevice9_SetStreamSource(device, 0, vb_list, 0, sizeof(quad_list[0]));
6529         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr));
6530         primtype = D3DPT_TRIANGLELIST;
6531         shademode = D3DSHADE_FLAT;
6532     }
6533
6534 bail:
6535     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
6536     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr));
6537     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
6538     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
6539
6540     if (vb_strip)
6541         IDirect3DVertexBuffer9_Release(vb_strip);
6542     if (vb_list)
6543         IDirect3DVertexBuffer9_Release(vb_list);
6544 }
6545
6546
6547 static void fog_srgbwrite_test(IDirect3DDevice9 *device)
6548 {
6549     /* Draw a black quad, half fogged with white fog -> grey color. Enable sRGB writing.
6550      * if sRGB writing is applied before fogging, the 0.0 will be multiplied with ~ 12.92, so still
6551      * stay 0.0. After that the fog gives 0.5. If sRGB writing is applied after fogging, the
6552      * 0.5 will run through the alternative path(0^5 ^ 0.41666 * 1.055 - 0.055), resulting in approx.
6553      * 0.73
6554      *
6555      * At the time of this writing, wined3d could not apply sRGB correction to fixed function rendering,
6556      * so use shaders for this task
6557      */
6558     IDirect3DPixelShader9 *pshader;
6559     IDirect3DVertexShader9 *vshader;
6560     IDirect3D9 *d3d;
6561     DWORD vshader_code[] = {
6562         0xfffe0101,                                                             /* vs_1_1                       */
6563         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
6564         0x00000051, 0xa00f0000, 0x3f000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.5, 0.0, 0.0, 0.0   */
6565         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
6566         0x00000001, 0xc00f0001, 0xa0000000,                                     /* mov oFog, c0.x               */
6567         0x0000ffff                                                              /* end                          */
6568     };
6569     DWORD pshader_code[] = {
6570         0xffff0101,                                                             /* ps_1_1                       */
6571         0x00000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0   */
6572         0x00000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                   */
6573         0x0000ffff                                                              /* end                          */
6574     };
6575     const float quad[] = {
6576        -1.0,   -1.0,    0.1,
6577         1.0,   -1.0,    0.1,
6578        -1.0,    1.0,    0.1,
6579         1.0,    1.0,    0.1
6580     };
6581     HRESULT hr;
6582     DWORD color;
6583
6584     IDirect3DDevice9_GetDirect3D(device, &d3d);
6585     /* Ask for srgb writing on D3DRTYPE_TEXTURE. Some Windows drivers do not report it on surfaces.
6586      * For some not entirely understood reasons D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE
6587      * passes on surfaces, while asking for SRGBWRITE alone fails. Textures advertize srgb writing
6588      * alone as well, so use that since it is not the point of this test to show how CheckDeviceFormat
6589      * works
6590      */
6591     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
6592                                     D3DUSAGE_RENDERTARGET | D3DUSAGE_QUERY_SRGBWRITE,
6593                                     D3DRTYPE_TEXTURE, D3DFMT_A8R8G8B8) != D3D_OK) {
6594         skip("No SRGBWRITEENABLE support on D3DFMT_X8R8G8B8\n");
6595         IDirect3D9_Release(d3d);
6596         return;
6597     }
6598     IDirect3D9_Release(d3d);
6599
6600     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
6601     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
6602
6603     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
6604     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
6605     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
6606     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
6607     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
6608     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
6609     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xffffffff);
6610     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
6611     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, TRUE);
6612     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
6613
6614     hr = IDirect3DDevice9_CreateVertexShader(device, vshader_code, &vshader);
6615     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexShader returned %s\n", DXGetErrorString9(hr));
6616     hr = IDirect3DDevice9_CreatePixelShader(device, pshader_code, &pshader);
6617     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
6618     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
6619     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
6620     hr = IDirect3DDevice9_SetVertexShader(device, vshader);
6621     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
6622     hr = IDirect3DDevice9_SetPixelShader(device, pshader);
6623     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
6624
6625     hr = IDirect3DDevice9_BeginScene(device);
6626     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
6627     if(SUCCEEDED(hr)) {
6628         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 3);
6629         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
6630
6631         hr = IDirect3DDevice9_EndScene(device);
6632         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
6633     }
6634
6635     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
6636     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
6637     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
6638     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
6639     IDirect3DPixelShader9_Release(pshader);
6640     IDirect3DVertexShader9_Release(vshader);
6641
6642     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
6643     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
6644     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRGBWRITEENABLE, FALSE);
6645     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
6646
6647     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6648     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
6649     color = getPixelColor(device, 160, 360);
6650     ok(color == 0x00808080 || color == 0x007f7f7f || color == 0x00818181,
6651        "Fog with D3DRS_SRGBWRITEENABLE returned color 0x%08x, expected 0x00808080\n", color);
6652 }
6653
6654 static void alpha_test(IDirect3DDevice9 *device)
6655 {
6656     HRESULT hr;
6657     IDirect3DTexture9 *offscreenTexture;
6658     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
6659     DWORD color, red, green, blue;
6660
6661     struct vertex quad1[] =
6662     {
6663         {-1.0f, -1.0f,   0.1f,                          0x4000ff00},
6664         {-1.0f,  0.0f,   0.1f,                          0x4000ff00},
6665         { 1.0f, -1.0f,   0.1f,                          0x4000ff00},
6666         { 1.0f,  0.0f,   0.1f,                          0x4000ff00},
6667     };
6668     struct vertex quad2[] =
6669     {
6670         {-1.0f,  0.0f,   0.1f,                          0xc00000ff},
6671         {-1.0f,  1.0f,   0.1f,                          0xc00000ff},
6672         { 1.0f,  0.0f,   0.1f,                          0xc00000ff},
6673         { 1.0f,  1.0f,   0.1f,                          0xc00000ff},
6674     };
6675     static const float composite_quad[][5] = {
6676         { 0.0f, -1.0f, 0.1f, 0.0f, 1.0f},
6677         { 0.0f,  1.0f, 0.1f, 0.0f, 0.0f},
6678         { 1.0f, -1.0f, 0.1f, 1.0f, 1.0f},
6679         { 1.0f,  1.0f, 0.1f, 1.0f, 0.0f},
6680     };
6681
6682     /* Clear the render target with alpha = 0.5 */
6683     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
6684     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
6685
6686     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
6687     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr);
6688
6689     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
6690     ok(hr == D3D_OK, "Can't get back buffer, hr = %s\n", DXGetErrorString9(hr));
6691     if(!backbuffer) {
6692         goto out;
6693     }
6694
6695     hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
6696     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %s\n", DXGetErrorString9(hr));
6697     if(!offscreen) {
6698         goto out;
6699     }
6700
6701     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
6702     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr);
6703
6704     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
6705     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
6706     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
6707     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
6708     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
6709     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
6710     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
6711     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
6712     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
6713     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
6714
6715     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
6716     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6717     if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
6718
6719         /* Draw two quads, one with src alpha blending, one with dest alpha blending. */
6720         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
6721         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6722         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
6723         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6724         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
6725         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6726
6727         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
6728         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6729         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
6730         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6731         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
6732         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6733
6734         /* Switch to the offscreen buffer, and redo the testing. The offscreen render target
6735          * doesn't have an alpha channel. DESTALPHA and INVDESTALPHA "don't work" on render
6736          * targets without alpha channel, they give essentially ZERO and ONE blend factors. */
6737         hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
6738         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
6739         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
6740         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
6741
6742         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
6743         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6744         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
6745         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6746         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
6747         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6748
6749         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
6750         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6751         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
6752         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6753         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
6754         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6755
6756         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
6757         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
6758
6759         /* Render the offscreen texture onto the frame buffer to be able to compare it regularly.
6760          * Disable alpha blending for the final composition
6761          */
6762         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
6763         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
6764         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
6765         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %#08x\n", hr);
6766
6767         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
6768         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr = %08x\n", hr);
6769         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, composite_quad, sizeof(float) * 5);
6770         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6771         hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
6772         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr = %08x\n", hr);
6773
6774         hr = IDirect3DDevice9_EndScene(device);
6775         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
6776     }
6777
6778     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
6779
6780     color = getPixelColor(device, 160, 360);
6781     red =   (color & 0x00ff0000) >> 16;
6782     green = (color & 0x0000ff00) >>  8;
6783     blue =  (color & 0x000000ff);
6784     ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
6785        "SRCALPHA on frame buffer returned color %08x, expected 0x00bf4000\n", color);
6786
6787     color = getPixelColor(device, 160, 120);
6788     red =   (color & 0x00ff0000) >> 16;
6789     green = (color & 0x0000ff00) >>  8;
6790     blue =  (color & 0x000000ff);
6791     ok(red >= 0x7e && red <= 0x81 && green == 0x00 && blue >= 0x7e && blue <= 0x81,
6792        "DSTALPHA on frame buffer returned color %08x, expected 0x00ff0000\n", color);
6793
6794     color = getPixelColor(device, 480, 360);
6795     red =   (color & 0x00ff0000) >> 16;
6796     green = (color & 0x0000ff00) >>  8;
6797     blue =  (color & 0x000000ff);
6798     ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
6799        "SRCALPHA on texture returned color %08x, expected bar\n", color);
6800
6801     color = getPixelColor(device, 480, 120);
6802     red =   (color & 0x00ff0000) >> 16;
6803     green = (color & 0x0000ff00) >>  8;
6804     blue =  (color & 0x000000ff);
6805     ok(red == 0x00 && green == 0x00 && blue >= 0xfe && blue <= 0xff ,
6806        "DSTALPHA on texture returned color %08x, expected 0x00800080\n", color);
6807
6808     out:
6809     /* restore things */
6810     if(backbuffer) {
6811         IDirect3DSurface9_Release(backbuffer);
6812     }
6813     if(offscreenTexture) {
6814         IDirect3DTexture9_Release(offscreenTexture);
6815     }
6816     if(offscreen) {
6817         IDirect3DSurface9_Release(offscreen);
6818     }
6819 }
6820
6821 struct vertex_shortcolor {
6822     float x, y, z;
6823     unsigned short r, g, b, a;
6824 };
6825 struct vertex_floatcolor {
6826     float x, y, z;
6827     float r, g, b, a;
6828 };
6829
6830 static void fixed_function_decl_test(IDirect3DDevice9 *device)
6831 {
6832     HRESULT hr;
6833     BOOL s_ok, ub_ok, f_ok;
6834     DWORD color, size, i;
6835     void *data;
6836     static const D3DVERTEXELEMENT9 decl_elements_d3dcolor[] = {
6837         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6838         {0,  12,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6839         D3DDECL_END()
6840     };
6841     static const D3DVERTEXELEMENT9 decl_elements_d3dcolor_2streams[] = {
6842         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6843         {1,   0,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6844         D3DDECL_END()
6845     };
6846     static const D3DVERTEXELEMENT9 decl_elements_ubyte4n[] = {
6847         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6848         {0,  12,  D3DDECLTYPE_UBYTE4N,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6849         D3DDECL_END()
6850     };
6851     static const D3DVERTEXELEMENT9 decl_elements_ubyte4n_2streams[] = {
6852         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6853         {1,   0,  D3DDECLTYPE_UBYTE4N,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6854         D3DDECL_END()
6855     };
6856     static const D3DVERTEXELEMENT9 decl_elements_short4[] = {
6857         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6858         {0,  12,  D3DDECLTYPE_USHORT4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6859         D3DDECL_END()
6860     };
6861     static const D3DVERTEXELEMENT9 decl_elements_float[] = {
6862         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
6863         {0,  12,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6864         D3DDECL_END()
6865     };
6866     static const D3DVERTEXELEMENT9 decl_elements_positiont[] = {
6867         {0,   0,  D3DDECLTYPE_FLOAT4,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITIONT,      0},
6868         {0,  16,  D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
6869         D3DDECL_END()
6870     };
6871     IDirect3DVertexDeclaration9 *dcl_float = NULL, *dcl_short = NULL, *dcl_ubyte = NULL, *dcl_color = NULL;
6872     IDirect3DVertexDeclaration9 *dcl_color_2 = NULL, *dcl_ubyte_2 = NULL, *dcl_positiont;
6873     IDirect3DVertexBuffer9 *vb, *vb2;
6874     struct vertex quad1[] =                             /* D3DCOLOR */
6875     {
6876         {-1.0f, -1.0f,   0.1f,                          0x00ffff00},
6877         {-1.0f,  0.0f,   0.1f,                          0x00ffff00},
6878         { 0.0f, -1.0f,   0.1f,                          0x00ffff00},
6879         { 0.0f,  0.0f,   0.1f,                          0x00ffff00},
6880     };
6881     struct vertex quad2[] =                             /* UBYTE4N */
6882     {
6883         {-1.0f,  0.0f,   0.1f,                          0x00ffff00},
6884         {-1.0f,  1.0f,   0.1f,                          0x00ffff00},
6885         { 0.0f,  0.0f,   0.1f,                          0x00ffff00},
6886         { 0.0f,  1.0f,   0.1f,                          0x00ffff00},
6887     };
6888     struct vertex_shortcolor quad3[] =                  /* short */
6889     {
6890         { 0.0f, -1.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
6891         { 0.0f,  0.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
6892         { 1.0f, -1.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
6893         { 1.0f,  0.0f,   0.1f,                          0x0000, 0x0000, 0xffff, 0xffff},
6894     };
6895     struct vertex_floatcolor quad4[] =
6896     {
6897         { 0.0f,  0.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
6898         { 0.0f,  1.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
6899         { 1.0f,  0.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
6900         { 1.0f,  1.0f,   0.1f,                          1.0, 0.0, 0.0, 0.0},
6901     };
6902     DWORD colors[] = {
6903         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6904         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6905         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6906         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6907         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6908         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6909         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6910         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6911         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6912         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6913         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6914         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6915         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6916         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6917         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6918         0x00ff0000,   0x0000ff00,     0x000000ff,   0x00ffffff,
6919     };
6920     float quads[] = {
6921         -1.0,   -1.0,     0.1,
6922         -1.0,    0.0,     0.1,
6923          0.0,   -1.0,     0.1,
6924          0.0,    0.0,     0.1,
6925
6926          0.0,   -1.0,     0.1,
6927          0.0,    0.0,     0.1,
6928          1.0,   -1.0,     0.1,
6929          1.0,    0.0,     0.1,
6930
6931          0.0,    0.0,     0.1,
6932          0.0,    1.0,     0.1,
6933          1.0,    0.0,     0.1,
6934          1.0,    1.0,     0.1,
6935
6936         -1.0,    0.0,     0.1,
6937         -1.0,    1.0,     0.1,
6938          0.0,    0.0,     0.1,
6939          0.0,    1.0,     0.1
6940     };
6941     struct tvertex quad_transformed[] = {
6942        {  90,    110,     0.1,      2.0,        0x00ffff00},
6943        { 570,    110,     0.1,      2.0,        0x00ffff00},
6944        {  90,    300,     0.1,      2.0,        0x00ffff00},
6945        { 570,    300,     0.1,      2.0,        0x00ffff00}
6946     };
6947     D3DCAPS9 caps;
6948
6949     memset(&caps, 0, sizeof(caps));
6950     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
6951     ok(hr == D3D_OK, "GetDeviceCaps failed, hr = %08x\n", hr);
6952
6953     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
6954     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
6955
6956     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_d3dcolor, &dcl_color);
6957     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
6958     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_short4, &dcl_short);
6959     ok(SUCCEEDED(hr) || hr == E_FAIL, "CreateVertexDeclaration failed (%08x)\n", hr);
6960     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_float, &dcl_float);
6961     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
6962     if(caps.DeclTypes & D3DDTCAPS_UBYTE4N) {
6963         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_ubyte4n_2streams, &dcl_ubyte_2);
6964         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
6965         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_ubyte4n, &dcl_ubyte);
6966         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
6967     } else {
6968         trace("D3DDTCAPS_UBYTE4N not supported\n");
6969         dcl_ubyte_2 = NULL;
6970         dcl_ubyte = NULL;
6971     }
6972     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_d3dcolor_2streams, &dcl_color_2);
6973     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
6974     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements_positiont, &dcl_positiont);
6975     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
6976
6977     size = max(sizeof(quad1), max(sizeof(quad2), max(sizeof(quad3), max(sizeof(quad4), sizeof(quads)))));
6978     hr = IDirect3DDevice9_CreateVertexBuffer(device, size,
6979                                              0, 0, D3DPOOL_MANAGED, &vb, NULL);
6980     ok(hr == D3D_OK, "CreateVertexBuffer failed with %s\n", DXGetErrorString9(hr));
6981
6982     hr = IDirect3DDevice9_BeginScene(device);
6983     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
6984     f_ok = FALSE; s_ok = FALSE; ub_ok = FALSE;
6985     if(SUCCEEDED(hr)) {
6986         if(dcl_color) {
6987             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color);
6988             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
6989             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
6990             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
6991         }
6992
6993         /* Tests with non-standard fixed function types fail on the refrast. The ATI driver partially
6994          * accepts them, the nvidia driver accepts them all. All those differences even though we're
6995          * using software vertex processing. Doh!
6996          */
6997         if(dcl_ubyte) {
6998             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte);
6999             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7000             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
7001             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7002             ub_ok = SUCCEEDED(hr);
7003         }
7004
7005         if(dcl_short) {
7006             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_short);
7007             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7008             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(quad3[0]));
7009             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7010             s_ok = SUCCEEDED(hr);
7011         }
7012
7013         if(dcl_float) {
7014             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_float);
7015             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7016             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(quad4[0]));
7017             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
7018             f_ok = SUCCEEDED(hr);
7019         }
7020
7021         hr = IDirect3DDevice9_EndScene(device);
7022         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr = %#08x\n", hr);
7023     }
7024
7025     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7026     if(dcl_short) {
7027         color = getPixelColor(device, 480, 360);
7028         ok(color == 0x000000ff || !s_ok,
7029            "D3DDECLTYPE_USHORT4N returned color %08x, expected 0x000000ff\n", color);
7030     }
7031     if(dcl_ubyte) {
7032         color = getPixelColor(device, 160, 120);
7033         ok(color == 0x0000ffff || !ub_ok,
7034            "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x0000ffff\n", color);
7035     }
7036     if(dcl_color) {
7037         color = getPixelColor(device, 160, 360);
7038         ok(color == 0x00ffff00,
7039            "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ffff00\n", color);
7040     }
7041     if(dcl_float) {
7042         color = getPixelColor(device, 480, 120);
7043         ok(color == 0x00ff0000 || !f_ok,
7044            "D3DDECLTYPE_FLOAT4 returned color %08x, expected 0x00ff0000\n", color);
7045     }
7046
7047     /* The following test with vertex buffers doesn't serve to find out new information from windows.
7048      * It is a plain regression test because wined3d uses different codepaths for attribute conversion
7049      * with vertex buffers. It makes sure that the vertex buffer one works, while the above tests
7050      * whether the immediate mode code works
7051      */
7052     f_ok = FALSE; s_ok = FALSE; ub_ok = FALSE;
7053     hr = IDirect3DDevice9_BeginScene(device);
7054     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
7055     if(SUCCEEDED(hr)) {
7056         if(dcl_color) {
7057             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad1), (void **) &data, 0);
7058             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
7059             memcpy(data, quad1, sizeof(quad1));
7060             hr = IDirect3DVertexBuffer9_Unlock(vb);
7061             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7062             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color);
7063             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7064             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad1[0]));
7065             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr));
7066             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7067             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7068         }
7069
7070         if(dcl_ubyte) {
7071             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad2), (void **) &data, 0);
7072             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
7073             memcpy(data, quad2, sizeof(quad2));
7074             hr = IDirect3DVertexBuffer9_Unlock(vb);
7075             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7076             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte);
7077             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7078             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad2[0]));
7079             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr));
7080             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7081             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7082                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7083             ub_ok = SUCCEEDED(hr);
7084         }
7085
7086         if(dcl_short) {
7087             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad3), (void **) &data, 0);
7088             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
7089             memcpy(data, quad3, sizeof(quad3));
7090             hr = IDirect3DVertexBuffer9_Unlock(vb);
7091             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7092             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_short);
7093             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7094             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad3[0]));
7095             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr));
7096             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7097             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7098                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7099             s_ok = SUCCEEDED(hr);
7100         }
7101
7102         if(dcl_float) {
7103             hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad4), (void **) &data, 0);
7104             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
7105             memcpy(data, quad4, sizeof(quad4));
7106             hr = IDirect3DVertexBuffer9_Unlock(vb);
7107             ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7108             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_float);
7109             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7110             hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad4[0]));
7111             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr));
7112             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7113             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7114                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7115             f_ok = SUCCEEDED(hr);
7116         }
7117
7118         hr = IDirect3DDevice9_EndScene(device);
7119         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr = %#08x\n", hr);
7120     }
7121
7122     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
7123     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr));
7124     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
7125     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed (%08x)\n", hr);
7126
7127     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7128     if(dcl_short) {
7129         color = getPixelColor(device, 480, 360);
7130         ok(color == 0x000000ff || !s_ok,
7131            "D3DDECLTYPE_USHORT4N returned color %08x, expected 0x000000ff\n", color);
7132     }
7133     if(dcl_ubyte) {
7134         color = getPixelColor(device, 160, 120);
7135         ok(color == 0x0000ffff || !ub_ok,
7136            "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x0000ffff\n", color);
7137     }
7138     if(dcl_color) {
7139         color = getPixelColor(device, 160, 360);
7140         ok(color == 0x00ffff00,
7141            "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ffff00\n", color);
7142     }
7143     if(dcl_float) {
7144         color = getPixelColor(device, 480, 120);
7145         ok(color == 0x00ff0000 || !f_ok,
7146            "D3DDECLTYPE_FLOAT4 returned color %08x, expected 0x00ff0000\n", color);
7147     }
7148
7149     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
7150     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
7151
7152     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad_transformed), (void **) &data, 0);
7153     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
7154     memcpy(data, quad_transformed, sizeof(quad_transformed));
7155     hr = IDirect3DVertexBuffer9_Unlock(vb);
7156     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7157
7158     hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_positiont);
7159     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
7160
7161     hr = IDirect3DDevice9_BeginScene(device);
7162     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
7163     if(SUCCEEDED(hr)) {
7164         hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad_transformed[0]));
7165         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr));
7166         hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7167         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7168
7169         hr = IDirect3DDevice9_EndScene(device);
7170         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
7171     }
7172
7173     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7174     color = getPixelColor(device, 88, 108);
7175     ok(color == 0x000000ff,
7176        "pixel 88/108 has color %08x, expected 0x000000ff\n", color);
7177     color = getPixelColor(device, 92, 108);
7178     ok(color == 0x000000ff,
7179        "pixel 92/108 has color %08x, expected 0x000000ff\n", color);
7180     color = getPixelColor(device, 88, 112);
7181     ok(color == 0x000000ff,
7182        "pixel 88/112 has color %08x, expected 0x000000ff\n", color);
7183     color = getPixelColor(device, 92, 112);
7184     ok(color == 0x00ffff00,
7185        "pixel 92/112 has color %08x, expected 0x00ffff00\n", color);
7186
7187     color = getPixelColor(device, 568, 108);
7188     ok(color == 0x000000ff,
7189        "pixel 568/108 has color %08x, expected 0x000000ff\n", color);
7190     color = getPixelColor(device, 572, 108);
7191     ok(color == 0x000000ff,
7192        "pixel 572/108 has color %08x, expected 0x000000ff\n", color);
7193     color = getPixelColor(device, 568, 112);
7194     ok(color == 0x00ffff00,
7195        "pixel 568/112 has color %08x, expected 0x00ffff00\n", color);
7196     color = getPixelColor(device, 572, 112);
7197     ok(color == 0x000000ff,
7198        "pixel 572/112 has color %08x, expected 0x000000ff\n", color);
7199
7200     color = getPixelColor(device, 88, 298);
7201     ok(color == 0x000000ff,
7202        "pixel 88/298 has color %08x, expected 0x000000ff\n", color);
7203     color = getPixelColor(device, 92, 298);
7204     ok(color == 0x00ffff00,
7205        "pixel 92/298 has color %08x, expected 0x00ffff00\n", color);
7206     color = getPixelColor(device, 88, 302);
7207     ok(color == 0x000000ff,
7208        "pixel 88/302 has color %08x, expected 0x000000ff\n", color);
7209     color = getPixelColor(device, 92, 302);
7210     ok(color == 0x000000ff,
7211        "pixel 92/302 has color %08x, expected 0x000000ff\n", color);
7212
7213     color = getPixelColor(device, 568, 298);
7214     ok(color == 0x00ffff00,
7215        "pixel 568/298 has color %08x, expected 0x00ffff00\n", color);
7216     color = getPixelColor(device, 572, 298);
7217     ok(color == 0x000000ff,
7218        "pixel 572/298 has color %08x, expected 0x000000ff\n", color);
7219     color = getPixelColor(device, 568, 302);
7220     ok(color == 0x000000ff,
7221        "pixel 568/302 has color %08x, expected 0x000000ff\n", color);
7222     color = getPixelColor(device, 572, 302);
7223     ok(color == 0x000000ff,
7224        "pixel 572/302 has color %08x, expected 0x000000ff\n", color);
7225
7226     /* This test is pointless without those two declarations: */
7227     if((!dcl_color_2) || (!dcl_ubyte_2)) {
7228         skip("color-ubyte switching test declarations aren't supported\n");
7229         goto out;
7230     }
7231
7232     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quads), (void **) &data, 0);
7233     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
7234     memcpy(data, quads, sizeof(quads));
7235     hr = IDirect3DVertexBuffer9_Unlock(vb);
7236     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7237     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(colors),
7238                                              0, 0, D3DPOOL_MANAGED, &vb2, NULL);
7239     ok(hr == D3D_OK, "CreateVertexBuffer failed with %s\n", DXGetErrorString9(hr));
7240     hr = IDirect3DVertexBuffer9_Lock(vb2, 0, sizeof(colors), (void **) &data, 0);
7241     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
7242     memcpy(data, colors, sizeof(colors));
7243     hr = IDirect3DVertexBuffer9_Unlock(vb2);
7244     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed (%08x)\n", hr);
7245
7246     for(i = 0; i < 2; i++) {
7247         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
7248         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
7249
7250         hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(float) * 3);
7251         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr));
7252         if(i == 0) {
7253             hr = IDirect3DDevice9_SetStreamSource(device, 1, vb2, 0, sizeof(DWORD) * 4);
7254         } else {
7255             hr = IDirect3DDevice9_SetStreamSource(device, 1, vb2, 8, sizeof(DWORD) * 4);
7256         }
7257         ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr));
7258
7259         hr = IDirect3DDevice9_BeginScene(device);
7260         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
7261         ub_ok = FALSE;
7262         if(SUCCEEDED(hr)) {
7263             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2);
7264             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
7265             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2);
7266             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7267                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7268             ub_ok = SUCCEEDED(hr);
7269
7270             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_color_2);
7271             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
7272             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 4, 2);
7273             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7274
7275             hr = IDirect3DDevice9_SetVertexDeclaration(device, dcl_ubyte_2);
7276             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
7277             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 8, 2);
7278             ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
7279                "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7280             ub_ok = (SUCCEEDED(hr) && ub_ok);
7281
7282             hr = IDirect3DDevice9_EndScene(device);
7283             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
7284         }
7285
7286         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7287         if(i == 0) {
7288             color = getPixelColor(device, 480, 360);
7289             ok(color == 0x00ff0000,
7290                "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x00ff0000\n", color);
7291             color = getPixelColor(device, 160, 120);
7292             ok(color == 0x00ffffff,
7293                 "Unused quad returned color %08x, expected 0x00ffffff\n", color);
7294             color = getPixelColor(device, 160, 360);
7295             ok(color == 0x000000ff || !ub_ok,
7296                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x000000ff\n", color);
7297             color = getPixelColor(device, 480, 120);
7298             ok(color == 0x000000ff || !ub_ok,
7299                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x000000ff\n", color);
7300         } else {
7301             color = getPixelColor(device, 480, 360);
7302             ok(color == 0x000000ff,
7303                "D3DDECLTYPE_D3DCOLOR returned color %08x, expected 0x000000ff\n", color);
7304             color = getPixelColor(device, 160, 120);
7305             ok(color == 0x00ffffff,
7306                "Unused quad returned color %08x, expected 0x00ffffff\n", color);
7307             color = getPixelColor(device, 160, 360);
7308             ok(color == 0x00ff0000 || !ub_ok,
7309                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x00ff0000\n", color);
7310             color = getPixelColor(device, 480, 120);
7311             ok(color == 0x00ff0000 || !ub_ok,
7312                "D3DDECLTYPE_UBYTE4N returned color %08x, expected 0x00ff0000\n", color);
7313         }
7314     }
7315
7316     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
7317     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr));
7318     hr = IDirect3DDevice9_SetStreamSource(device, 1, NULL, 0, 0);
7319     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %s\n", DXGetErrorString9(hr));
7320     IDirect3DVertexBuffer9_Release(vb2);
7321
7322     out:
7323     IDirect3DVertexBuffer9_Release(vb);
7324     if(dcl_float) IDirect3DVertexDeclaration9_Release(dcl_float);
7325     if(dcl_short) IDirect3DVertexDeclaration9_Release(dcl_short);
7326     if(dcl_ubyte) IDirect3DVertexDeclaration9_Release(dcl_ubyte);
7327     if(dcl_color) IDirect3DVertexDeclaration9_Release(dcl_color);
7328     if(dcl_color_2) IDirect3DVertexDeclaration9_Release(dcl_color_2);
7329     if(dcl_ubyte_2) IDirect3DVertexDeclaration9_Release(dcl_ubyte_2);
7330     if(dcl_positiont) IDirect3DVertexDeclaration9_Release(dcl_positiont);
7331 }
7332
7333 struct vertex_float16color {
7334     float x, y, z;
7335     DWORD c1, c2;
7336 };
7337
7338 static void test_vshader_float16(IDirect3DDevice9 *device)
7339 {
7340     HRESULT hr;
7341     DWORD color;
7342     void *data;
7343     static const D3DVERTEXELEMENT9 decl_elements[] = {
7344         {0,   0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,       0},
7345         {0,  12,  D3DDECLTYPE_FLOAT16_4,D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,          0},
7346         D3DDECL_END()
7347     };
7348     IDirect3DVertexDeclaration9 *vdecl = NULL;
7349     IDirect3DVertexBuffer9 *buffer = NULL;
7350     IDirect3DVertexShader9 *shader;
7351     DWORD shader_code[] = {
7352         0xfffe0101, 0x0000001f, 0x80000000, 0x900f0000, 0x0000001f, 0x8000000a,
7353         0x900f0001, 0x00000001, 0xc00f0000, 0x90e40000, 0x00000001, 0xd00f0000,
7354         0x90e40001, 0x0000ffff
7355     };
7356     struct vertex_float16color quad[] = {
7357         { -1.0,   -1.0,     0.1,        0x3c000000, 0x00000000 }, /* green */
7358         { -1.0,    0.0,     0.1,        0x3c000000, 0x00000000 },
7359         {  0.0,   -1.0,     0.1,        0x3c000000, 0x00000000 },
7360         {  0.0,    0.0,     0.1,        0x3c000000, 0x00000000 },
7361
7362         {  0.0,   -1.0,     0.1,        0x00003c00, 0x00000000 }, /* red */
7363         {  0.0,    0.0,     0.1,        0x00003c00, 0x00000000 },
7364         {  1.0,   -1.0,     0.1,        0x00003c00, 0x00000000 },
7365         {  1.0,    0.0,     0.1,        0x00003c00, 0x00000000 },
7366
7367         {  0.0,    0.0,     0.1,        0x00000000, 0x00003c00 }, /* blue */
7368         {  0.0,    1.0,     0.1,        0x00000000, 0x00003c00 },
7369         {  1.0,    0.0,     0.1,        0x00000000, 0x00003c00 },
7370         {  1.0,    1.0,     0.1,        0x00000000, 0x00003c00 },
7371
7372         { -1.0,    0.0,     0.1,        0x00000000, 0x3c000000 }, /* alpha */
7373         { -1.0,    1.0,     0.1,        0x00000000, 0x3c000000 },
7374         {  0.0,    0.0,     0.1,        0x00000000, 0x3c000000 },
7375         {  0.0,    1.0,     0.1,        0x00000000, 0x3c000000 },
7376     };
7377
7378     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff102030, 0.0, 0);
7379     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%s\n", DXGetErrorString9(hr));
7380
7381     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vdecl);
7382     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed hr=%s\n", DXGetErrorString9(hr));
7383     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
7384     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexShader failed hr=%s\n", DXGetErrorString9(hr));
7385     hr = IDirect3DDevice9_SetVertexShader(device, shader);
7386     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed hr=%s\n", DXGetErrorString9(hr));
7387
7388     hr = IDirect3DDevice9_BeginScene(device);
7389     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%s\n", DXGetErrorString9(hr));
7390     if(SUCCEEDED(hr)) {
7391         hr = IDirect3DDevice9_SetVertexDeclaration(device, vdecl);
7392         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%s\n", DXGetErrorString9(hr));
7393         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad +  0, sizeof(quad[0]));
7394         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
7395         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad +  4, sizeof(quad[0]));
7396         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
7397         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad +  8, sizeof(quad[0]));
7398         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
7399         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad + 12, sizeof(quad[0]));
7400         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
7401
7402         hr = IDirect3DDevice9_EndScene(device);
7403         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%s\n", DXGetErrorString9(hr));
7404     }
7405     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7406     color = getPixelColor(device, 480, 360);
7407     ok(color == 0x00ff0000,
7408        "Input 0x00003c00, 0x00000000 returned color %08x, expected 0x00ff0000\n", color);
7409     color = getPixelColor(device, 160, 120);
7410     ok(color == 0x00000000,
7411        "Input 0x00000000, 0x3c000000 returned color %08x, expected 0x00000000\n", color);
7412     color = getPixelColor(device, 160, 360);
7413     ok(color == 0x0000ff00,
7414        "Input 0x3c000000, 0x00000000 returned color %08x, expected 0x0000ff00\n", color);
7415     color = getPixelColor(device, 480, 120);
7416     ok(color == 0x000000ff,
7417        "Input 0x00000000, 0x00003c00 returned color %08x, expected 0x000000ff\n", color);
7418
7419     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff102030, 0.0, 0);
7420     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%s\n", DXGetErrorString9(hr));
7421
7422     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0,
7423                                              D3DPOOL_MANAGED, &buffer, NULL);
7424     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexBuffer failed, hr=%s\n", DXGetErrorString9(hr));
7425     hr = IDirect3DVertexBuffer9_Lock(buffer, 0, sizeof(quad), (void **) &data, 0);
7426     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed, hr=%s\n", DXGetErrorString9(hr));
7427     memcpy(data, quad, sizeof(quad));
7428     hr = IDirect3DVertexBuffer9_Unlock(buffer);
7429     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed, hr=%s\n", DXGetErrorString9(hr));
7430     hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(quad[0]));
7431     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed, hr=%s\n", DXGetErrorString9(hr));
7432
7433     hr = IDirect3DDevice9_BeginScene(device);
7434     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
7435     if(SUCCEEDED(hr)) {
7436             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,  0, 2);
7437             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7438             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,  4, 2);
7439             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7440             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP,  8, 2);
7441             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7442             hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 12, 2);
7443             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitive failed, hr = %#08x\n", hr);
7444
7445             hr = IDirect3DDevice9_EndScene(device);
7446             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%s\n", DXGetErrorString9(hr));
7447     }
7448
7449     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7450     color = getPixelColor(device, 480, 360);
7451     ok(color == 0x00ff0000,
7452        "Input 0x00003c00, 0x00000000 returned color %08x, expected 0x00ff0000\n", color);
7453     color = getPixelColor(device, 160, 120);
7454     ok(color == 0x00000000,
7455        "Input 0x00000000, 0x3c000000 returned color %08x, expected 0x00000000\n", color);
7456     color = getPixelColor(device, 160, 360);
7457     ok(color == 0x0000ff00,
7458        "Input 0x3c000000, 0x00000000 returned color %08x, expected 0x0000ff00\n", color);
7459     color = getPixelColor(device, 480, 120);
7460     ok(color == 0x000000ff,
7461        "Input 0x00000000, 0x00003c00 returned color %08x, expected 0x000000ff\n", color);
7462
7463     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
7464     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed, hr=%s\n", DXGetErrorString9(hr));
7465     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
7466     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%s\n", DXGetErrorString9(hr));
7467     IDirect3DDevice9_SetVertexShader(device, NULL);
7468     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed hr=%s\n", DXGetErrorString9(hr));
7469
7470     IDirect3DVertexDeclaration9_Release(vdecl);
7471     IDirect3DVertexShader9_Release(shader);
7472     IDirect3DVertexBuffer9_Release(buffer);
7473 }
7474
7475 static void conditional_np2_repeat_test(IDirect3DDevice9 *device)
7476 {
7477     D3DCAPS9 caps;
7478     IDirect3DTexture9 *texture;
7479     HRESULT hr;
7480     D3DLOCKED_RECT rect;
7481     unsigned int x, y;
7482     DWORD *dst, color;
7483     const float quad[] = {
7484         -1.0,   -1.0,   0.1,   -0.2,   -0.2,
7485          1.0,   -1.0,   0.1,    1.2,   -0.2,
7486         -1.0,    1.0,   0.1,   -0.2,    1.2,
7487          1.0,    1.0,   0.1,    1.2,    1.2
7488     };
7489     memset(&caps, 0, sizeof(caps));
7490
7491     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7492     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%s\n", DXGetErrorString9(hr));
7493     if(!(caps.TextureCaps & D3DPTEXTURECAPS_POW2)) {
7494         /* NP2 conditional requires the POW2 flag. Check that while we're at it */
7495         ok((caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) == 0,
7496            "Card has conditional NP2 support without power of two restriction set\n");
7497         skip("Card has unconditional pow2 support, skipping conditional NP2 tests\n");
7498         return;
7499     } else if(!(caps.TextureCaps & D3DPTEXTURECAPS_POW2)) {
7500         skip("No conditional NP2 support, skipping conditional NP2 tests\n");
7501         return;
7502     }
7503
7504     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
7505     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%s\n", DXGetErrorString9(hr));
7506
7507     hr = IDirect3DDevice9_CreateTexture(device, 10, 10, 1, 0, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
7508     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed hr=%s\n", DXGetErrorString9(hr));
7509
7510     memset(&rect, 0, sizeof(rect));
7511     hr = IDirect3DTexture9_LockRect(texture, 0, &rect, NULL, 0);
7512     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed hr=%s\n", DXGetErrorString9(hr));
7513     for(y = 0; y < 10; y++) {
7514         for(x = 0; x < 10; x++) {
7515             dst = (DWORD *) ((BYTE *) rect.pBits + y * rect.Pitch + x * sizeof(DWORD));
7516             if(x == 0 || x == 9 || y == 0 || y == 9) {
7517                 *dst = 0x00ff0000;
7518             } else {
7519                 *dst = 0x000000ff;
7520             }
7521         }
7522     }
7523     hr = IDirect3DTexture9_UnlockRect(texture, 0);
7524     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed hr=%s\n", DXGetErrorString9(hr));
7525
7526     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
7527     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%s\n", DXGetErrorString9(hr));
7528     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
7529     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed hr=%s\n", DXGetErrorString9(hr));
7530     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
7531     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed hr=%s\n", DXGetErrorString9(hr));
7532     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7533     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed, hr=%s\n", DXGetErrorString9(hr));
7534
7535     hr = IDirect3DDevice9_BeginScene(device);
7536     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%s\n", DXGetErrorString9(hr));
7537     if(SUCCEEDED(hr)) {
7538         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
7539         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
7540
7541         hr = IDirect3DDevice9_EndScene(device);
7542         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%s\n", DXGetErrorString9(hr));
7543     }
7544
7545     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7546
7547     color = getPixelColor(device,    1,  1);
7548     ok(color == 0x00ff0000, "NP2: Pixel   1,  1 has color %08x, expected 0x00ff0000\n", color);
7549     color = getPixelColor(device, 639, 479);
7550     ok(color == 0x00ff0000, "NP2: Pixel 639, 479 has color %08x, expected 0x00ff0000\n", color);
7551
7552     color = getPixelColor(device, 135, 101);
7553     ok(color == 0x00ff0000, "NP2: Pixel 135, 101 has color %08x, expected 0x00ff0000\n", color);
7554     color = getPixelColor(device, 140, 101);
7555     ok(color == 0x00ff0000, "NP2: Pixel 140, 101 has color %08x, expected 0x00ff0000\n", color);
7556     color = getPixelColor(device, 135, 105);
7557     ok(color == 0x00ff0000, "NP2: Pixel 135, 105 has color %08x, expected 0x00ff0000\n", color);
7558     color = getPixelColor(device, 140, 105);
7559     ok(color == 0x000000ff, "NP2: Pixel 140, 105 has color %08x, expected 0x000000ff\n", color);
7560
7561     color = getPixelColor(device, 135, 376);
7562     ok(color == 0x00ff0000, "NP2: Pixel 135, 376 has color %08x, expected 0x00ff0000\n", color);
7563     color = getPixelColor(device, 140, 376);
7564     ok(color == 0x000000ff, "NP2: Pixel 140, 376 has color %08x, expected 0x000000ff\n", color);
7565     color = getPixelColor(device, 135, 379);
7566     ok(color == 0x00ff0000, "NP2: Pixel 135, 379 has color %08x, expected 0x00ff0000\n", color);
7567     color = getPixelColor(device, 140, 379);
7568     ok(color == 0x00ff0000, "NP2: Pixel 140, 379 has color %08x, expected 0x00ff0000\n", color);
7569
7570     color = getPixelColor(device, 500, 101);
7571     ok(color == 0x00ff0000, "NP2: Pixel 500, 101 has color %08x, expected 0x00ff0000\n", color);
7572     color = getPixelColor(device, 504, 101);
7573     ok(color == 0x00ff0000, "NP2: Pixel 504, 101 has color %08x, expected 0x00ff0000\n", color);
7574     color = getPixelColor(device, 500, 105);
7575     ok(color == 0x000000ff, "NP2: Pixel 500, 105 has color %08x, expected 0x000000ff\n", color);
7576     color = getPixelColor(device, 504, 105);
7577     ok(color == 0x00ff0000, "NP2: Pixel 504, 105 has color %08x, expected 0x00ff0000\n", color);
7578
7579     color = getPixelColor(device, 500, 376);
7580     ok(color == 0x000000ff, "NP2: Pixel 500, 376 has color %08x, expected 0x000000ff\n", color);
7581     color = getPixelColor(device, 504, 376);
7582     ok(color == 0x00ff0000, "NP2: Pixel 504, 376 has color %08x, expected 0x00ff0000\n", color);
7583     color = getPixelColor(device, 500, 380);
7584     ok(color == 0x00ff0000, "NP2: Pixel 500, 380 has color %08x, expected 0x00ff0000\n", color);
7585     color = getPixelColor(device, 504, 380);
7586     ok(color == 0x00ff0000, "NP2: Pixel 504, 380 has color %08x, expected 0x00ff0000\n", color);
7587
7588     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
7589     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed hr=%s\n", DXGetErrorString9(hr));
7590     IDirect3DTexture9_Release(texture);
7591 }
7592
7593 static void vFace_register_test(IDirect3DDevice9 *device)
7594 {
7595     HRESULT hr;
7596     DWORD color;
7597     const DWORD shader_code[] = {
7598         0xffff0300,                                                             /* ps_3_0                     */
7599         0x05000051, 0xa00f0000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c0, 0.0, 1.0, 0.0, 0.0 */
7600         0x05000051, 0xa00f0001, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c1, 1.0, 0.0, 0.0, 0.0 */
7601         0x0200001f, 0x80000000, 0x900f1001,                                     /* dcl vFace                  */
7602         0x02000001, 0x800f0001, 0xa0e40001,                                     /* mov r1, c1                 */
7603         0x04000058, 0x800f0000, 0x90e41001, 0xa0e40000, 0x80e40001,             /* cmp r0, vFace, c0, r1      */
7604         0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                */
7605         0x0000ffff                                                              /* END                        */
7606     };
7607     IDirect3DPixelShader9 *shader;
7608     IDirect3DTexture9 *texture;
7609     IDirect3DSurface9 *surface, *backbuffer;
7610     const float quad[] = {
7611         -1.0,   -1.0,   0.1,
7612          1.0,   -1.0,   0.1,
7613         -1.0,    0.0,   0.1,
7614
7615          1.0,   -1.0,   0.1,
7616          1.0,    0.0,   0.1,
7617         -1.0,    0.0,   0.1,
7618
7619         -1.0,    0.0,   0.1,
7620         -1.0,    1.0,   0.1,
7621          1.0,    0.0,   0.1,
7622
7623          1.0,    0.0,   0.1,
7624         -1.0,    1.0,   0.1,
7625          1.0,    1.0,   0.1,
7626     };
7627     const float blit[] = {
7628          0.0,   -1.0,   0.1,    0.0,    0.0,
7629          1.0,   -1.0,   0.1,    1.0,    0.0,
7630          0.0,    1.0,   0.1,    0.0,    1.0,
7631          1.0,    1.0,   0.1,    1.0,    1.0,
7632     };
7633
7634     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
7635     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed hr=%s\n", DXGetErrorString9(hr));
7636     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &texture, NULL);
7637     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed hr=%s\n", DXGetErrorString9(hr));
7638     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
7639     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed hr=%s\n", DXGetErrorString9(hr));
7640     hr = IDirect3DDevice9_SetPixelShader(device, shader);
7641     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%s\n", DXGetErrorString9(hr));
7642     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
7643     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%s\n", DXGetErrorString9(hr));
7644     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
7645     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed hr=%s\n", DXGetErrorString9(hr));
7646
7647     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
7648     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%s\n", DXGetErrorString9(hr));
7649
7650     hr = IDirect3DDevice9_BeginScene(device);
7651     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%s\n", DXGetErrorString9(hr));
7652     if(SUCCEEDED(hr)) {
7653         /* First, draw to the texture and the back buffer to test both offscreen and onscreen cases */
7654         hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
7655         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%s\n", DXGetErrorString9(hr));
7656         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
7657         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%s\n", DXGetErrorString9(hr));
7658         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 4, quad, sizeof(float) * 3);
7659         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
7660         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
7661         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%s\n", DXGetErrorString9(hr));
7662         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLELIST, 4, quad, sizeof(float) * 3);
7663         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
7664
7665         /* Blit the texture onto the back buffer to make it visible */
7666         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
7667         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed, hr=%s\n", DXGetErrorString9(hr));
7668         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
7669         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%s\n", DXGetErrorString9(hr));
7670         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
7671         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed, hr=%s\n", DXGetErrorString9(hr));
7672         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
7673         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed, hr=%s\n", DXGetErrorString9(hr));
7674         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
7675         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%s\n", DXGetErrorString9(hr));
7676
7677         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, blit, sizeof(float) * 5);
7678         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
7679
7680         hr = IDirect3DDevice9_EndScene(device);
7681         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%s\n", DXGetErrorString9(hr));
7682     }
7683
7684     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7685     color = getPixelColor(device, 160, 360);
7686     ok(color == 0x00ff0000, "vFace: Onscreen rendered front facing quad has color 0x%08x, expected 0x00ff0000\n", color);
7687     color = getPixelColor(device, 160, 120);
7688     ok(color == 0x0000ff00, "vFace: Onscreen rendered back facing quad has color 0x%08x, expected 0x0000ff00\n", color);
7689     color = getPixelColor(device, 480, 360);
7690     ok(color == 0x0000ff00, "vFace: Offscreen rendered back facing quad has color 0x%08x, expected 0x0000ff00\n", color);
7691     color = getPixelColor(device, 480, 120);
7692     ok(color == 0x00ff0000, "vFace: Offscreen rendered front facing quad has color 0x%08x, expected 0x00ff0000\n", color);
7693
7694     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%s\n", DXGetErrorString9(hr));
7695     IDirect3DDevice9_SetTexture(device, 0, NULL);
7696     IDirect3DPixelShader9_Release(shader);
7697     IDirect3DSurface9_Release(surface);
7698     IDirect3DSurface9_Release(backbuffer);
7699     IDirect3DTexture9_Release(texture);
7700 }
7701
7702 static void fixed_function_bumpmap_test(IDirect3DDevice9 *device)
7703 {
7704     HRESULT hr;
7705     DWORD color;
7706     int i;
7707     D3DCAPS9 caps;
7708
7709     static const float quad[][7] = {
7710         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f},
7711         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f},
7712         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 1.0f, 0.0f},
7713         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 1.0f, 1.0f},
7714     };
7715
7716     static const D3DVERTEXELEMENT9 decl_elements[] = {
7717         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
7718         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
7719         {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
7720         D3DDECL_END()
7721     };
7722
7723     /* use asymmetric matrix to test loading */
7724     float bumpenvmat[4] = {0.0,0.5,-0.5,0.0};
7725
7726     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
7727     IDirect3DTexture9           *texture            = NULL;
7728
7729     memset(&caps, 0, sizeof(caps));
7730     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
7731     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%s\n", DXGetErrorString9(hr));
7732     if(!(caps.TextureOpCaps & D3DTEXOPCAPS_BUMPENVMAP)) {
7733         skip("D3DTEXOPCAPS_BUMPENVMAP not set, skipping bumpmap tests\n");
7734         return;
7735     } else {
7736         /* This check is disabled, some Windows drivers do not handle D3DUSAGE_QUERY_LEGACYBUMPMAP properly.
7737          * They report that it is not supported, but after that bump mapping works properly. So just test
7738          * if the format is generally supported, and check the BUMPENVMAP flag
7739          */
7740         IDirect3D9 *d3d9;
7741
7742         IDirect3DDevice9_GetDirect3D(device, &d3d9);
7743         hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
7744                                           D3DRTYPE_TEXTURE, D3DFMT_V8U8);
7745         IDirect3D9_Release(d3d9);
7746         if(FAILED(hr)) {
7747             skip("D3DFMT_V8U8 not supported for legacy bump mapping\n");
7748             return;
7749         }
7750     }
7751
7752     /* Generate the textures */
7753     generate_bumpmap_textures(device);
7754
7755     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
7756     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7757     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
7758     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7759     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
7760     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7761     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
7762     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7763
7764     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_BUMPENVMAP);
7765     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7766     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
7767     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7768     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_CURRENT );
7769     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7770
7771     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
7772     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7773     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
7774     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7775     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG2, D3DTA_CURRENT);
7776     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7777
7778     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
7779     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7780
7781     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
7782     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
7783
7784     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
7785     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
7786
7787
7788     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
7789     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
7790     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
7791     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
7792
7793     hr = IDirect3DDevice9_BeginScene(device);
7794     ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
7795
7796     hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
7797     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
7798
7799     hr = IDirect3DDevice9_EndScene(device);
7800     ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
7801
7802     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7803     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
7804
7805     color = getPixelColor(device, 320-32, 240);
7806     ok(color == 0x00ffffff, "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
7807     color = getPixelColor(device, 320+32, 240);
7808     ok(color == 0x00ffffff, "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
7809     color = getPixelColor(device, 320, 240-32);
7810     ok(color == 0x00ffffff, "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
7811     color = getPixelColor(device, 320, 240+32);
7812     ok(color == 0x00ffffff, "bumpmap failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
7813     color = getPixelColor(device, 320, 240);
7814     ok(color == 0x00000000, "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
7815     color = getPixelColor(device, 320+32, 240+32);
7816     ok(color == 0x00000000, "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
7817     color = getPixelColor(device, 320-32, 240+32);
7818     ok(color == 0x00000000, "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
7819     color = getPixelColor(device, 320+32, 240-32);
7820     ok(color == 0x00000000, "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
7821     color = getPixelColor(device, 320-32, 240-32);
7822     ok(color == 0x00000000, "bumpmap failed: Got color 0x%08x, expected 0x00000000.\n", color);
7823
7824     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
7825     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
7826     IDirect3DVertexDeclaration9_Release(vertex_declaration);
7827
7828     for(i = 0; i < 2; i++) {
7829         hr = IDirect3DDevice9_GetTexture(device, i, (IDirect3DBaseTexture9 **) &texture);
7830         ok(SUCCEEDED(hr), "IDirect3DDevice9_GetTexture failed (0x%08x)\n", hr);
7831         IDirect3DTexture9_Release(texture); /* For the GetTexture */
7832         hr = IDirect3DDevice9_SetTexture(device, i, NULL);
7833         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
7834         IDirect3DTexture9_Release(texture); /* To destroy it */
7835     }
7836
7837     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
7838     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7839     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_MODULATE);
7840     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
7841
7842 }
7843
7844 static void stencil_cull_test(IDirect3DDevice9 *device) {
7845     HRESULT hr;
7846     IDirect3DSurface9 *depthstencil = NULL;
7847     D3DSURFACE_DESC desc;
7848     float quad1[] = {
7849         -1.0,   -1.0,   0.1,
7850          0.0,   -1.0,   0.1,
7851         -1.0,    0.0,   0.1,
7852          0.0,    0.0,   0.1,
7853     };
7854     float quad2[] = {
7855          0.0,   -1.0,   0.1,
7856          1.0,   -1.0,   0.1,
7857          0.0,    0.0,   0.1,
7858          1.0,    0.0,   0.1,
7859     };
7860     float quad3[] = {
7861         0.0,    0.0,   0.1,
7862         1.0,    0.0,   0.1,
7863         0.0,    1.0,   0.1,
7864         1.0,    1.0,   0.1,
7865     };
7866     float quad4[] = {
7867         -1.0,    0.0,   0.1,
7868          0.0,    0.0,   0.1,
7869         -1.0,    1.0,   0.1,
7870          0.0,    1.0,   0.1,
7871     };
7872     struct vertex painter[] = {
7873        {-1.0,   -1.0,   0.0,    0x00000000},
7874        { 1.0,   -1.0,   0.0,    0x00000000},
7875        {-1.0,    1.0,   0.0,    0x00000000},
7876        { 1.0,    1.0,   0.0,    0x00000000},
7877     };
7878     WORD indices_cw[]  = {0, 1, 3};
7879     WORD indices_ccw[] = {0, 2, 3};
7880     unsigned int i;
7881     DWORD color;
7882
7883     IDirect3DDevice9_GetDepthStencilSurface(device, &depthstencil);
7884     if(depthstencil == NULL) {
7885         skip("No depth stencil buffer\n");
7886         return;
7887     }
7888     hr = IDirect3DSurface9_GetDesc(depthstencil, &desc);
7889     ok(hr == D3D_OK, "IDirect3DSurface9_GetDesc failed with %s\n", DXGetErrorString9(hr));
7890     IDirect3DSurface9_Release(depthstencil);
7891     if(desc.Format != D3DFMT_D24S8 && desc.Format != D3DFMT_D24X4S4) {
7892         skip("No 4 or 8 bit stencil surface\n");
7893         return;
7894     }
7895
7896     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_STENCIL, 0x00ff0000, 0.0, 0x8);
7897     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
7898     IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
7899
7900     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILFAIL, D3DSTENCILOP_INCR);
7901     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7902     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILZFAIL, D3DSTENCILOP_DECR);
7903     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7904     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
7905     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7906     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILREF, 0x3);
7907     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7908
7909     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CCW_STENCILFAIL, D3DSTENCILOP_REPLACE);
7910     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7911     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CCW_STENCILZFAIL, D3DSTENCILOP_DECR);
7912     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7913     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CCW_STENCILPASS, D3DSTENCILOP_INCR);
7914     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7915
7916     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, TRUE);
7917     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7918     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TWOSIDEDSTENCILMODE, FALSE);
7919     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7920
7921     /* First pass: Fill the stencil buffer with some values... */
7922     hr = IDirect3DDevice9_BeginScene(device);
7923     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
7924     if(SUCCEEDED(hr))
7925     {
7926         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_CW);
7927         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7928         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
7929                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad1, sizeof(float) * 3);
7930         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
7931                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad1, sizeof(float) * 3);
7932
7933         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TWOSIDEDSTENCILMODE, TRUE);
7934         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7935         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
7936         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7937         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
7938                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad2, sizeof(float) * 3);
7939         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
7940                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad2, sizeof(float) * 3);
7941
7942         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_CW);
7943         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7944         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
7945                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad3, sizeof(float) * 3);
7946         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
7947                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad3, sizeof(float) * 3);
7948
7949         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_CCW);
7950         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7951         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
7952                 1 /*PrimCount */, indices_cw, D3DFMT_INDEX16, quad4, sizeof(float) * 3);
7953         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
7954                 1 /*PrimCount */, indices_ccw, D3DFMT_INDEX16, quad4, sizeof(float) * 3);
7955
7956         hr = IDirect3DDevice9_EndScene(device);
7957         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
7958     }
7959
7960     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7961     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
7962     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7963     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILPASS, D3DSTENCILOP_KEEP);
7964     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7965     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
7966     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7967     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TWOSIDEDSTENCILMODE, FALSE);
7968     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7969     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
7970     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7971     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILFUNC, D3DCMP_EQUAL);
7972     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7973
7974     /* 2nd pass: Make the stencil values visible */
7975     hr = IDirect3DDevice9_BeginScene(device);
7976     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
7977     if(SUCCEEDED(hr))
7978     {
7979         IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
7980         for(i = 0; i < 16; i++) {
7981             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILREF, i);
7982             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
7983
7984             painter[0].diffuse = (i * 16); /* Creates shades of blue */
7985             painter[1].diffuse = (i * 16);
7986             painter[2].diffuse = (i * 16);
7987             painter[3].diffuse = (i * 16);
7988             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, painter, sizeof(painter[0]));
7989             ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
7990         }
7991         hr = IDirect3DDevice9_EndScene(device);
7992         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
7993     }
7994
7995     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
7996     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
7997
7998     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
7999     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
8000
8001     color = getPixelColor(device, 160, 420);
8002     ok(color == 0x00000030, "CCW triangle, twoside FALSE, cull cw, replace, has color 0x%08x, expected 0x00000030\n", color);
8003     color = getPixelColor(device, 160, 300);
8004     ok(color == 0x00000080, "CW triangle, twoside FALSE, cull cw, culled, has color 0x%08x, expected 0x00000080\n", color);
8005
8006     color = getPixelColor(device, 480, 420);
8007     ok(color == 0x00000090, "CCW triangle, twoside TRUE, cull off, incr, has color 0x%08x, expected 0x00000090\n", color);
8008     color = getPixelColor(device, 480, 300);
8009     ok(color == 0x00000030, "CW triangle, twoside TRUE, cull off, replace, has color 0x%08x, expected 0x00000030\n", color);
8010
8011     color = getPixelColor(device, 160, 180);
8012     ok(color == 0x00000080, "CCW triangle, twoside TRUE, cull ccw, culled, has color 0x%08x, expected 0x00000080\n", color);
8013     color = getPixelColor(device, 160, 60);
8014     ok(color == 0x00000030, "CW triangle, twoside TRUE, cull ccw, replace, has color 0x%08x, expected 0x00000030\n", color);
8015
8016     color = getPixelColor(device, 480, 180);
8017     ok(color == 0x00000090, "CCW triangle, twoside TRUE, cull cw, incr, has color 0x%08x, expected 0x00000090\n", color);
8018     color = getPixelColor(device, 480, 60);
8019     ok(color == 0x00000080, "CW triangle, twoside TRUE, cull cw, culled, has color 0x%08x, expected 0x00000080\n", color);
8020 }
8021
8022 static void vpos_register_test(IDirect3DDevice9 *device)
8023 {
8024     HRESULT hr;
8025     DWORD color;
8026     const DWORD shader_code[] = {
8027     0xffff0300,                                                             /* ps_3_0                     */
8028     0x0200001f, 0x80000000, 0x90031000,                                     /* dcl vPos.xy                */
8029     0x03000002, 0x80030000, 0x90541000, 0xa1fe0000,                         /* sub r0.xy, vPos.xy, c0.zw  */
8030     0x02000001, 0x800f0001, 0xa0e40000,                                     /* mov r1, c0                 */
8031     0x02000001, 0x80080002, 0xa0550000,                                     /* mov r2.a, c0.y             */
8032     0x02000001, 0x80010002, 0xa0550000,                                     /* mov r2.r, c0.y             */
8033     0x04000058, 0x80020002, 0x80000000, 0x80000001, 0x80550001,             /* cmp r2.g, r0.x, r1.x, r1.y */
8034     0x04000058, 0x80040002, 0x80550000, 0x80000001, 0x80550001,             /* cmp r2.b, r0.y, r1.x, r1.y */
8035     0x02000001, 0x800f0800, 0x80e40002,                                     /* mov oC0, r2                */
8036     0x0000ffff                                                              /* end                        */
8037     };
8038     const DWORD shader_frac_code[] = {
8039     0xffff0300,                                                             /* ps_3_0                     */
8040     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 0.0, 0.0, 0.0, 0.0 */
8041     0x0200001f, 0x80000000, 0x90031000,                                     /* dcl vPos.xy                */
8042     0x02000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                 */
8043     0x02000013, 0x80030000, 0x90541000,                                     /* frc r0.xy, vPos.xy         */
8044     0x02000001, 0x800f0800, 0x80e40000,                                     /* mov oC0, r0                */
8045     0x0000ffff                                                              /* end                        */
8046     };
8047     IDirect3DPixelShader9 *shader, *shader_frac;
8048     IDirect3DSurface9 *surface = NULL, *backbuffer;
8049     const float quad[] = {
8050         -1.0,   -1.0,   0.1,    0.0,    0.0,
8051          1.0,   -1.0,   0.1,    1.0,    0.0,
8052         -1.0,    1.0,   0.1,    0.0,    1.0,
8053          1.0,    1.0,   0.1,    1.0,    1.0,
8054     };
8055     D3DLOCKED_RECT lr;
8056     float constant[4] = {1.0, 0.0, 320, 240};
8057     DWORD *pos;
8058
8059     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
8060     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%s\n", DXGetErrorString9(hr));
8061     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
8062     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed hr=%s\n", DXGetErrorString9(hr));
8063     hr = IDirect3DDevice9_CreatePixelShader(device, shader_frac_code, &shader_frac);
8064     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed hr=%s\n", DXGetErrorString9(hr));
8065     hr = IDirect3DDevice9_SetPixelShader(device, shader);
8066     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%s\n", DXGetErrorString9(hr));
8067     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8068     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%s\n", DXGetErrorString9(hr));
8069     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
8070     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed hr=%s\n", DXGetErrorString9(hr));
8071
8072     hr = IDirect3DDevice9_BeginScene(device);
8073     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%s\n", DXGetErrorString9(hr));
8074     if(SUCCEEDED(hr)) {
8075         hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, constant, 1);
8076         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF failed hr=%s\n", DXGetErrorString9(hr));
8077         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
8078         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
8079         hr = IDirect3DDevice9_EndScene(device);
8080         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%s\n", DXGetErrorString9(hr));
8081     }
8082
8083     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8084     /* This has to be pixel exact */
8085     color = getPixelColor(device, 319, 239);
8086     ok(color == 0x00000000, "vPos: Pixel 319,239 has color 0x%08x, expected 0x00000000\n", color);
8087     color = getPixelColor(device, 320, 239);
8088     ok(color == 0x0000ff00, "vPos: Pixel 320,239 has color 0x%08x, expected 0x0000ff00\n", color);
8089     color = getPixelColor(device, 319, 240);
8090     ok(color == 0x000000ff, "vPos: Pixel 319,240 has color 0x%08x, expected 0x000000ff\n", color);
8091     color = getPixelColor(device, 320, 240);
8092     ok(color == 0x0000ffff, "vPos: Pixel 320,240 has color 0x%08x, expected 0x0000ffff\n", color);
8093
8094     hr = IDirect3DDevice9_CreateRenderTarget(device, 32, 32, D3DFMT_X8R8G8B8, 0, 0, TRUE,
8095                                              &surface, NULL);
8096     ok(hr == D3D_OK, "IDirect3DDevice9_CreateRenderTarget failed hr=%s\n", DXGetErrorString9(hr));
8097     hr = IDirect3DDevice9_BeginScene(device);
8098     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%s\n", DXGetErrorString9(hr));
8099     if(SUCCEEDED(hr)) {
8100         constant[2] = 16; constant[3] = 16;
8101         hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, constant, 1);
8102         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF failed hr=%s\n", DXGetErrorString9(hr));
8103         hr = IDirect3DDevice9_SetRenderTarget(device, 0, surface);
8104         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%s\n", DXGetErrorString9(hr));
8105         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
8106         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
8107         hr = IDirect3DDevice9_EndScene(device);
8108         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%s\n", DXGetErrorString9(hr));
8109     }
8110     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, D3DLOCK_READONLY);
8111     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr=%s\n", DXGetErrorString9(hr));
8112
8113     pos = (DWORD *) (((BYTE *) lr.pBits) + 14 * lr.Pitch + 14 * sizeof(DWORD));
8114     color = *pos & 0x00ffffff;
8115     ok(color == 0x00000000, "Pixel 14/14 has color 0x%08x, expected 0x00000000\n", color);
8116     pos = (DWORD *) (((BYTE *) lr.pBits) + 14 * lr.Pitch + 18 * sizeof(DWORD));
8117     color = *pos & 0x00ffffff;
8118     ok(color == 0x0000ff00, "Pixel 14/18 has color 0x%08x, expected 0x0000ff00\n", color);
8119     pos = (DWORD *) (((BYTE *) lr.pBits) + 18 * lr.Pitch + 14 * sizeof(DWORD));
8120     color = *pos & 0x00ffffff;
8121     ok(color == 0x000000ff, "Pixel 18/14 has color 0x%08x, expected 0x000000ff\n", color);
8122     pos = (DWORD *) (((BYTE *) lr.pBits) + 18 * lr.Pitch + 18 * sizeof(DWORD));
8123     color = *pos & 0x00ffffff;
8124     ok(color == 0x0000ffff, "Pixel 18/18 has color 0x%08x, expected 0x0000ffff\n", color);
8125
8126     hr = IDirect3DSurface9_UnlockRect(surface);
8127     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr=%s\n", DXGetErrorString9(hr));
8128
8129     /* Test the fraction value of vPos. This is tested with the offscreen target and not the backbuffer to
8130      * have full control over the multisampling setting inside this test
8131      */
8132     hr = IDirect3DDevice9_SetPixelShader(device, shader_frac);
8133     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%s\n", DXGetErrorString9(hr));
8134     hr = IDirect3DDevice9_BeginScene(device);
8135     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%s\n", DXGetErrorString9(hr));
8136     if(SUCCEEDED(hr)) {
8137         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
8138         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%s\n", DXGetErrorString9(hr));
8139         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
8140         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
8141         hr = IDirect3DDevice9_EndScene(device);
8142         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%s\n", DXGetErrorString9(hr));
8143     }
8144     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
8145     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%s\n", DXGetErrorString9(hr));
8146
8147     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, D3DLOCK_READONLY);
8148     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed, hr=%s\n", DXGetErrorString9(hr));
8149
8150     pos = (DWORD *) (((BYTE *) lr.pBits) + 14 * lr.Pitch + 14 * sizeof(DWORD));
8151     color = *pos & 0x00ffffff;
8152     ok(color == 0x00000000, "vPos fraction test has color 0x%08x, expected 0x00000000\n", color);
8153
8154     hr = IDirect3DSurface9_UnlockRect(surface);
8155     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed, hr=%s\n", DXGetErrorString9(hr));
8156
8157     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
8158     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed hr=%s\n", DXGetErrorString9(hr));
8159     IDirect3DPixelShader9_Release(shader);
8160     IDirect3DPixelShader9_Release(shader_frac);
8161     if(surface) IDirect3DSurface9_Release(surface);
8162     IDirect3DSurface9_Release(backbuffer);
8163 }
8164
8165 static void pointsize_test(IDirect3DDevice9 *device)
8166 {
8167     HRESULT hr;
8168     D3DCAPS9 caps;
8169     D3DMATRIX matrix;
8170     D3DMATRIX identity;
8171     float ptsize, ptsize_orig;
8172     DWORD color;
8173
8174     const float vertices[] = {
8175         64,     64,     0.1,
8176         128,    64,     0.1,
8177         192,    64,     0.1,
8178         256,    64,     0.1,
8179         320,    64,     0.1,
8180         384,    64,     0.1
8181     };
8182
8183     /* Transforms the coordinate system [-1.0;1.0]x[-1.0;1.0] to [0.0;0.0]x[640.0;480.0]. Z is untouched */
8184     U(matrix).m[0][0] = 2.0/640.0; U(matrix).m[1][0] = 0.0;       U(matrix).m[2][0] = 0.0;   U(matrix).m[3][0] =-1.0;
8185     U(matrix).m[0][1] = 0.0;       U(matrix).m[1][1] =-2.0/480.0; U(matrix).m[2][1] = 0.0;   U(matrix).m[3][1] = 1.0;
8186     U(matrix).m[0][2] = 0.0;       U(matrix).m[1][2] = 0.0;       U(matrix).m[2][2] = 1.0;   U(matrix).m[3][2] = 0.0;
8187     U(matrix).m[0][3] = 0.0;       U(matrix).m[1][3] = 0.0;       U(matrix).m[2][3] = 0.0;   U(matrix).m[3][3] = 1.0;
8188
8189     U(identity).m[0][0] = 1.0;     U(identity).m[1][0] = 0.0;     U(identity).m[2][0] = 0.0; U(identity).m[3][0] = 0.0;
8190     U(identity).m[0][1] = 0.0;     U(identity).m[1][1] = 1.0;     U(identity).m[2][1] = 0.0; U(identity).m[3][1] = 0.0;
8191     U(identity).m[0][2] = 0.0;     U(identity).m[1][2] = 0.0;     U(identity).m[2][2] = 1.0; U(identity).m[3][2] = 0.0;
8192     U(identity).m[0][3] = 0.0;     U(identity).m[1][3] = 0.0;     U(identity).m[2][3] = 0.0; U(identity).m[3][3] = 1.0;
8193
8194     memset(&caps, 0, sizeof(caps));
8195     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8196     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed hr=%s\n", DXGetErrorString9(hr));
8197     if(caps.MaxPointSize < 32.0) {
8198         skip("MaxPointSize < 32.0, skipping(MaxPointsize = %f)\n", caps.MaxPointSize);
8199         return;
8200     }
8201
8202     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 0.0, 0);
8203     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%s\n", DXGetErrorString9(hr));
8204     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, &matrix);
8205     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed, hr=%s\n", DXGetErrorString9(hr));
8206     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8207     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed hr=%s\n", DXGetErrorString9(hr));
8208     hr = IDirect3DDevice9_GetRenderState(device, D3DRS_POINTSIZE, (DWORD *) &ptsize_orig);
8209     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderState failed hr=%s\n", DXGetErrorString9(hr));
8210
8211     hr = IDirect3DDevice9_BeginScene(device);
8212     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed hr=%s\n", DXGetErrorString9(hr));
8213     if(SUCCEEDED(hr)) {
8214         ptsize = 16.0;
8215         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8216         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%s\n", DXGetErrorString9(hr));
8217         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[0], sizeof(float) * 3);
8218         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
8219
8220         ptsize = 32.0;
8221         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8222         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%s\n", DXGetErrorString9(hr));
8223         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[3], sizeof(float) * 3);
8224         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
8225
8226         ptsize = 31.5;
8227         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8228         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%s\n", DXGetErrorString9(hr));
8229         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[6], sizeof(float) * 3);
8230         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
8231
8232         if(caps.MaxPointSize >= 64.0) {
8233             ptsize = 64.0;
8234             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8235             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%s\n", DXGetErrorString9(hr));
8236             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[9], sizeof(float) * 3);
8237             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
8238
8239             ptsize = 63.75;
8240             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8241             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%s\n", DXGetErrorString9(hr));
8242             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[15], sizeof(float) * 3);
8243             ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
8244         }
8245
8246         ptsize = 1.0;
8247         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize)));
8248         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr=%s\n", DXGetErrorString9(hr));
8249         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_POINTLIST, 1, &vertices[12], sizeof(float) * 3);
8250         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
8251
8252         hr = IDirect3DDevice9_EndScene(device);
8253         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed hr=%s\n", DXGetErrorString9(hr));
8254     }
8255     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8256     color = getPixelColor(device, 64-9, 64-9);
8257     ok(color == 0x000000ff, "pSize: Pixel (64-9),(64-9) has color 0x%08x, expected 0x000000ff\n", color);
8258     color = getPixelColor(device, 64-8, 64-8);
8259     todo_wine ok(color == 0x00ffffff, "pSize: Pixel (64-8),(64-8) has color 0x%08x, expected 0x00ffffff\n", color);
8260     color = getPixelColor(device, 64-7, 64-7);
8261     ok(color == 0x00ffffff, "pSize: Pixel (64-7),(64-7) has color 0x%08x, expected 0x00ffffff\n", color);
8262     color = getPixelColor(device, 64+7, 64+7);
8263     ok(color == 0x00ffffff, "pSize: Pixel (64+7),(64+7) has color 0x%08x, expected 0x00ffffff\n", color);
8264     color = getPixelColor(device, 64+8, 64+8);
8265     ok(color == 0x000000ff, "pSize: Pixel (64+8),(64+8) has color 0x%08x, expected 0x000000ff\n", color);
8266     color = getPixelColor(device, 64+9, 64+9);
8267     ok(color == 0x000000ff, "pSize: Pixel (64+9),(64+9) has color 0x%08x, expected 0x000000ff\n", color);
8268
8269     color = getPixelColor(device, 128-17, 64-17);
8270     ok(color == 0x000000ff, "pSize: Pixel (128-17),(64-17) has color 0x%08x, expected 0x000000ff\n", color);
8271     color = getPixelColor(device, 128-16, 64-16);
8272     todo_wine ok(color == 0x00ffffff, "pSize: Pixel (128-16),(64-16) has color 0x%08x, expected 0x00ffffff\n", color);
8273     color = getPixelColor(device, 128-15, 64-15);
8274     ok(color == 0x00ffffff, "pSize: Pixel (128-15),(64-15) has color 0x%08x, expected 0x00ffffff\n", color);
8275     color = getPixelColor(device, 128+15, 64+15);
8276     ok(color == 0x00ffffff, "pSize: Pixel (128+15),(64+15) has color 0x%08x, expected 0x00ffffff\n", color);
8277     color = getPixelColor(device, 128+16, 64+16);
8278     ok(color == 0x000000ff, "pSize: Pixel (128+16),(64+16) has color 0x%08x, expected 0x000000ff\n", color);
8279     color = getPixelColor(device, 128+17, 64+17);
8280     ok(color == 0x000000ff, "pSize: Pixel (128+17),(64+17) has color 0x%08x, expected 0x000000ff\n", color);
8281
8282     color = getPixelColor(device, 192-17, 64-17);
8283     ok(color == 0x000000ff, "pSize: Pixel (192-17),(64-17) has color 0x%08x, expected 0x000000ff\n", color);
8284     color = getPixelColor(device, 192-16, 64-16);
8285     ok(color == 0x000000ff, "pSize: Pixel (192-16),(64-16) has color 0x%08x, expected 0x000000ff\n", color);
8286     color = getPixelColor(device, 192-15, 64-15);
8287     ok(color == 0x00ffffff, "pSize: Pixel (192-15),(64-15) has color 0x%08x, expected 0x00ffffff\n", color);
8288     color = getPixelColor(device, 192+15, 64+15);
8289     ok(color == 0x00ffffff, "pSize: Pixel (192+15),(64+15) has color 0x%08x, expected 0x00ffffff\n", color);
8290     color = getPixelColor(device, 192+16, 64+16);
8291     ok(color == 0x000000ff, "pSize: Pixel (192+16),(64+16) has color 0x%08x, expected 0x000000ff\n", color);
8292     color = getPixelColor(device, 192+17, 64+17);
8293     ok(color == 0x000000ff, "pSize: Pixel (192+17),(64+17) has color 0x%08x, expected 0x000000ff\n", color);
8294
8295     if(caps.MaxPointSize >= 64.0) {
8296         color = getPixelColor(device, 256-33, 64-33);
8297         ok(color == 0x000000ff, "pSize: Pixel (256-33),(64-33) has color 0x%08x, expected 0x000000ff\n", color);
8298         color = getPixelColor(device, 256-32, 64-32);
8299         todo_wine ok(color == 0x00ffffff, "pSize: Pixel (256-32),(64-32) has color 0x%08x, expected 0x00ffffff\n", color);
8300         color = getPixelColor(device, 256-31, 64-31);
8301         ok(color == 0x00ffffff, "pSize: Pixel (256-31),(64-31) has color 0x%08x, expected 0x00ffffff\n", color);
8302         color = getPixelColor(device, 256+31, 64+31);
8303         ok(color == 0x00ffffff, "pSize: Pixel (256+31),(64+31) has color 0x%08x, expected 0x00ffffff\n", color);
8304         color = getPixelColor(device, 256+32, 64+32);
8305         ok(color == 0x000000ff, "pSize: Pixel (256+32),(64+32) has color 0x%08x, expected 0x000000ff\n", color);
8306         color = getPixelColor(device, 256+33, 64+33);
8307         ok(color == 0x000000ff, "pSize: Pixel (256+33),(64+33) has color 0x%08x, expected 0x000000ff\n", color);
8308
8309         color = getPixelColor(device, 384-33, 64-33);
8310         ok(color == 0x000000ff, "pSize: Pixel (384-33),(64-33) has color 0x%08x, expected 0x000000ff\n", color);
8311         color = getPixelColor(device, 384-32, 64-32);
8312         ok(color == 0x000000ff, "pSize: Pixel (384-32),(64-32) has color 0x%08x, expected 0x000000ff\n", color);
8313         color = getPixelColor(device, 384-31, 64-31);
8314         ok(color == 0x00ffffff, "pSize: Pixel (384-31),(64-31) has color 0x%08x, expected 0x00ffffff\n", color);
8315         color = getPixelColor(device, 384+31, 64+31);
8316         ok(color == 0x00ffffff, "pSize: Pixel (384+31),(64+31) has color 0x%08x, expected 0x00ffffff\n", color);
8317         color = getPixelColor(device, 384+32, 64+32);
8318         ok(color == 0x000000ff, "pSize: Pixel (384+32),(64+32) has color 0x%08x, expected 0x000000ff\n", color);
8319         color = getPixelColor(device, 384+33, 64+33);
8320         ok(color == 0x000000ff, "pSize: Pixel (384+33),(64+33) has color 0x%08x, expected 0x000000ff\n", color);
8321     }
8322
8323     color = getPixelColor(device, 320-1, 64-1);
8324     ok(color == 0x000000ff, "pSize: Pixel (320-1),(64-1) has color 0x%08x, expected 0x000000ff\n", color);
8325     color = getPixelColor(device, 320-0, 64-0);
8326     ok(color == 0x00ffffff, "pSize: Pixel (320-0),(64-0) has color 0x%08x, expected 0x00ffffff\n", color);
8327     color = getPixelColor(device, 320+1, 64+1);
8328     ok(color == 0x000000ff, "pSize: Pixel (320+1),(64+1) has color 0x%08x, expected 0x000000ff\n", color);
8329
8330     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_POINTSIZE, *((DWORD *) (&ptsize_orig)));
8331     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed hr=%s\n", DXGetErrorString9(hr));
8332     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, &identity);
8333     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed, hr=%s\n", DXGetErrorString9(hr));
8334 }
8335
8336 static void multiple_rendertargets_test(IDirect3DDevice9 *device)
8337 {
8338     HRESULT hr;
8339     IDirect3DPixelShader9 *ps;
8340     IDirect3DTexture9 *tex1, *tex2;
8341     IDirect3DSurface9 *surf1, *surf2, *backbuf;
8342     D3DCAPS9 caps;
8343     DWORD color;
8344     DWORD shader_code[] = {
8345     0xffff0300,                                                             /* ps_3_0             */
8346     0x05000051, 0xa00f0000, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c0, 0, 1, 0, 0 */
8347     0x05000051, 0xa00f0001, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, /* def c1, 0, 0, 1, 0 */
8348     0x02000001, 0x800f0800, 0xa0e40000,                                     /* mov oC0, c0        */
8349     0x02000001, 0x800f0801, 0xa0e40001,                                     /* mov oC1, c1        */
8350     0x0000ffff                                                              /* END                */
8351     };
8352     float quad[] = {
8353        -1.0,   -1.0,    0.1,
8354         1.0,   -1.0,    0.1,
8355        -1.0,    1.0,    0.1,
8356         1.0,    1.0,    0.1,
8357     };
8358     float texquad[] = {
8359        -1.0,   -1.0,    0.1,    0.0,    0.0,
8360         0.0,   -1.0,    0.1,    1.0,    0.0,
8361        -1.0,    1.0,    0.1,    0.0,    1.0,
8362         0.0,    1.0,    0.1,    1.0,    1.0,
8363
8364         0.0,   -1.0,    0.1,    0.0,    0.0,
8365         1.0,   -1.0,    0.1,    1.0,    0.0,
8366         0.0,    1.0,    0.1,    0.0,    1.0,
8367         1.0,    1.0,    0.1,    1.0,    1.0,
8368     };
8369
8370     memset(&caps, 0, sizeof(caps));
8371     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8372     ok(hr == D3D_OK, "IDirect3DDevice9_GetCaps failed, hr=%s\n", DXGetErrorString9(hr));
8373     if(caps.NumSimultaneousRTs < 2) {
8374         skip("Only 1 simultaneous render target supported, skipping MRT test\n");
8375         return;
8376     }
8377
8378     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0, 0);
8379     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed, hr=%s\n", DXGetErrorString9(hr));
8380
8381     hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &tex1, NULL);
8382     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%s\n", DXGetErrorString9(hr));
8383     hr = IDirect3DDevice9_CreateTexture(device, 16, 16, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &tex2, NULL);
8384     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed, hr=%s\n", DXGetErrorString9(hr));
8385     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &ps);
8386     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader failed, hr=%s\n", DXGetErrorString9(hr));
8387
8388     hr = IDirect3DDevice9_GetRenderTarget(device, 0, &backbuf);
8389     ok(hr == D3D_OK, "IDirect3DDevice9_GetRenderTarget failed, hr=%s\n", DXGetErrorString9(hr));
8390     hr = IDirect3DTexture9_GetSurfaceLevel(tex1, 0, &surf1);
8391     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed, hr=%s\n", DXGetErrorString9(hr));
8392     hr = IDirect3DTexture9_GetSurfaceLevel(tex2, 0, &surf2);
8393     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed, hr=%s\n", DXGetErrorString9(hr));
8394
8395     hr = IDirect3DDevice9_SetPixelShader(device, ps);
8396     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed, hr=%s\n", DXGetErrorString9(hr));
8397     hr = IDirect3DDevice9_SetRenderTarget(device, 0, surf1);
8398     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%s\n", DXGetErrorString9(hr));
8399     hr = IDirect3DDevice9_SetRenderTarget(device, 1, surf2);
8400     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%s\n", DXGetErrorString9(hr));
8401     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
8402     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr=%s\n", DXGetErrorString9(hr));
8403
8404     hr = IDirect3DDevice9_BeginScene(device);
8405     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed, hr=%s\n", DXGetErrorString9(hr));
8406     if(SUCCEEDED(hr)) {
8407         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 3 * sizeof(float));
8408         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
8409
8410         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
8411         ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed, hr=%s\n", DXGetErrorString9(hr));
8412         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuf);
8413         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%s\n", DXGetErrorString9(hr));
8414         hr = IDirect3DDevice9_SetRenderTarget(device, 1, NULL);
8415         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed, hr=%s\n", DXGetErrorString9(hr));
8416         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
8417         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr=%s\n", DXGetErrorString9(hr));
8418
8419         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex1);
8420         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%s\n", DXGetErrorString9(hr));
8421         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &texquad[0], 5 * sizeof(float));
8422         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
8423
8424         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) tex2);
8425         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%s\n", DXGetErrorString9(hr));
8426         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &texquad[20], 5 * sizeof(float));
8427         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed, hr=%s\n", DXGetErrorString9(hr));
8428
8429         hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
8430         ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed, hr=%s\n", DXGetErrorString9(hr));
8431
8432         hr = IDirect3DDevice9_EndScene(device);
8433         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr=%s\n", DXGetErrorString9(hr));
8434     }
8435
8436     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8437     color = getPixelColor(device, 160, 240);
8438     ok(color == 0x0000ff00, "Texture 1(output color 1) has color 0x%08x, expected 0x0000ff00\n", color);
8439     color = getPixelColor(device, 480, 240);
8440     ok(color == 0x000000ff, "Texture 2(output color 2) has color 0x%08x, expected 0x000000ff\n", color);
8441
8442     IDirect3DPixelShader9_Release(ps);
8443     IDirect3DTexture9_Release(tex1);
8444     IDirect3DTexture9_Release(tex2);
8445     IDirect3DSurface9_Release(surf1);
8446     IDirect3DSurface9_Release(surf2);
8447     IDirect3DSurface9_Release(backbuf);
8448 }
8449
8450 struct formats {
8451     const char *fmtName;
8452     D3DFORMAT textureFormat;
8453     DWORD resultColorBlending;
8454     DWORD resultColorNoBlending;
8455 };
8456
8457 const struct formats test_formats[] = {
8458   { "D3DFMT_G16R16", D3DFMT_G16R16, 0x00181800, 0x002010ff},
8459   { "D3DFMT_R16F", D3DFMT_R16F, 0x0018ffff, 0x0020ffff },
8460   { "D3DFMT_G16R16F", D3DFMT_G16R16F, 0x001818ff, 0x002010ff },
8461   { "D3DFMT_A16B16G16R16F", D3DFMT_A16B16G16R16F, 0x00181800, 0x00201000 },
8462   { "D3DFMT_R32F", D3DFMT_R32F, 0x0018ffff, 0x0020ffff },
8463   { "D3DFMT_G32R32F", D3DFMT_G32R32F, 0x001818ff, 0x002010ff },
8464   { "D3DFMT_A32B32G32R32F", D3DFMT_A32B32G32R32F, 0x00181800, 0x00201000 },
8465   { NULL, 0 }
8466 };
8467
8468 static void pixelshader_blending_test(IDirect3DDevice9 *device)
8469 {
8470     HRESULT hr;
8471     IDirect3DTexture9 *offscreenTexture = NULL;
8472     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
8473     IDirect3D9 *d3d = NULL;
8474     DWORD color;
8475     DWORD r0, g0, b0, r1, g1, b1;
8476     int fmt_index;
8477
8478     static const float quad[][5] = {
8479         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
8480         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
8481         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
8482         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
8483     };
8484
8485     /* Quad with R=0x10, G=0x20 */
8486     static const struct vertex quad1[] = {
8487         {-1.0f, -1.0f, 0.1f, 0x80102000},
8488         {-1.0f,  1.0f, 0.1f, 0x80102000},
8489         { 1.0f, -1.0f, 0.1f, 0x80102000},
8490         { 1.0f,  1.0f, 0.1f, 0x80102000},
8491     };
8492
8493     /* Quad with R=0x20, G=0x10 */
8494     static const struct vertex quad2[] = {
8495         {-1.0f, -1.0f, 0.1f, 0x80201000},
8496         {-1.0f,  1.0f, 0.1f, 0x80201000},
8497         { 1.0f, -1.0f, 0.1f, 0x80201000},
8498         { 1.0f,  1.0f, 0.1f, 0x80201000},
8499     };
8500
8501     IDirect3DDevice9_GetDirect3D(device, &d3d);
8502
8503     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
8504     ok(hr == D3D_OK, "Can't get back buffer, hr = %s\n", DXGetErrorString9(hr));
8505     if(!backbuffer) {
8506         goto out;
8507     }
8508
8509     for(fmt_index=0; test_formats[fmt_index].textureFormat != 0; fmt_index++)
8510     {
8511         D3DFORMAT fmt = test_formats[fmt_index].textureFormat;
8512         if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0, D3DRTYPE_TEXTURE, fmt) != D3D_OK) {
8513            skip("%s textures not supported\n", test_formats[fmt_index].fmtName);
8514            continue;
8515         }
8516
8517         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
8518         ok(hr == D3D_OK, "Clear failed, hr = %s\n", DXGetErrorString9(hr));
8519
8520         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, fmt, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
8521         ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %s\n", DXGetErrorString9(hr));
8522         if(!offscreenTexture) {
8523             continue;
8524         }
8525
8526         hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
8527         ok(hr == D3D_OK, "Can't get offscreen surface, hr = %s\n", DXGetErrorString9(hr));
8528         if(!offscreen) {
8529             continue;
8530         }
8531
8532         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
8533         ok(hr == D3D_OK, "SetFVF failed, hr = %s\n", DXGetErrorString9(hr));
8534
8535         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
8536         ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8537         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
8538         ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8539         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
8540         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
8541         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
8542         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
8543         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
8544         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
8545
8546         /* Below we will draw two quads with different colors and try to blend them together.
8547          * The result color is compared with the expected outcome.
8548          */
8549         if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
8550             hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
8551             ok(hr == D3D_OK, "SetRenderTarget failed, hr = %s\n", DXGetErrorString9(hr));
8552             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x00ffffff, 0.0, 0);
8553             ok(hr == D3D_OK, "Clear failed, hr = %s\n", DXGetErrorString9(hr));
8554
8555             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
8556             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8557
8558             /* Draw a quad using color 0x0010200 */
8559             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_ONE);
8560             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8561             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_ZERO);
8562             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8563             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
8564             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
8565
8566             /* Draw a quad using color 0x0020100 */
8567             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
8568             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8569             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
8570             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8571             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
8572             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
8573
8574             /* We don't want to blend the result on the backbuffer */
8575             hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
8576             ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %08x\n", hr);
8577
8578             /* Prepare rendering the 'blended' texture quad to the backbuffer */
8579             hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
8580             ok(hr == D3D_OK, "SetRenderTarget failed, hr = %s\n", DXGetErrorString9(hr));
8581             hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
8582             ok(hr == D3D_OK, "SetTexture failed, %s\n", DXGetErrorString9(hr));
8583
8584             hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
8585             ok(hr == D3D_OK, "SetFVF failed, hr = %s\n", DXGetErrorString9(hr));
8586
8587             /* This time with the texture */
8588             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
8589             ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %s\n", DXGetErrorString9(hr));
8590
8591             IDirect3DDevice9_EndScene(device);
8592         }
8593         IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8594
8595
8596         if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, D3DRTYPE_TEXTURE, fmt) == D3D_OK) {
8597             /* Compare the color of the center quad with our expectation */
8598             color = getPixelColor(device, 320, 240);
8599             r0 = (color & 0x00ff0000) >> 16;
8600             g0 = (color & 0x0000ff00) >>  8;
8601             b0 = (color & 0x000000ff) >>  0;
8602
8603             r1 = (test_formats[fmt_index].resultColorBlending & 0x00ff0000) >> 16;
8604             g1 = (test_formats[fmt_index].resultColorBlending & 0x0000ff00) >>  8;
8605             b1 = (test_formats[fmt_index].resultColorBlending & 0x000000ff) >>  0;
8606
8607             ok(r0 >= max(r1, 1) - 1 && r0 <= r1 + 1 &&
8608                g0 >= max(g1, 1) - 1 && g0 <= g1 + 1 &&
8609                b0 >= max(b1, 1) - 1 && b0 <= b1 + 1,
8610                "Offscreen failed for %s: Got color %#08x, expected %#08x.\n", test_formats[fmt_index].fmtName, color, test_formats[fmt_index].resultColorBlending);
8611         } else {
8612             /* No pixel shader blending is supported so expected garbage.The type of 'garbage' depends on the driver version and OS.
8613              * E.g. on G16R16 ati reports (on old r9600 drivers) 0x00ffffff and on modern ones 0x002010ff which is also what Nvidia
8614              * reports. On Vista Nvidia seems to report 0x00ffffff on Geforce7 cards. */
8615             color = getPixelColor(device, 320, 240);
8616             ok((color == 0x00ffffff) || (color == test_formats[fmt_index].resultColorNoBlending), "Offscreen failed for %s: expected no color blending but received it anyway.\n", test_formats[fmt_index].fmtName);
8617         }
8618
8619         IDirect3DDevice9_SetTexture(device, 0, NULL);
8620         if(offscreenTexture) {
8621             IDirect3DTexture9_Release(offscreenTexture);
8622         }
8623         if(offscreen) {
8624             IDirect3DSurface9_Release(offscreen);
8625         }
8626     }
8627
8628 out:
8629     /* restore things */
8630     if(backbuffer) {
8631         IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
8632         IDirect3DSurface9_Release(backbuffer);
8633     }
8634 }
8635
8636 static void tssargtemp_test(IDirect3DDevice9 *device)
8637 {
8638     HRESULT hr;
8639     DWORD color;
8640     static const struct vertex quad[] = {
8641         {-1.0,     -1.0,    0.1,    0x00ff0000},
8642         { 1.0,     -1.0,    0.1,    0x00ff0000},
8643         {-1.0,      1.0,    0.1,    0x00ff0000},
8644         { 1.0,      1.0,    0.1,    0x00ff0000}
8645     };
8646     D3DCAPS9 caps;
8647
8648     memset(&caps, 0, sizeof(caps));
8649     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
8650     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps failed with %s\n", DXGetErrorString9(hr));
8651     if(!(caps.PrimitiveMiscCaps & D3DPMISCCAPS_TSSARGTEMP)) {
8652         skip("D3DPMISCCAPS_TSSARGTEMP not supported\n");
8653         return;
8654     }
8655
8656     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
8657     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
8658
8659     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
8660     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8661     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_DIFFUSE);
8662     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8663
8664     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
8665     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8666     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLORARG1, D3DTA_TFACTOR);
8667     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8668     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_RESULTARG, D3DTA_TEMP);
8669     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8670
8671     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_ADD);
8672     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8673     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLORARG1, D3DTA_CURRENT);
8674     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8675     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLORARG2, D3DTA_TEMP);
8676     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8677
8678     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_COLOROP, D3DTOP_DISABLE);
8679     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8680
8681     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0x0000ff00);
8682     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed, hr = %s\n", DXGetErrorString9(hr));
8683     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
8684     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed, hr = %s\n", DXGetErrorString9(hr));
8685
8686     hr = IDirect3DDevice9_BeginScene(device);
8687     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed, hr = %s\n", DXGetErrorString9(hr));
8688     if(SUCCEEDED(hr)) {
8689
8690         hr = IDirect3DDevice9_EndScene(device);
8691         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed, hr = %s\n", DXGetErrorString9(hr));
8692         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
8693         ok(hr == D3D_OK, "IDirect3DDevice9_DrawPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
8694     }
8695     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8696     color = getPixelColor(device, 320, 240);
8697     ok(color == 0x00FFFF00, "TSSARGTEMP test returned color 0x%08x, expected 0x00FFFF00\n", color);
8698
8699     /* Set stage 1 back to default */
8700     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_RESULTARG, D3DTA_CURRENT);
8701     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8702     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
8703     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8704     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
8705     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8706     hr = IDirect3DDevice9_SetTextureStageState(device, 2, D3DTSS_COLOROP, D3DTOP_DISABLE);
8707     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8708     hr = IDirect3DDevice9_SetTextureStageState(device, 3, D3DTSS_COLOROP, D3DTOP_DISABLE);
8709     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
8710 }
8711
8712 struct testdata
8713 {
8714     DWORD idxVertex; /* number of instances in the first stream */
8715     DWORD idxColor; /* number of instances in the second stream */
8716     DWORD idxInstance; /* should be 1 ?? */
8717     DWORD color1; /* color 1 instance */
8718     DWORD color2; /* color 2 instance */
8719     DWORD color3; /* color 3 instance */
8720     DWORD color4; /* color 4 instance */
8721     WORD strVertex; /* specify which stream to use 0-2*/
8722     WORD strColor;
8723     WORD strInstance;
8724 };
8725
8726 static const struct testdata testcases[]=
8727 {
8728     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  0 */
8729     {3, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0, 1, 2}, /*  1 */
8730     {2, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0, 1, 2}, /*  2 */
8731     {1, 4, 1, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0, 1, 2}, /*  3 */
8732     {0, 4, 1, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0, 1, 2}, /*  4 */
8733     {4, 3, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  5 */
8734     {4, 2, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  6 */
8735     {4, 1, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  7 */
8736     {4, 0, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 1, 2}, /*  8 */
8737     {3, 3, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ffffff, 0, 1, 2}, /*  9 */
8738     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 1, 0, 2}, /* 10 */
8739     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0, 2, 1}, /* 11 */
8740     {4, 4, 1, 0x00ff0000, 0x00ffffff, 0x00ffffff, 0x00ffffff, 2, 3, 1}, /* 12 */
8741     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 2, 0, 1}, /* 13 */
8742     {4, 4, 1, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 1, 2, 3}, /* 14 */
8743 /*
8744     This case is handled in a stand alone test, SetStreamSourceFreq(0,(D3DSTREAMSOURCE_INSTANCEDATA | 1))  has to return D3DERR_INVALIDCALL!
8745     {4, 4, 1, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 2, 1, 0, D3DERR_INVALIDCALL},
8746 */
8747 };
8748
8749 /* Drawing Indexed Geometry with instances*/
8750 static void stream_test(IDirect3DDevice9 *device)
8751 {
8752     IDirect3DVertexBuffer9 *vb = NULL;
8753     IDirect3DVertexBuffer9 *vb2 = NULL;
8754     IDirect3DVertexBuffer9 *vb3 = NULL;
8755     IDirect3DIndexBuffer9 *ib = NULL;
8756     IDirect3DVertexDeclaration9 *pDecl = NULL;
8757     IDirect3DVertexShader9 *shader = NULL;
8758     HRESULT hr;
8759     BYTE *data;
8760     DWORD color;
8761     DWORD ind;
8762     int i;
8763
8764     const DWORD shader_code[] =
8765     {
8766         0xfffe0101,                                     /* vs_1_1 */
8767         0x0000001f, 0x80000000, 0x900f0000,             /* dcl_position v0 */
8768         0x0000001f, 0x8000000a, 0x900f0001,             /* dcl_color0 v1 */
8769         0x0000001f, 0x80000005, 0x900f0002,             /* dcl_texcoord v2 */
8770         0x00000001, 0x800f0000, 0x90e40000,             /* mov r0, v0 */
8771         0x00000002, 0xc00f0000, 0x80e40000, 0x90e40002, /* add oPos, r0, v2 */
8772         0x00000001, 0xd00f0000, 0x90e40001,             /* mov oD0, v1 */
8773         0x0000ffff
8774     };
8775
8776     const float quad[][3] =
8777     {
8778         {-0.5f, -0.5f,  1.1f}, /*0 */
8779         {-0.5f,  0.5f,  1.1f}, /*1 */
8780         { 0.5f, -0.5f,  1.1f}, /*2 */
8781         { 0.5f,  0.5f,  1.1f}, /*3 */
8782     };
8783
8784     const float vertcolor[][4] =
8785     {
8786         {1.0f, 0.0f, 0.0f, 1.0f}, /*0 */
8787         {1.0f, 0.0f, 0.0f, 1.0f}, /*1 */
8788         {1.0f, 0.0f, 0.0f, 1.0f}, /*2 */
8789         {1.0f, 0.0f, 0.0f, 1.0f}, /*3 */
8790     };
8791
8792     /* 4 position for 4 instances */
8793     const float instancepos[][3] =
8794     {
8795         {-0.6f,-0.6f, 0.0f},
8796         { 0.6f,-0.6f, 0.0f},
8797         { 0.6f, 0.6f, 0.0f},
8798         {-0.6f, 0.6f, 0.0f},
8799     };
8800
8801     short indices[] = {0, 1, 2, 1, 2, 3};
8802
8803     D3DVERTEXELEMENT9 decl[] =
8804     {
8805         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
8806         {1, 0,  D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
8807         {2, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
8808         D3DDECL_END()
8809     };
8810
8811     /* set the default value because it isn't done in wine? */
8812     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 1);
8813     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %s\n", DXGetErrorString9(hr));
8814
8815     /* check for D3DSTREAMSOURCE_INDEXEDDATA at stream0 */
8816     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 0, (D3DSTREAMSOURCE_INSTANCEDATA | 1));
8817     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetStreamSourceFreq failed with %s\n", DXGetErrorString9(hr));
8818
8819     /* check wrong cases */
8820     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 0);
8821     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetStreamSourceFreq failed with %s\n", DXGetErrorString9(hr));
8822     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
8823     ok(hr == D3D_OK && ind == 1, "IDirect3DDevice9_GetStreamSourceFreq failed with %s\n", DXGetErrorString9(hr));
8824     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 2);
8825     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %s\n", DXGetErrorString9(hr));
8826     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
8827     ok(hr == D3D_OK && ind == 2, "IDirect3DDevice9_GetStreamSourceFreq failed with %s\n", DXGetErrorString9(hr));
8828     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, (D3DSTREAMSOURCE_INDEXEDDATA | 0));
8829     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %s\n", DXGetErrorString9(hr));
8830     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
8831     ok(hr == D3D_OK && ind == (D3DSTREAMSOURCE_INDEXEDDATA | 0), "IDirect3DDevice9_GetStreamSourceFreq failed with %s\n", DXGetErrorString9(hr));
8832     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, (D3DSTREAMSOURCE_INSTANCEDATA | 0));
8833     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %s\n", DXGetErrorString9(hr));
8834     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
8835     ok(hr == D3D_OK && ind == (0 | D3DSTREAMSOURCE_INSTANCEDATA), "IDirect3DDevice9_GetStreamSourceFreq failed with %s\n", DXGetErrorString9(hr));
8836     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, (D3DSTREAMSOURCE_INSTANCEDATA | D3DSTREAMSOURCE_INDEXEDDATA | 0));
8837     ok(hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_SetStreamSourceFreq failed with %s\n", DXGetErrorString9(hr));
8838     hr = IDirect3DDevice9_GetStreamSourceFreq(device, 1, &ind);
8839     ok(hr == D3D_OK && ind == (0 | D3DSTREAMSOURCE_INSTANCEDATA), "IDirect3DDevice9_GetStreamSourceFreq failed with %s\n", DXGetErrorString9(hr));
8840
8841     /* set the default value back */
8842     hr = IDirect3DDevice9_SetStreamSourceFreq(device, 1, 1);
8843     ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %s\n", DXGetErrorString9(hr));
8844
8845     /* create all VertexBuffers*/
8846     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, 0, D3DPOOL_MANAGED, &vb, NULL);
8847     ok(hr == D3D_OK, "CreateVertexBuffer failed with %s\n", DXGetErrorString9(hr));
8848     if(!vb) {
8849         skip("Failed to create a vertex buffer\n");
8850         return;
8851     }
8852     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(vertcolor), 0, 0, D3DPOOL_MANAGED, &vb2, NULL);
8853     ok(hr == D3D_OK, "CreateVertexBuffer failed with %s\n", DXGetErrorString9(hr));
8854     if(!vb2) {
8855         skip("Failed to create a vertex buffer\n");
8856         goto out;
8857     }
8858     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(instancepos), 0, 0, D3DPOOL_MANAGED, &vb3, NULL);
8859     ok(hr == D3D_OK, "CreateVertexBuffer failed with %s\n", DXGetErrorString9(hr));
8860     if(!vb3) {
8861         skip("Failed to create a vertex buffer\n");
8862         goto out;
8863     }
8864
8865     /* create IndexBuffer*/
8866     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, NULL);
8867     ok(hr == D3D_OK, "IDirect3DDevice9_CreateIndexBuffer failed with %s\n", DXGetErrorString9(hr));
8868     if(!ib) {
8869         skip("Failed to create a index buffer\n");
8870         goto out;
8871     }
8872
8873     /* copy all Buffers (Vertex + Index)*/
8874     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), (void **) &data, 0);
8875     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
8876     memcpy(data, quad, sizeof(quad));
8877     hr = IDirect3DVertexBuffer9_Unlock(vb);
8878     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr));
8879     hr = IDirect3DVertexBuffer9_Lock(vb2, 0, sizeof(vertcolor), (void **) &data, 0);
8880     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
8881     memcpy(data, vertcolor, sizeof(vertcolor));
8882     hr = IDirect3DVertexBuffer9_Unlock(vb2);
8883     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr));
8884     hr = IDirect3DVertexBuffer9_Lock(vb3, 0, sizeof(instancepos), (void **) &data, 0);
8885     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
8886     memcpy(data, instancepos, sizeof(instancepos));
8887     hr = IDirect3DVertexBuffer9_Unlock(vb3);
8888     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr));
8889     hr = IDirect3DIndexBuffer9_Lock(ib, 0, sizeof(indices), (void **) &data, 0);
8890     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
8891     memcpy(data, indices, sizeof(indices));
8892     hr = IDirect3DIndexBuffer9_Unlock(ib);
8893     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr));
8894
8895     /* create VertexShader */
8896     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
8897     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexShader failed hr=%s\n", DXGetErrorString9(hr));
8898     if(!shader) {
8899         skip("Failed to create a vetex shader\n");
8900         goto out;
8901     }
8902
8903     hr = IDirect3DDevice9_SetVertexShader(device, shader);
8904     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetVertexShader failed hr=%s\n", DXGetErrorString9(hr));
8905
8906     hr = IDirect3DDevice9_SetIndices(device, ib);
8907     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr));
8908
8909     /* run all tests */
8910     for( i = 0; i < sizeof(testcases)/sizeof(testcases[0]); ++i)
8911     {
8912         struct testdata act = testcases[i];
8913         decl[0].Stream = act.strVertex;
8914         decl[1].Stream = act.strColor;
8915         decl[2].Stream = act.strInstance;
8916         /* create VertexDeclarations */
8917         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl, &pDecl);
8918         ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateVertexDeclaration failed hr=%s (case %i)\n", DXGetErrorString9(hr), i);
8919
8920         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
8921         ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x (case %i)\n", hr, i);
8922
8923         hr = IDirect3DDevice9_BeginScene(device);
8924         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x (case %i)\n", hr, i);
8925         if(SUCCEEDED(hr))
8926         {
8927             hr = IDirect3DDevice9_SetVertexDeclaration(device, pDecl);
8928             ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %08x (case %i)\n", hr, i);
8929
8930             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strVertex, (D3DSTREAMSOURCE_INDEXEDDATA | act.idxVertex));
8931             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %s (case %i)\n", DXGetErrorString9(hr), i);
8932             hr = IDirect3DDevice9_SetStreamSource(device, act.strVertex, vb, 0, sizeof(quad[0]));
8933             ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %s (case %i)\n", DXGetErrorString9(hr), i);
8934
8935             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strColor, (D3DSTREAMSOURCE_INDEXEDDATA | act.idxColor));
8936             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %s (case %i)\n", DXGetErrorString9(hr), i);
8937             hr = IDirect3DDevice9_SetStreamSource(device, act.strColor, vb2, 0, sizeof(vertcolor[0]));
8938             ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %s (case %i)\n", DXGetErrorString9(hr), i);
8939
8940             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strInstance, (D3DSTREAMSOURCE_INSTANCEDATA | act.idxInstance));
8941             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %s (case %i)\n", DXGetErrorString9(hr), i);
8942             hr = IDirect3DDevice9_SetStreamSource(device, act.strInstance, vb3, 0, sizeof(instancepos[0]));
8943             ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %s (case %i)\n", DXGetErrorString9(hr), i);
8944
8945             /* don't know if this is right (1*3 and 4*1)*/
8946             hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 0, 1 * 3 , 0, 4*1);
8947             ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitive failed with %08x (case %i)\n", hr, i);
8948             hr = IDirect3DDevice9_EndScene(device);
8949             ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x (case %i)\n", hr, i);
8950
8951             /* set all StreamSource && StreamSourceFreq back to default */
8952             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.strVertex, 1);
8953             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %s (case %i)\n", DXGetErrorString9(hr), i);
8954             hr = IDirect3DDevice9_SetStreamSource(device, act.strVertex, NULL, 0, 0);
8955             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
8956             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.idxColor, 1);
8957             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %s (case %i)\n", DXGetErrorString9(hr), i);
8958             hr = IDirect3DDevice9_SetStreamSource(device, act.idxColor, NULL, 0, 0);
8959             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
8960             hr = IDirect3DDevice9_SetStreamSourceFreq(device, act.idxInstance, 1);
8961             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSourceFreq failed with %s (case %i)\n", DXGetErrorString9(hr), i);
8962             hr = IDirect3DDevice9_SetStreamSource(device, act.idxInstance, NULL, 0, 0);
8963             ok(hr == D3D_OK, "IDirect3DDevice9_SetStreamSource failed with %08x (case %i)\n", hr, i);
8964         }
8965
8966         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
8967         ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x (case %i)\n", hr, i);
8968
8969         hr = IDirect3DVertexDeclaration9_Release(pDecl);
8970         ok(hr == D3D_OK, "IDirect3DVertexDeclaration9_Release failed with %08x (case %i)\n", hr, i);
8971
8972         color = getPixelColor(device, 160, 360);
8973         ok(color == act.color1, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color1, i);
8974         color = getPixelColor(device, 480, 360);
8975         ok(color == act.color2, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color2, i);
8976         color = getPixelColor(device, 480, 120);
8977         ok(color == act.color3, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color3, i);
8978         color = getPixelColor(device, 160, 120);
8979         ok(color == act.color4, "has color 0x%08x, expected 0x%08x (case %i)\n", color, act.color4, i);
8980     }
8981
8982     hr = IDirect3DDevice9_SetIndices(device, NULL);
8983     ok(hr == D3D_OK, "IDirect3DDevice9_SetIndices failed with %08x\n", hr);
8984
8985 out:
8986     if(vb) IDirect3DVertexBuffer9_Release(vb);
8987     if(vb2)IDirect3DVertexBuffer9_Release(vb2);
8988     if(vb3)IDirect3DVertexBuffer9_Release(vb3);
8989     if(ib)IDirect3DIndexBuffer9_Release(ib);
8990     if(shader)IDirect3DVertexShader9_Release(shader);
8991 }
8992
8993 static void np2_stretch_rect_test(IDirect3DDevice9 *device) {
8994     IDirect3DSurface9 *src = NULL, *dst = NULL, *backbuffer = NULL;
8995     IDirect3DTexture9 *dsttex = NULL;
8996     HRESULT hr;
8997     DWORD color;
8998     D3DRECT r1 = {0,  0,  50,  50 };
8999     D3DRECT r2 = {50, 0,  100, 50 };
9000     D3DRECT r3 = {50, 50, 100, 100};
9001     D3DRECT r4 = {0,  50,  50, 100};
9002     const float quad[] = {
9003         -1.0,   -1.0,   0.1,    0.0,    0.0,
9004          1.0,   -1.0,   0.1,    1.0,    0.0,
9005         -1.0,    1.0,   0.1,    0.0,    1.0,
9006          1.0,    1.0,   0.1,    1.0,    1.0,
9007     };
9008
9009     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
9010     ok(hr == D3D_OK, "IDirect3DDevice9_GetBackBuffer failed with %s\n", DXGetErrorString9(hr));
9011
9012     hr = IDirect3DDevice9_CreateRenderTarget(device, 100, 100, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &src, NULL );
9013     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_CreateRenderTarget failed with %s\n", DXGetErrorString9(hr));
9014     hr = IDirect3DDevice9_CreateTexture(device, 25, 25, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &dsttex, NULL);
9015     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "IDirect3DDevice9_CreateTexture failed with %s\n", DXGetErrorString9(hr));
9016
9017     if(!src || !dsttex) {
9018         skip("One or more test resources could not be created\n");
9019         goto cleanup;
9020     }
9021
9022     hr = IDirect3DTexture9_GetSurfaceLevel(dsttex, 0, &dst);
9023     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel failed with %s\n", DXGetErrorString9(hr));
9024
9025     hr = IDirect3DDevice9_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0xff00ffff, 0.0, 0);
9026     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
9027
9028     /* Clear the StretchRect destination for debugging */
9029     hr = IDirect3DDevice9_SetRenderTarget(device, 0, dst);
9030     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %s\n", DXGetErrorString9(hr));
9031     hr = IDirect3DDevice9_Clear(device, 1, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
9032     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
9033
9034     hr = IDirect3DDevice9_SetRenderTarget(device, 0, src);
9035     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %s\n", DXGetErrorString9(hr));
9036
9037     hr = IDirect3DDevice9_Clear(device, 1, &r1, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
9038     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
9039     hr = IDirect3DDevice9_Clear(device, 1, &r2, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
9040     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
9041     hr = IDirect3DDevice9_Clear(device, 1, &r3, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
9042     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
9043     hr = IDirect3DDevice9_Clear(device, 1, &r4, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
9044     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
9045
9046     /* Stretchrect before setting the render target back to the backbuffer. This will make Wine use
9047      * the target -> texture GL blit path
9048      */
9049     hr = IDirect3DDevice9_StretchRect(device, src, NULL, dst, NULL, D3DTEXF_POINT);
9050     ok(hr == D3D_OK, "IDirect3DDevice9_StretchRect failed with %s\n", DXGetErrorString9(hr));
9051     IDirect3DSurface9_Release(dst);
9052
9053     hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
9054     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderTarget failed with %s\n", DXGetErrorString9(hr));
9055
9056     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) dsttex);
9057     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
9058     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
9059     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
9060     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
9061     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
9062     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9063     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
9064
9065     hr = IDirect3DDevice9_BeginScene(device);
9066     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
9067     if(SUCCEEDED(hr)) {
9068         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float) * 5);
9069         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
9070         hr = IDirect3DDevice9_EndScene(device);
9071         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
9072     }
9073
9074     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9075     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
9076     color = getPixelColor(device, 160, 360);
9077     ok(color == 0x00ff0000, "stretchrect: Pixel 160,360 has color 0x%08x, expected 0x00ff0000\n", color);
9078     color = getPixelColor(device, 480, 360);
9079     ok(color == 0x0000ff00, "stretchrect: Pixel 480,360 has color 0x%08x, expected 0x0000ff00\n", color);
9080     color = getPixelColor(device, 480, 120);
9081     ok(color == 0x000000ff, "stretchrect: Pixel 480,120 has color 0x%08x, expected 0x000000ff\n", color);
9082     color = getPixelColor(device, 160, 120);
9083     ok(color == 0x00000000, "stretchrect: Pixel 160,120 has color 0x%08x, expected 0x00000000\n", color);
9084
9085     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
9086     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
9087     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
9088     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
9089
9090 cleanup:
9091     if(src) IDirect3DSurface9_Release(src);
9092     if(backbuffer) IDirect3DSurface9_Release(backbuffer);
9093     if(dsttex) IDirect3DTexture9_Release(dsttex);
9094 }
9095
9096 static void texop_test(IDirect3DDevice9 *device)
9097 {
9098     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
9099     IDirect3DTexture9 *texture = NULL;
9100     D3DLOCKED_RECT locked_rect;
9101     D3DCOLOR color;
9102     D3DCAPS9 caps;
9103     HRESULT hr;
9104     int i;
9105
9106     static const struct {
9107         float x, y, z;
9108         float s, t;
9109         D3DCOLOR diffuse;
9110     } quad[] = {
9111         {-1.0f, -1.0f, 0.1f, -1.0f, -1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)},
9112         {-1.0f,  1.0f, 0.1f, -1.0f,  1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)},
9113         { 1.0f, -1.0f, 0.1f,  1.0f, -1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)},
9114         { 1.0f,  1.0f, 0.1f,  1.0f,  1.0f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00)}
9115     };
9116
9117     static const D3DVERTEXELEMENT9 decl_elements[] = {
9118         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
9119         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
9120         {0, 20, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
9121         D3DDECL_END()
9122     };
9123
9124     static const struct {
9125         D3DTEXTUREOP op;
9126         const char *name;
9127         DWORD caps_flag;
9128         D3DCOLOR result;
9129     } test_data[] = {
9130         {D3DTOP_SELECTARG1,                "SELECTARG1",                D3DTEXOPCAPS_SELECTARG1,                D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
9131         {D3DTOP_SELECTARG2,                "SELECTARG2",                D3DTEXOPCAPS_SELECTARG2,                D3DCOLOR_ARGB(0x00, 0x33, 0x33, 0x33)},
9132         {D3DTOP_MODULATE,                  "MODULATE",                  D3DTEXOPCAPS_MODULATE,                  D3DCOLOR_ARGB(0x00, 0x00, 0x33, 0x00)},
9133         {D3DTOP_MODULATE2X,                "MODULATE2X",                D3DTEXOPCAPS_MODULATE2X,                D3DCOLOR_ARGB(0x00, 0x00, 0x66, 0x00)},
9134         {D3DTOP_MODULATE4X,                "MODULATE4X",                D3DTEXOPCAPS_MODULATE4X,                D3DCOLOR_ARGB(0x00, 0x00, 0xcc, 0x00)},
9135         {D3DTOP_ADD,                       "ADD",                       D3DTEXOPCAPS_ADD,                       D3DCOLOR_ARGB(0x00, 0x33, 0xff, 0x33)},
9136         {D3DTOP_ADDSIGNED,                 "ADDSIGNED",                 D3DTEXOPCAPS_ADDSIGNED,                 D3DCOLOR_ARGB(0x00, 0x00, 0xb2, 0x00)},
9137         {D3DTOP_ADDSIGNED2X,               "ADDSIGNED2X",               D3DTEXOPCAPS_ADDSIGNED2X,               D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
9138         {D3DTOP_SUBTRACT,                  "SUBTRACT",                  D3DTEXOPCAPS_SUBTRACT,                  D3DCOLOR_ARGB(0x00, 0x00, 0xcc, 0x00)},
9139         {D3DTOP_ADDSMOOTH,                 "ADDSMOOTH",                 D3DTEXOPCAPS_ADDSMOOTH,                 D3DCOLOR_ARGB(0x00, 0x33, 0xff, 0x33)},
9140         {D3DTOP_BLENDDIFFUSEALPHA,         "BLENDDIFFUSEALPHA",         D3DTEXOPCAPS_BLENDDIFFUSEALPHA,         D3DCOLOR_ARGB(0x00, 0x22, 0x77, 0x22)},
9141         {D3DTOP_BLENDTEXTUREALPHA,         "BLENDTEXTUREALPHA",         D3DTEXOPCAPS_BLENDTEXTUREALPHA,         D3DCOLOR_ARGB(0x00, 0x14, 0xad, 0x14)},
9142         {D3DTOP_BLENDFACTORALPHA,          "BLENDFACTORALPHA",          D3DTEXOPCAPS_BLENDFACTORALPHA,          D3DCOLOR_ARGB(0x00, 0x07, 0xe4, 0x07)},
9143         {D3DTOP_BLENDTEXTUREALPHAPM,       "BLENDTEXTUREALPHAPM",       D3DTEXOPCAPS_BLENDTEXTUREALPHAPM,       D3DCOLOR_ARGB(0x00, 0x14, 0xff, 0x14)},
9144         {D3DTOP_BLENDCURRENTALPHA,         "BLENDCURRENTALPHA",         D3DTEXOPCAPS_BLENDCURRENTALPHA,         D3DCOLOR_ARGB(0x00, 0x22, 0x77, 0x22)},
9145         {D3DTOP_MODULATEALPHA_ADDCOLOR,    "MODULATEALPHA_ADDCOLOR",    D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR,    D3DCOLOR_ARGB(0x00, 0x1f, 0xff, 0x1f)},
9146         {D3DTOP_MODULATECOLOR_ADDALPHA,    "MODULATECOLOR_ADDALPHA",    D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA,    D3DCOLOR_ARGB(0x00, 0x99, 0xcc, 0x99)},
9147         {D3DTOP_MODULATEINVALPHA_ADDCOLOR, "MODULATEINVALPHA_ADDCOLOR", D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR, D3DCOLOR_ARGB(0x00, 0x14, 0xff, 0x14)},
9148         {D3DTOP_MODULATEINVCOLOR_ADDALPHA, "MODULATEINVCOLOR_ADDALPHA", D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA, D3DCOLOR_ARGB(0x00, 0xcc, 0x99, 0xcc)},
9149         /* BUMPENVMAP & BUMPENVMAPLUMINANCE have their own tests */
9150         {D3DTOP_DOTPRODUCT3,               "DOTPRODUCT2",               D3DTEXOPCAPS_DOTPRODUCT3,               D3DCOLOR_ARGB(0x00, 0x99, 0x99, 0x99)},
9151         {D3DTOP_MULTIPLYADD,               "MULTIPLYADD",               D3DTEXOPCAPS_MULTIPLYADD,               D3DCOLOR_ARGB(0x00, 0xff, 0x33, 0x00)},
9152         {D3DTOP_LERP,                      "LERP",                      D3DTEXOPCAPS_LERP,                      D3DCOLOR_ARGB(0x00, 0x00, 0x33, 0x33)},
9153     };
9154
9155     memset(&caps, 0, sizeof(caps));
9156     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
9157     ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9158
9159     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
9160     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9161     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
9162     ok(SUCCEEDED(hr), "SetVertexDeclaration failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9163
9164     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, NULL);
9165     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9166     hr = IDirect3DTexture9_LockRect(texture, 0, &locked_rect, NULL, 0);
9167     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9168     *((DWORD *)locked_rect.pBits) = D3DCOLOR_ARGB(0x99, 0x00, 0xff, 0x00);
9169     hr = IDirect3DTexture9_UnlockRect(texture, 0);
9170     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9171     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
9172     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9173
9174     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG0, D3DTA_DIFFUSE);
9175     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9176     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
9177     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9178     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
9179     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9180
9181     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
9182     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9183
9184     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
9185     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9186     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0xdd333333);
9187     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9188     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA);
9189     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9190
9191     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
9192     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9193
9194     for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
9195     {
9196         if (!(caps.TextureOpCaps & test_data[i].caps_flag))
9197         {
9198             skip("tex operation %s not supported\n", test_data[i].name);
9199             continue;
9200         }
9201
9202         hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, test_data[i].op);
9203         ok(SUCCEEDED(hr), "SetTextureStageState (%s) failed with 0x%08x (%s)\n",
9204                 test_data[i].name, hr, DXGetErrorString9(hr));
9205
9206         hr = IDirect3DDevice9_BeginScene(device);
9207         ok(SUCCEEDED(hr), "BeginScene failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9208
9209         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
9210         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9211
9212         hr = IDirect3DDevice9_EndScene(device);
9213         ok(SUCCEEDED(hr), "EndScene failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9214
9215         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
9216         ok(SUCCEEDED(hr), "Present failed with 0x%08x (%s)\n", hr, DXGetErrorString9(hr));
9217
9218         color = getPixelColor(device, 320, 240);
9219         ok(color_match(color, test_data[i].result, 1), "Operation %s returned color 0x%08x, expected 0x%08x\n",
9220                 test_data[i].name, color, test_data[i].result);
9221     }
9222
9223     if (texture) IDirect3DTexture9_Release(texture);
9224     if (vertex_declaration) IDirect3DVertexDeclaration9_Release(vertex_declaration);
9225 }
9226
9227 START_TEST(visual)
9228 {
9229     IDirect3DDevice9 *device_ptr;
9230     D3DCAPS9 caps;
9231     HRESULT hr;
9232     DWORD color;
9233
9234     d3d9_handle = LoadLibraryA("d3d9.dll");
9235     if (!d3d9_handle)
9236     {
9237         skip("Could not load d3d9.dll\n");
9238         return;
9239     }
9240
9241     device_ptr = init_d3d9();
9242     if (!device_ptr)
9243     {
9244         skip("Creating the device failed\n");
9245         return;
9246     }
9247
9248     IDirect3DDevice9_GetDeviceCaps(device_ptr, &caps);
9249
9250     /* Check for the reliability of the returned data */
9251     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
9252     if(FAILED(hr))
9253     {
9254         skip("Clear failed, can't assure correctness of the test results, skipping\n");
9255         goto cleanup;
9256     }
9257     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
9258
9259     color = getPixelColor(device_ptr, 1, 1);
9260     if(color !=0x00ff0000)
9261     {
9262         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
9263         goto cleanup;
9264     }
9265
9266     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xff00ddee, 0.0, 0);
9267     if(FAILED(hr))
9268     {
9269         skip("Clear failed, can't assure correctness of the test results, skipping\n");
9270         goto cleanup;
9271     }
9272     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
9273
9274     color = getPixelColor(device_ptr, 639, 479);
9275     if(color != 0x0000ddee)
9276     {
9277         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
9278         goto cleanup;
9279     }
9280
9281     /* Now execute the real tests */
9282     stretchrect_test(device_ptr);
9283     lighting_test(device_ptr);
9284     clear_test(device_ptr);
9285     fog_test(device_ptr);
9286     if(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
9287     {
9288         test_cube_wrap(device_ptr);
9289     } else {
9290         skip("No cube texture support\n");
9291     }
9292     z_range_test(device_ptr);
9293     if(caps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)
9294     {
9295         maxmip_test(device_ptr);
9296     }
9297     else
9298     {
9299         skip("No mipmap support\n");
9300     }
9301     offscreen_test(device_ptr);
9302     alpha_test(device_ptr);
9303     shademode_test(device_ptr);
9304     srgbtexture_test(device_ptr);
9305     release_buffer_test(device_ptr);
9306     float_texture_test(device_ptr);
9307     g16r16_texture_test(device_ptr);
9308     pixelshader_blending_test(device_ptr);
9309     texture_transform_flags_test(device_ptr);
9310     autogen_mipmap_test(device_ptr);
9311     fixed_function_decl_test(device_ptr);
9312     conditional_np2_repeat_test(device_ptr);
9313     fixed_function_bumpmap_test(device_ptr);
9314     if(caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) {
9315         stencil_cull_test(device_ptr);
9316     } else {
9317         skip("No two sided stencil support\n");
9318     }
9319     pointsize_test(device_ptr);
9320     tssargtemp_test(device_ptr);
9321     np2_stretch_rect_test(device_ptr);
9322
9323     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1))
9324     {
9325         test_constant_clamp_vs(device_ptr);
9326         test_compare_instructions(device_ptr);
9327     }
9328     else skip("No vs_1_1 support\n");
9329
9330     if (caps.VertexShaderVersion >= D3DVS_VERSION(2, 0))
9331     {
9332         test_mova(device_ptr);
9333         if (caps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) {
9334             test_vshader_input(device_ptr);
9335             test_vshader_float16(device_ptr);
9336             stream_test(device_ptr);
9337         } else {
9338             skip("No vs_3_0 support\n");
9339         }
9340     }
9341     else skip("No vs_2_0 support\n");
9342
9343     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1) && caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
9344     {
9345         fog_with_shader_test(device_ptr);
9346         fog_srgbwrite_test(device_ptr);
9347     }
9348     else skip("No vs_1_1 and ps_1_1 support\n");
9349
9350     if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
9351     {
9352         texbem_test(device_ptr);
9353         texdepth_test(device_ptr);
9354         texkill_test(device_ptr);
9355         x8l8v8u8_test(device_ptr);
9356         if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 4)) {
9357             constant_clamp_ps_test(device_ptr);
9358             cnd_test(device_ptr);
9359             if (caps.PixelShaderVersion >= D3DPS_VERSION(2, 0)) {
9360                 dp2add_ps_test(device_ptr);
9361                 if (caps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) {
9362                     nested_loop_test(device_ptr);
9363                     fixed_function_varying_test(device_ptr);
9364                     vFace_register_test(device_ptr);
9365                     vpos_register_test(device_ptr);
9366                     multiple_rendertargets_test(device_ptr);
9367                     if(caps.VertexShaderVersion >= D3DVS_VERSION(3, 0)) {
9368                         vshader_version_varying_test(device_ptr);
9369                         pshader_version_varying_test(device_ptr);
9370                     } else {
9371                         skip("No vs_3_0 support\n");
9372                     }
9373                 } else {
9374                     skip("No ps_3_0 support\n");
9375                 }
9376             } else {
9377                 skip("No ps_2_0 support\n");
9378             }
9379         }
9380     }
9381     else skip("No ps_1_1 support\n");
9382     texop_test(device_ptr);
9383
9384 cleanup:
9385     if(device_ptr) {
9386         ULONG ref;
9387
9388         D3DPRESENT_PARAMETERS present_parameters;
9389         IDirect3DSwapChain9 *swapchain;
9390         IDirect3DDevice9_GetSwapChain(device_ptr, 0, &swapchain);
9391         IDirect3DSwapChain9_GetPresentParameters(swapchain, &present_parameters);
9392         IDirect3DSwapChain9_Release(swapchain);
9393         ref = IDirect3DDevice9_Release(device_ptr);
9394         DestroyWindow(present_parameters.hDeviceWindow);
9395         ok(ref == 0, "The device was not properly freed: refcount %u\n", ref);
9396     }
9397 }