wined3d: Accept rendering to sublevels with backbuffer orm.
[wine] / dlls / d3d9 / tests / visual.c
1 /*
2  * Copyright 2005, 2007 Henri Verbeet
3  * Copyright (C) 2007 Stefan Dösinger(for CodeWeavers)
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 /* This test framework allows limited testing of rendering results. Things are rendered, shown on
21  * the framebuffer, read back from there and compared to expected colors.
22  *
23  * However, neither d3d nor opengl is guaranteed to be pixel exact, and thus the capability of this test
24  * is rather limited. As a general guideline for adding tests, do not rely on corner pixels. Draw a big enough
25  * area which shows specific behavior(like a quad on the whole screen), and try to get resulting colos with
26  * all bits set or unset in all channels(like pure red, green, blue, white, black). Hopefully everything that
27  * causes visible results in games can be tested in a way that does not depend on pixel exactness
28  */
29
30 #define COBJMACROS
31 #include <d3d9.h>
32 #include <dxerr9.h>
33 #include "wine/test.h"
34
35 static HMODULE d3d9_handle = 0;
36
37 static HWND create_window(void)
38 {
39     WNDCLASS wc = {0};
40     HWND ret;
41     wc.lpfnWndProc = &DefWindowProc;
42     wc.lpszClassName = "d3d9_test_wc";
43     RegisterClass(&wc);
44
45     ret = CreateWindow("d3d9_test_wc", "d3d9_test",
46                         WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
47     return ret;
48 }
49
50 static DWORD getPixelColor(IDirect3DDevice9 *device, UINT x, UINT y)
51 {
52     DWORD ret;
53     IDirect3DSurface9 *surf;
54     HRESULT hr;
55     D3DLOCKED_RECT lockedRect;
56     RECT rectToLock = {x, y, x+1, y+1};
57
58     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 640, 480, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL);
59     if(FAILED(hr) || !surf )  /* This is not a test */
60     {
61         trace("Can't create an offscreen plain surface to read the render target data, hr=%s\n", DXGetErrorString9(hr));
62         return 0xdeadbeef;
63     }
64
65     hr = IDirect3DDevice9_GetFrontBufferData(device, 0, surf);
66     if(FAILED(hr))
67     {
68         trace("Can't read the front buffer data, hr=%s\n", DXGetErrorString9(hr));
69         ret = 0xdeadbeed;
70         goto out;
71     }
72
73     hr = IDirect3DSurface9_LockRect(surf, &lockedRect, &rectToLock, D3DLOCK_READONLY);
74     if(FAILED(hr))
75     {
76         trace("Can't lock the offscreen surface, hr=%s\n", DXGetErrorString9(hr));
77         ret = 0xdeadbeec;
78         goto out;
79     }
80
81     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
82      * really important for these tests
83      */
84     ret = ((DWORD *) lockedRect.pBits)[0] & 0x00ffffff;
85     hr = IDirect3DSurface9_UnlockRect(surf);
86     if(FAILED(hr))
87     {
88         trace("Can't unlock the offscreen surface, hr=%s\n", DXGetErrorString9(hr));
89     }
90
91 out:
92     if(surf) IDirect3DSurface9_Release(surf);
93     return ret;
94 }
95
96 static IDirect3DDevice9 *init_d3d9(void)
97 {
98     IDirect3D9 * (__stdcall * d3d9_create)(UINT SDKVersion) = 0;
99     IDirect3D9 *d3d9_ptr = 0;
100     IDirect3DDevice9 *device_ptr = 0;
101     D3DPRESENT_PARAMETERS present_parameters;
102     HRESULT hr;
103
104     d3d9_create = (void *)GetProcAddress(d3d9_handle, "Direct3DCreate9");
105     ok(d3d9_create != NULL, "Failed to get address of Direct3DCreate9\n");
106     if (!d3d9_create) return NULL;
107
108     d3d9_ptr = d3d9_create(D3D_SDK_VERSION);
109     ok(d3d9_ptr != NULL, "Failed to create IDirect3D9 object\n");
110     if (!d3d9_ptr) return NULL;
111
112     ZeroMemory(&present_parameters, sizeof(present_parameters));
113     present_parameters.Windowed = FALSE;
114     present_parameters.hDeviceWindow = create_window();
115     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
116     present_parameters.BackBufferWidth = 640;
117     present_parameters.BackBufferHeight = 480;
118     present_parameters.BackBufferFormat = D3DFMT_X8R8G8B8;
119     present_parameters.EnableAutoDepthStencil = TRUE;
120     present_parameters.AutoDepthStencilFormat = D3DFMT_D16;
121
122     hr = IDirect3D9_CreateDevice(d3d9_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, present_parameters.hDeviceWindow, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
123     ok(hr == D3D_OK || hr == D3DERR_NOTAVAILABLE, "IDirect3D_CreateDevice returned: %s\n", DXGetErrorString9(hr));
124
125     return device_ptr;
126 }
127
128 struct vertex
129 {
130     float x, y, z;
131     DWORD diffuse;
132 };
133
134 struct nvertex
135 {
136     float x, y, z;
137     float nx, ny, nz;
138     DWORD diffuse;
139 };
140
141 static void lighting_test(IDirect3DDevice9 *device)
142 {
143     HRESULT hr;
144     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
145     DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
146     DWORD color;
147
148     float mat[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
149                       0.0f, 1.0f, 0.0f, 0.0f,
150                       0.0f, 0.0f, 1.0f, 0.0f,
151                       0.0f, 0.0f, 0.0f, 1.0f };
152
153     struct vertex unlitquad[] =
154     {
155         {-1.0f, -1.0f,   0.1f,                          0xffff0000},
156         {-1.0f,  0.0f,   0.1f,                          0xffff0000},
157         { 0.0f,  0.0f,   0.1f,                          0xffff0000},
158         { 0.0f, -1.0f,   0.1f,                          0xffff0000},
159     };
160     struct vertex litquad[] =
161     {
162         {-1.0f,  0.0f,   0.1f,                          0xff00ff00},
163         {-1.0f,  1.0f,   0.1f,                          0xff00ff00},
164         { 0.0f,  1.0f,   0.1f,                          0xff00ff00},
165         { 0.0f,  0.0f,   0.1f,                          0xff00ff00},
166     };
167     struct nvertex unlitnquad[] =
168     {
169         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
170         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
171         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
172         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
173     };
174     struct nvertex litnquad[] =
175     {
176         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
177         { 0.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
178         { 1.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
179         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
180     };
181     WORD Indices[] = {0, 1, 2, 2, 3, 0};
182
183     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
184     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
185
186     /* Setup some states that may cause issues */
187     hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(0), (D3DMATRIX *) mat);
188     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %s\n", DXGetErrorString9(hr));
189     hr = IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, (D3DMATRIX *)mat);
190     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %s\n", DXGetErrorString9(hr));
191     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, (D3DMATRIX *) mat);
192     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %s\n", DXGetErrorString9(hr));
193     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
194     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
195     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
196     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
197     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
198     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
199     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
200     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
201     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, FALSE);
202     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
203     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
204     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
205     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, FALSE);
206     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
207     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
208     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %s\n", DXGetErrorString9(hr));
209     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
210     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %s\n", DXGetErrorString9(hr));
211
212     hr = IDirect3DDevice9_SetFVF(device, fvf);
213     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
214
215     hr = IDirect3DDevice9_BeginScene(device);
216     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
217     if(hr == D3D_OK)
218     {
219         /* No lights are defined... That means, lit vertices should be entirely black */
220         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
221         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
222         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
223                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitquad, sizeof(unlitquad[0]));
224         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
225
226         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
227         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
228         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
229                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litquad, sizeof(litquad[0]));
230         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
231
232         hr = IDirect3DDevice9_SetFVF(device, nfvf);
233         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
234
235         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
236         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
237         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
238                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitnquad, sizeof(unlitnquad[0]));
239         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
240
241         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
242         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
243         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
244                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litnquad, sizeof(litnquad[0]));
245         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
246
247         IDirect3DDevice9_EndScene(device);
248         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
249     }
250
251     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
252
253     color = getPixelColor(device, 160, 360); /* lower left quad - unlit without normals */
254     ok(color == 0x00ff0000, "Unlit quad without normals has color %08x\n", color);
255     color = getPixelColor(device, 160, 120); /* upper left quad - lit without normals */
256     ok(color == 0x00000000, "Lit quad without normals has color %08x\n", color);
257     color = getPixelColor(device, 480, 360); /* lower left quad - unlit width normals */
258     ok(color == 0x000000ff, "Unlit quad width normals has color %08x\n", color);
259     color = getPixelColor(device, 480, 120); /* upper left quad - lit width normals */
260     ok(color == 0x00000000, "Lit quad width normals has color %08x\n", color);
261
262     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
263     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
264 }
265
266 static void clear_test(IDirect3DDevice9 *device)
267 {
268     /* Tests the correctness of clearing parameters */
269     HRESULT hr;
270     D3DRECT rect[2];
271     D3DRECT rect_negneg;
272     DWORD color;
273
274     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
275     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
276
277     /* Positive x, negative y */
278     rect[0].x1 = 0;
279     rect[0].y1 = 480;
280     rect[0].x2 = 320;
281     rect[0].y2 = 240;
282
283     /* Positive x, positive y */
284     rect[1].x1 = 0;
285     rect[1].y1 = 0;
286     rect[1].x2 = 320;
287     rect[1].y2 = 240;
288     /* Clear 2 rectangles with one call. Shows that a positive value is returned, but the negative rectangle
289      * is ignored, the positive is still cleared afterwards
290      */
291     hr = IDirect3DDevice9_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
292     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
293
294     /* negative x, negative y */
295     rect_negneg.x1 = 640;
296     rect_negneg.x1 = 240;
297     rect_negneg.x2 = 320;
298     rect_negneg.y2 = 0;
299     hr = IDirect3DDevice9_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
300     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
301
302     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
303
304     color = getPixelColor(device, 160, 360); /* lower left quad */
305     ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
306     color = getPixelColor(device, 160, 120); /* upper left quad */
307     ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
308     color = getPixelColor(device, 480, 360); /* lower right quad  */
309     ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
310     color = getPixelColor(device, 480, 120); /* upper right quad */
311     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
312 }
313
314 typedef struct {
315     float in[4];
316     DWORD out;
317 } test_data_t;
318
319 /*
320  *  c7      rounded     ARGB
321  * -2.4     -2          0x00ffff00
322  * -1.6     -2          0x00ffff00
323  * -0.4      0          0x0000ffff
324  *  0.4      0          0x0000ffff
325  *  1.6      2          0x00ff00ff
326  *  2.4      2          0x00ff00ff
327  */
328 static void test_mova(IDirect3DDevice9 *device)
329 {
330     static const DWORD mova_test[] = {
331         0xfffe0200,                                                             /* vs_2_0                       */
332         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
333         0x05000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0   */
334         0x05000051, 0xa00f0001, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, /* def c1, 1.0, 1.0, 0.0, 1.0   */
335         0x05000051, 0xa00f0002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, /* def c2, 0.0, 1.0, 0.0, 1.0   */
336         0x05000051, 0xa00f0003, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 0.0, 1.0, 1.0, 1.0   */
337         0x05000051, 0xa00f0004, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c4, 0.0, 0.0, 1.0, 1.0   */
338         0x05000051, 0xa00f0005, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, /* def c5, 1.0, 0.0, 1.0, 1.0   */
339         0x05000051, 0xa00f0006, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c6, 1.0, 1.0, 1.0, 1.0   */
340         0x0200002e, 0xb0010000, 0xa0000007,                                     /* mova a0.x, c7.x              */
341         0x03000001, 0xd00f0000, 0xa0e42003, 0xb0000000,                         /* mov oD0, c[a0.x + 3]         */
342         0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
343         0x0000ffff                                                              /* END                          */
344     };
345
346     static const test_data_t test_data[] = {
347         {{-2.4f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
348         {{-1.6f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
349         {{-0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
350         {{ 0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
351         {{ 1.6f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff},
352         {{ 2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff}
353     };
354
355     static const float quad[][3] = {
356         {-1.0f, -1.0f, 0.0f},
357         {-1.0f,  1.0f, 0.0f},
358         { 1.0f, -1.0f, 0.0f},
359         { 1.0f,  1.0f, 0.0f},
360     };
361
362     static const D3DVERTEXELEMENT9 decl_elements[] = {
363         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
364         D3DDECL_END()
365     };
366
367     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
368     IDirect3DVertexShader9 *mova_shader = NULL;
369     HRESULT hr;
370     int i;
371
372     hr = IDirect3DDevice9_CreateVertexShader(device, mova_test, &mova_shader);
373     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
374     hr = IDirect3DDevice9_SetVertexShader(device, mova_shader);
375     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
376
377     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
378     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
379     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
380     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
381
382     for (i = 0; i < (sizeof(test_data) / sizeof(test_data_t)); ++i)
383     {
384         DWORD color;
385
386         hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 7, test_data[i].in, 1);
387         ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
388
389         hr = IDirect3DDevice9_BeginScene(device);
390         ok(SUCCEEDED(hr), "BeginScene failed (%08x)\n", hr);
391
392         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], 3 * sizeof(float));
393         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
394
395         hr = IDirect3DDevice9_EndScene(device);
396         ok(SUCCEEDED(hr), "EndScene failed (%08x)\n", hr);
397
398         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
399         ok(SUCCEEDED(hr), "Present failed (%08x)\n", hr);
400
401         color = getPixelColor(device, 320, 240);
402         ok(color == test_data[i].out, "Expected color %08x, got %08x (for input %f)\n", test_data[i].out, color, test_data[i].in[0]);
403
404         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
405         ok(SUCCEEDED(hr), "Clear failed (%08x)\n", hr);
406     }
407
408     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
409     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
410
411     IDirect3DVertexDeclaration9_Release(vertex_declaration);
412     IDirect3DVertexShader9_Release(mova_shader);
413 }
414
415 struct sVertex {
416     float x, y, z;
417     DWORD diffuse;
418     DWORD specular;
419 };
420
421 struct sVertexT {
422     float x, y, z, rhw;
423     DWORD diffuse;
424     DWORD specular;
425 };
426
427 static void fog_test(IDirect3DDevice9 *device)
428 {
429     HRESULT hr;
430     DWORD color;
431     float start = 0.0f, end = 1.0f;
432     D3DCAPS9 caps;
433
434     /* Gets full z based fog with linear fog, no fog with specular color */
435     struct sVertex unstransformed_1[] = {
436         {-1,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
437         {-1,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
438         { 0,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
439         { 0,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
440     };
441     /* Ok, I am too lazy to deal with transform matrices */
442     struct sVertex unstransformed_2[] = {
443         {-1,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
444         {-1,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
445         { 0,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
446         { 0,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
447     };
448     /* Untransformed ones. Give them a different diffuse color to make the test look
449      * nicer. It also makes making sure that they are drawn correctly easier.
450      */
451     struct sVertexT transformed_1[] = {
452         {320,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
453         {640,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
454         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
455         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
456     };
457     struct sVertexT transformed_2[] = {
458         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
459         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
460         {640,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
461         {320,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
462     };
463     WORD Indices[] = {0, 1, 2, 2, 3, 0};
464
465     memset(&caps, 0, sizeof(caps));
466     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
467     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %s\n", DXGetErrorString9(hr));
468     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
469     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
470
471     /* Setup initial states: No lighting, fog on, fog color */
472     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
473     ok(hr == D3D_OK, "Turning off lighting returned %s\n", DXGetErrorString9(hr));
474     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
475     ok(hr == D3D_OK, "Turning on fog calculations returned %s\n", DXGetErrorString9(hr));
476     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
477     ok(hr == D3D_OK, "Turning on fog calculations returned %s\n", DXGetErrorString9(hr));
478
479     /* First test: Both table fog and vertex fog off */
480     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
481     ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString9(hr));
482     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
483     ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString9(hr));
484
485     /* Start = 0, end = 1. Should be default, but set them */
486     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
487     ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
488     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
489     ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
490
491     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
492     {
493         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
494         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
495         /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
496         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
497                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_1,
498                                                      sizeof(unstransformed_1[0]));
499         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
500
501         /* That makes it use the Z value */
502         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
503         ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString9(hr));
504         /* Untransformed, vertex fog != none (or table fog != none):
505          * Use the Z value as input into the equation
506          */
507         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
508                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_2,
509                                                      sizeof(unstransformed_1[0]));
510         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
511
512         /* transformed verts */
513         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
514         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
515         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
516         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
517                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
518                                                      sizeof(transformed_1[0]));
519         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
520
521         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
522         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %s\n", DXGetErrorString9(hr));
523         /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
524          * equation
525          */
526         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
527                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_2,
528                                                      sizeof(transformed_2[0]));
529
530         hr = IDirect3DDevice9_EndScene(device);
531         ok(hr == D3D_OK, "EndScene returned %s\n", DXGetErrorString9(hr));
532     }
533     else
534     {
535         ok(FALSE, "BeginScene failed\n");
536     }
537
538     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
539     color = getPixelColor(device, 160, 360);
540     ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color);
541     color = getPixelColor(device, 160, 120);
542     ok(color == 0x0000FF00, "Untransformed vertex with linear vertex fog has color %08x\n", color);
543     color = getPixelColor(device, 480, 120);
544     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
545     if(caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
546     {
547         color = getPixelColor(device, 480, 360);
548         ok(color == 0x0000FF00, "Transformed vertex with linear table fog has color %08x\n", color);
549     }
550     else
551     {
552         /* Without fog table support the vertex fog is still applied, even though table fog is turned on.
553          * The settings above result in no fogging with vertex fog
554          */
555         color = getPixelColor(device, 480, 120);
556         ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
557         trace("Info: Table fog not supported by this device\n");
558     }
559
560     /* Now test the special case fogstart == fogend */
561     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
562     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
563
564     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
565     {
566         start = 512;
567         end = 512;
568         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
569         ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
570         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
571         ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
572
573         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
574         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
575         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
576         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState %s\n", DXGetErrorString9(hr));
577         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
578         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %s\n", DXGetErrorString9(hr));
579
580         /* Untransformed vertex, z coord = 0.1, fogstart = 512, fogend = 512. Would result in
581          * a completely fog-free primitive because start > zcoord, but because start == end, the primitive
582          * is fully covered by fog. The same happens to the 2nd untransformed quad with z = 1.0.
583          * The third transformed quad remains unfogged because the fogcoords are read from the specular
584          * color and has fixed fogstart and fogend.
585          */
586         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
587                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_1,
588                 sizeof(unstransformed_1[0]));
589         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
590         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
591                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_2,
592                 sizeof(unstransformed_1[0]));
593         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
594
595         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
596         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
597         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
598         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
599                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
600                 sizeof(transformed_1[0]));
601         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
602
603         hr = IDirect3DDevice9_EndScene(device);
604         ok(hr == D3D_OK, "EndScene returned %s\n", DXGetErrorString9(hr));
605     }
606     else
607     {
608         ok(FALSE, "BeginScene failed\n");
609     }
610     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
611     color = getPixelColor(device, 160, 360);
612     ok(color == 0x0000FF00, "Untransformed vertex with vertex fog and z = 0.1 has color %08x\n", color);
613     color = getPixelColor(device, 160, 120);
614     ok(color == 0x0000FF00, "Untransformed vertex with vertex fog and z = 1.0 has color %08x\n", color);
615     color = getPixelColor(device, 480, 120);
616     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
617
618     /* Turn off the fog master switch to avoid confusing other tests */
619     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
620     ok(hr == D3D_OK, "Turning off fog calculations returned %s\n", DXGetErrorString9(hr));
621     start = 0.0;
622     end = 1.0;
623     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
624     ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
625     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
626     ok(hr == D3D_OK, "Setting fog end returned %s\n", DXGetErrorString9(hr));
627     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
628     ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState %s\n", DXGetErrorString9(hr));
629     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
630     ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %s\n", DXGetErrorString9(hr));
631 }
632
633 /* This test verifies the behaviour of cube maps wrt. texture wrapping.
634  * D3D cube map wrapping always behaves like GL_CLAMP_TO_EDGE,
635  * regardless of the actual addressing mode set. */
636 static void test_cube_wrap(IDirect3DDevice9 *device)
637 {
638     static const float quad[][6] = {
639         {-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
640         {-1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
641         { 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
642         { 1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
643     };
644
645     static const D3DVERTEXELEMENT9 decl_elements[] = {
646         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
647         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
648         D3DDECL_END()
649     };
650
651     static const struct {
652         D3DTEXTUREADDRESS mode;
653         const char *name;
654     } address_modes[] = {
655         {D3DTADDRESS_WRAP, "D3DTADDRESS_WRAP"},
656         {D3DTADDRESS_MIRROR, "D3DTADDRESS_MIRROR"},
657         {D3DTADDRESS_CLAMP, "D3DTADDRESS_CLAMP"},
658         {D3DTADDRESS_BORDER, "D3DTADDRESS_BORDER"},
659         {D3DTADDRESS_MIRRORONCE, "D3DTADDRESS_MIRRORONCE"},
660     };
661
662     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
663     IDirect3DCubeTexture9 *texture = NULL;
664     IDirect3DSurface9 *surface = NULL;
665     D3DLOCKED_RECT locked_rect;
666     HRESULT hr;
667     INT x, y, face;
668
669     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
670     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
671     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
672     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
673
674     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
675             D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL);
676     ok(SUCCEEDED(hr), "CreateOffscreenPlainSurface failed (0x%08x)\n", hr);
677
678     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, D3DLOCK_DISCARD);
679     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
680
681     for (y = 0; y < 128; ++y)
682     {
683         DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
684         for (x = 0; x < 64; ++x)
685         {
686             *ptr++ = 0xffff0000;
687         }
688         for (x = 64; x < 128; ++x)
689         {
690             *ptr++ = 0xff0000ff;
691         }
692     }
693
694     hr = IDirect3DSurface9_UnlockRect(surface);
695     ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
696
697     hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
698             D3DPOOL_DEFAULT, &texture, NULL);
699     ok(SUCCEEDED(hr), "CreateCubeTexture failed (0x%08x)\n", hr);
700
701     /* Create cube faces */
702     for (face = 0; face < 6; ++face)
703     {
704         IDirect3DSurface9 *face_surface = NULL;
705
706         hr= IDirect3DCubeTexture9_GetCubeMapSurface(texture, face, 0, &face_surface);
707         ok(SUCCEEDED(hr), "GetCubeMapSurface failed (0x%08x)\n", hr);
708
709         hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, face_surface, NULL);
710         ok(SUCCEEDED(hr), "UpdateSurface failed (0x%08x)\n", hr);
711
712         IDirect3DSurface9_Release(face_surface);
713     }
714
715     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
716     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
717
718     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
719     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
720     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
721     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
722     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_BORDERCOLOR, 0xff00ff00);
723     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_BORDERCOLOR failed (0x%08x)\n", hr);
724
725     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
726     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
727
728     for (x = 0; x < (sizeof(address_modes) / sizeof(*address_modes)); ++x)
729     {
730         DWORD color;
731
732         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, address_modes[x].mode);
733         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU (%s) failed (0x%08x)\n", address_modes[x].name, hr);
734         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, address_modes[x].mode);
735         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV (%s) failed (0x%08x)\n", address_modes[x].name, hr);
736
737         hr = IDirect3DDevice9_BeginScene(device);
738         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
739
740         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
741         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
742
743         hr = IDirect3DDevice9_EndScene(device);
744         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
745
746         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
747         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
748
749         /* Due to the nature of this test, we sample essentially at the edge
750          * between two faces. Because of this it's undefined from which face
751          * the driver will sample. Furtunately that's not important for this
752          * test, since all we care about is that it doesn't sample from the
753          * other side of the surface or from the border. */
754         color = getPixelColor(device, 320, 240);
755         ok(color == 0x00ff0000 || color == 0x000000ff,
756                 "Got color 0x%08x for addressing mode %s, expected 0x00ff0000 or 0x000000ff.\n",
757                 color, address_modes[x].name);
758
759         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
760         ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
761     }
762
763     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
764     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
765
766     IDirect3DVertexDeclaration9_Release(vertex_declaration);
767     IDirect3DCubeTexture9_Release(texture);
768     IDirect3DSurface9_Release(surface);
769 }
770
771 static void offscreen_test(IDirect3DDevice9 *device)
772 {
773     HRESULT hr;
774     IDirect3DTexture9 *offscreenTexture = NULL;
775     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
776     DWORD color;
777
778     static const float quad[][5] = {
779         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
780         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
781         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
782         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
783     };
784
785     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
786     ok(hr == D3D_OK, "Clear failed, hr = %s\n", DXGetErrorString9(hr));
787
788     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
789     ok(hr == D3D_OK || D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %s\n", DXGetErrorString9(hr));
790     if(!offscreenTexture) {
791         trace("Failed to create an X8R8G8B8 offscreen texture, trying R5G6B5\n");
792         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
793         ok(hr == D3D_OK || D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %s\n", DXGetErrorString9(hr));
794         if(!offscreenTexture) {
795             skip("Cannot create an offscreen render target\n");
796             goto out;
797         }
798     }
799
800     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
801     ok(hr == D3D_OK, "Can't get back buffer, hr = %s\n", DXGetErrorString9(hr));
802     if(!backbuffer) {
803         goto out;
804     }
805
806     hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
807     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %s\n", DXGetErrorString9(hr));
808     if(!offscreen) {
809         goto out;
810     }
811
812     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
813     ok(hr == D3D_OK, "SetFVF failed, hr = %s\n", DXGetErrorString9(hr));
814
815     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
816     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
817     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
818     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
819     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_NONE);
820     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
821     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_NONE);
822     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
823     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
824     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
825
826     if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
827         hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
828         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %s\n", DXGetErrorString9(hr));
829         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
830         ok(hr == D3D_OK, "Clear failed, hr = %s\n", DXGetErrorString9(hr));
831
832         /* Draw without textures - Should resut in a white quad */
833         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
834         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %s\n", DXGetErrorString9(hr));
835
836         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
837         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %s\n", DXGetErrorString9(hr));
838         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
839         ok(hr == D3D_OK, "SetTexture failed, %s\n", DXGetErrorString9(hr));
840
841         /* This time with the texture */
842         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
843         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %s\n", DXGetErrorString9(hr));
844
845         IDirect3DDevice9_EndScene(device);
846     }
847
848     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
849
850     /* Center quad - should be white */
851     color = getPixelColor(device, 320, 240);
852     ok(color == 0x00ffffff, "Offscreen failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
853     /* Some quad in the cleared part of the texture */
854     color = getPixelColor(device, 170, 240);
855     ok(color == 0x00ff00ff, "Offscreen failed: Got color 0x%08x, expected 0x00ff00ff.\n", color);
856     /* Part of the originally cleared back buffer */
857     color = getPixelColor(device, 10, 10);
858     ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
859     if(0) {
860         /* Lower left corner of the screen, where back buffer offscreen rendering draws the offscreen texture.
861          * It should be red, but the offscreen texture may leave some junk there. Not tested yet. Depending on
862          * the offscreen rendering mode this test would succeed or fail
863          */
864         color = getPixelColor(device, 10, 470);
865         ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
866     }
867
868 out:
869     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
870
871     /* restore things */
872     if(backbuffer) {
873         IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
874         IDirect3DSurface9_Release(backbuffer);
875     }
876     if(offscreenTexture) {
877         IDirect3DTexture9_Release(offscreenTexture);
878     }
879     if(offscreen) {
880         IDirect3DSurface9_Release(offscreen);
881     }
882 }
883
884 /* This test tests fog in combination with shaders.
885  * What's tested: linear fog (vertex and table) with pixel shader
886  *                linear table fog with non foggy vertex shader
887  *                vertex fog with foggy vertex shader
888  * What's not tested: non linear fog with shader
889  *                    table fog with foggy vertex shader
890  */
891 static void fog_with_shader_test(IDirect3DDevice9 *device)
892 {
893     HRESULT hr;
894     DWORD color;
895     union {
896         float f;
897         DWORD i;
898     } start, end;
899     unsigned int i, j;
900
901     /* basic vertex shader without fog computation ("non foggy") */
902     static const DWORD vertex_shader_code1[] = {
903         0xfffe0101,                                                             /* vs_1_1                       */
904         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
905         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                */
906         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
907         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                  */
908         0x0000ffff
909     };
910     /* basic vertex shader with reversed fog computation ("foggy") */
911     static const DWORD vertex_shader_code2[] = {
912         0xfffe0101,                                                             /* vs_1_1                        */
913         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0               */
914         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                 */
915         0x00000051, 0xa00f0000, 0xbfa00000, 0x00000000, 0xbf666666, 0x00000000, /* def c0, -1.25, 0.0, -0.9, 0.0 */
916         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                  */
917         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                   */
918         0x00000002, 0x800f0000, 0x90aa0000, 0xa0aa0000,                         /* add r0, v0.z, c0.z            */
919         0x00000005, 0xc00f0001, 0x80000000, 0xa0000000,                         /* mul oFog, r0.x, c0.x          */
920         0x0000ffff
921     };
922     /* basic pixel shader */
923     static const DWORD pixel_shader_code[] = {
924         0xffff0101,                                                             /* ps_1_1     */
925         0x00000001, 0x800f0000, 0x90e40000,                                     /* mov r0, vo */
926         0x0000ffff
927     };
928
929     static struct vertex quad[] = {
930         {-1.0f, -1.0f,  0.0f,          0xFFFF0000  },
931         {-1.0f,  1.0f,  0.0f,          0xFFFF0000  },
932         { 1.0f, -1.0f,  0.0f,          0xFFFF0000  },
933         { 1.0f,  1.0f,  0.0f,          0xFFFF0000  },
934     };
935
936     static const D3DVERTEXELEMENT9 decl_elements[] = {
937         {0,  0, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
938         {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
939         D3DDECL_END()
940     };
941
942     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
943     IDirect3DVertexShader9      *vertex_shader[3]   = {NULL, NULL, NULL};
944     IDirect3DPixelShader9       *pixel_shader[2]    = {NULL, NULL};
945
946     /* This reference data was collected on a nVidia GeForce 7600GS driver version 84.19 DirectX version 9.0c on Windows XP */
947     static const struct test_data_t {
948         int vshader;
949         int pshader;
950         D3DFOGMODE vfog;
951         D3DFOGMODE tfog;
952         unsigned int color[11];
953     } test_data[] = {
954         /* only pixel shader: */
955         {0, 1, 0, 3,
956         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
957          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
958         {0, 1, 1, 3,
959         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
960          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
961         {0, 1, 2, 3,
962         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
963          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
964         {0, 1, 3, 0,
965         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
966          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
967         {0, 1, 3, 3,
968         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
969          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
970
971         /* vertex shader */
972         {1, 0, 0, 0,
973         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
974          0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
975         {1, 0, 0, 3,
976         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
977          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
978         {1, 0, 1, 3,
979         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
980          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
981         {1, 0, 2, 3,
982         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
983          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
984         {1, 0, 3, 3,
985         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
986          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
987
988         /* vertex shader and pixel shader */
989         {1, 1, 0, 3,
990         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
991          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
992         {1, 1, 1, 3,
993         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
994          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
995         {1, 1, 2, 3,
996         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
997          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
998         {1, 1, 3, 3,
999         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1000          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1001
1002 #if 0  /* FIXME: these fail on GeForce 8500 */
1003         /* foggy vertex shader */
1004         {2, 0, 0, 0,
1005         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1006          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1007         {2, 0, 1, 0,
1008         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1009          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1010         {2, 0, 2, 0,
1011         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1012          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1013         {2, 0, 3, 0,
1014         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1015          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1016 #endif
1017
1018         /* foggy vertex shader and pixel shader */
1019         {2, 1, 0, 0,
1020         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1021          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1022         {2, 1, 1, 0,
1023         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1024          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1025         {2, 1, 2, 0,
1026         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1027          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1028         {2, 1, 3, 0,
1029         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1030          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1031
1032     };
1033
1034     /* NOTE: changing these values will not affect the tests with foggy vertex shader, as the values are hardcoded in the shader*/
1035     start.f=0.9f;
1036     end.f=0.1f;
1037
1038     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code1, &vertex_shader[1]);
1039     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1040     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code2, &vertex_shader[2]);
1041     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1042     hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader[1]);
1043     ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1044     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1045     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
1046
1047     /* Setup initial states: No lighting, fog on, fog color */
1048     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1049     ok(hr == D3D_OK, "Turning off lighting failed (%08x)\n", hr);
1050     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
1051     ok(hr == D3D_OK, "Turning on fog calculations failed (%08x)\n", hr);
1052     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
1053     ok(hr == D3D_OK, "Setting fog color failed (%08x)\n", hr);
1054     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1055     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1056
1057     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
1058     ok(hr == D3D_OK, "Turning off table fog failed (%08x)\n", hr);
1059     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
1060     ok(hr == D3D_OK, "Turning off vertex fog failed (%08x)\n", hr);
1061
1062     /* Use fogtart = 0.1 and end = 0.9 to test behavior outside the fog transition phase, too*/
1063     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, start.i);
1064     ok(hr == D3D_OK, "Setting fog start failed (%08x)\n", hr);
1065     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, end.i);
1066     ok(hr == D3D_OK, "Setting fog end failed (%08x)\n", hr);
1067
1068     for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++)
1069     {
1070         hr = IDirect3DDevice9_SetVertexShader(device, vertex_shader[test_data[i].vshader]);
1071         ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1072         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader[test_data[i].pshader]);
1073         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1074         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, test_data[i].vfog);
1075         ok( hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1076         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, test_data[i].tfog);
1077         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1078
1079         for(j=0; j < 11; j++)
1080         {
1081             /* Don't use the whole zrange to prevent rounding errors */
1082             quad[0].z = 0.001f + (float)j / 10.02f;
1083             quad[1].z = 0.001f + (float)j / 10.02f;
1084             quad[2].z = 0.001f + (float)j / 10.02f;
1085             quad[3].z = 0.001f + (float)j / 10.02f;
1086
1087             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1088             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
1089
1090             hr = IDirect3DDevice9_BeginScene(device);
1091             ok( hr == D3D_OK, "BeginScene returned failed (%08x)\n", hr);
1092
1093             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1094             ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1095
1096             hr = IDirect3DDevice9_EndScene(device);
1097             ok(hr == D3D_OK, "EndScene failed (%08x)\n", hr);
1098
1099             IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1100
1101             /* As the red and green component are the result of blending use 5% tolerance on the expected value */
1102             color = getPixelColor(device, 128, 240);
1103             ok((unsigned char)(color) == ((unsigned char)test_data[i].color[j])
1104                     && abs( ((unsigned char)(color>>8)) - (unsigned char)(test_data[i].color[j]>>8) ) < 13
1105                     && abs( ((unsigned char)(color>>16)) - (unsigned char)(test_data[i].color[j]>>16) ) < 13,
1106                     "fog ps%i vs%i fvm%i ftm%i %d: got color %08x, expected %08x +-5%%\n", test_data[i].vshader, test_data[i].pshader, test_data[i].vfog, test_data[i].tfog, j, color, test_data[i].color[j]);
1107         }
1108     }
1109
1110     /* reset states */
1111     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
1112     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1113     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1114     ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1115     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1116     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1117     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
1118     ok(hr == D3D_OK, "Turning off fog calculations failed (%08x)\n", hr);
1119
1120     IDirect3DVertexShader9_Release(vertex_shader[1]);
1121     IDirect3DVertexShader9_Release(vertex_shader[2]);
1122     IDirect3DPixelShader9_Release(pixel_shader[1]);
1123     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1124 }
1125
1126 /* test the behavior of the texbem instruction
1127  * with normal 2D and projective 2D textures
1128  */
1129 static void texbem_test(IDirect3DDevice9 *device)
1130 {
1131     HRESULT hr;
1132     DWORD color;
1133     unsigned int i, x, y;
1134
1135     static const DWORD pixel_shader_code[] = {
1136         0xffff0101,                         /* ps_1_1*/
1137         0x00000042, 0xb00f0000,             /* tex t0*/
1138         0x00000043, 0xb00f0001, 0xb0e40000, /* texbem t1, t0*/
1139         0x00000001, 0x800f0000, 0xb0e40001, /* mov r0, t1*/
1140         0x0000ffff
1141     };
1142
1143     static const float quad[][7] = {
1144         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f},
1145         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f},
1146         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 1.0f, 0.0f},
1147         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 1.0f, 1.0f},
1148     };
1149     static const float quad_proj[][9] = {
1150         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f,   0.0f,   0.0f, 0.0f, 128.0f},
1151         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f,   0.0f, 128.0f, 0.0f, 128.0f},
1152         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 128.0f,   0.0f, 0.0f, 128.0f},
1153         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 128.0f, 128.0f, 0.0f, 128.0f},
1154     };
1155
1156     static const D3DVERTEXELEMENT9 decl_elements[][4] = { {
1157         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1158         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1159         {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1160         D3DDECL_END()
1161     },{
1162         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1163         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1164         {0, 20, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1165         D3DDECL_END()
1166     } };
1167
1168     /* use assymetric matrix to test loading */
1169     float bumpenvmat[4] = {0.0,0.5,-0.5,0.0};
1170
1171     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1172     IDirect3DPixelShader9       *pixel_shader       = NULL;
1173     IDirect3DTexture9           *texture[2]         = {NULL, NULL};
1174     D3DLOCKED_RECT locked_rect;
1175
1176     /* Generate the textures */
1177     for(i=0; i<2; i++)
1178     {
1179         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, i?D3DFMT_A8R8G8B8:D3DFMT_V8U8,
1180                 D3DPOOL_MANAGED, &texture[i], NULL);
1181         ok(SUCCEEDED(hr), "CreateTexture failed (0x%08x)\n", hr);
1182
1183         hr = IDirect3DTexture9_LockRect(texture[i], 0, &locked_rect, NULL, D3DLOCK_DISCARD);
1184         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1185         for (y = 0; y < 128; ++y)
1186         {
1187             if(i)
1188             { /* Set up black texture with 2x2 texel white spot in the middle */
1189                 DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1190                 for (x = 0; x < 128; ++x)
1191                 {
1192                     if(y>62 && y<66 && x>62 && x<66)
1193                         *ptr++ = 0xffffffff;
1194                     else
1195                         *ptr++ = 0xff000000;
1196                 }
1197             }
1198             else
1199             { /* Set up a displacement map which points away from the center parallel to the closest axis.
1200               * (if multiplied with bumpenvmat)
1201               */
1202                 WORD *ptr = (WORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1203                 for (x = 0; x < 128; ++x)
1204                 {
1205                     if(abs(x-64)>abs(y-64))
1206                     {
1207                         if(x < 64)
1208                             *ptr++ = 0xc000;
1209                         else
1210                             *ptr++ = 0x4000;
1211                     }
1212                     else
1213                     {
1214                         if(y < 64)
1215                             *ptr++ = 0x0040;
1216                         else
1217                             *ptr++ = 0x00c0;
1218                     }
1219                 }
1220             }
1221         }
1222         hr = IDirect3DTexture9_UnlockRect(texture[i], 0);
1223         ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
1224
1225         hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture[i]);
1226         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1227
1228         /* Disable texture filtering */
1229         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MINFILTER, D3DTEXF_POINT);
1230         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1231         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
1232         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1233
1234         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1235         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU failed (0x%08x)\n", hr);
1236         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1237         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV failed (0x%08x)\n", hr);
1238     }
1239
1240     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
1241     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
1242     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
1243     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
1244     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
1245
1246     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
1247     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1248
1249     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1250     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
1251
1252     for(i=0; i<2; i++)
1253     {
1254         if(i)
1255         {
1256             hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4|D3DTTFF_PROJECTED);
1257             ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
1258         }
1259
1260         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements[i], &vertex_declaration);
1261         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1262         hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1263         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1264
1265         hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader);
1266         ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1267         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader);
1268         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1269
1270         hr = IDirect3DDevice9_BeginScene(device);
1271         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1272
1273         if(!i)
1274             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1275         else
1276             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad_proj[0], sizeof(quad_proj[0]));
1277         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
1278
1279         hr = IDirect3DDevice9_EndScene(device);
1280         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1281
1282         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1283         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1284
1285         color = getPixelColor(device, 320-32, 240);
1286         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1287         color = getPixelColor(device, 320+32, 240);
1288         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1289         color = getPixelColor(device, 320, 240-32);
1290         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1291         color = getPixelColor(device, 320, 240+32);
1292         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1293
1294         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1295         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1296         IDirect3DPixelShader9_Release(pixel_shader);
1297
1298         hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1299         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1300         IDirect3DVertexDeclaration9_Release(vertex_declaration);
1301     }
1302
1303     /* clean up */
1304     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
1305     ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
1306
1307     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
1308     ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
1309
1310     for(i=0; i<2; i++)
1311     {
1312         hr = IDirect3DDevice9_SetTexture(device, i, NULL);
1313         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1314         IDirect3DCubeTexture9_Release(texture[i]);
1315     }
1316 }
1317
1318 static void present_test(IDirect3DDevice9 *device)
1319 {
1320     struct vertex quad[] =
1321     {
1322         {-1.0f, -1.0f,   0.9f,                          0xffff0000},
1323         {-1.0f,  1.0f,   0.9f,                          0xffff0000},
1324         { 1.0f, -1.0f,   0.1f,                          0xffff0000},
1325         { 1.0f,  1.0f,   0.1f,                          0xffff0000},
1326     };
1327     HRESULT hr;
1328     DWORD color;
1329
1330     /* Does the Present clear the depth stencil? Clear the depth buffer with some value != 0,
1331      * then call Present. Then clear the color buffer to make sure it has some defined content
1332      * after the Present with D3DSWAPEFFECT_DISCARD. After that draw a plane that is somewhere cut
1333      * by the depth value.
1334      */
1335     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.75, 0);
1336     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
1337     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1338     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4, 0);
1339
1340     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
1341     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1342     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
1343     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1344     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1345     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
1346
1347     hr = IDirect3DDevice9_BeginScene(device);
1348     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
1349     if(hr == D3D_OK)
1350     {
1351         /* No lights are defined... That means, lit vertices should be entirely black */
1352         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
1353         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1354
1355         hr = IDirect3DDevice9_EndScene(device);
1356         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
1357     }
1358
1359     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
1360     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1361
1362     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1363     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1364     color = getPixelColor(device, 512, 240);
1365     ok(color == 0x00ffffff, "Present failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1366     color = getPixelColor(device, 64, 240);
1367     ok(color == 0x00ff0000, "Present failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1368 }
1369
1370 static void fill_surface(IDirect3DSurface9 *surface, DWORD color)
1371 {
1372     D3DSURFACE_DESC desc;
1373     D3DLOCKED_RECT l;
1374     HRESULT hr;
1375     unsigned int x, y;
1376     DWORD *mem;
1377
1378     memset(&desc, 0, sizeof(desc));
1379     memset(&l, 0, sizeof(l));
1380     hr = IDirect3DSurface9_GetDesc(surface, &desc);
1381     ok(hr == D3D_OK, "IDirect3DSurface9_GetDesc failed with %s\n", DXGetErrorString9(hr));
1382     hr = IDirect3DSurface9_LockRect(surface, &l, NULL, D3DLOCK_DISCARD);
1383     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed with %s\n", DXGetErrorString9(hr));
1384     if(FAILED(hr)) return;
1385
1386     for(y = 0; y < desc.Height; y++)
1387     {
1388         mem = (DWORD *) ((BYTE *) l.pBits + y * l.Pitch);
1389         for(x = 0; x < l.Pitch / sizeof(DWORD); x++)
1390         {
1391             mem[x] = color;
1392         }
1393     }
1394     hr = IDirect3DSurface9_UnlockRect(surface);
1395     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed with %s\n", DXGetErrorString9(hr));
1396 }
1397
1398 static void maxmip_test(IDirect3DDevice9 *device)
1399 {
1400     IDirect3DTexture9 *texture = NULL;
1401     IDirect3DSurface9 *surface = NULL;
1402     HRESULT hr;
1403     DWORD color;
1404     const float quads[] = {
1405         -1.0,   -1.0,   0.0,    0.0,    0.0,
1406         -1.0,    0.0,   0.0,    0.0,    1.0,
1407          0.0,   -1.0,   0.0,    1.0,    0.0,
1408          0.0,    0.0,   0.0,    1.0,    1.0,
1409
1410          0.0,   -1.0,   0.0,    0.0,    0.0,
1411          0.0,    0.0,   0.0,    0.0,    1.0,
1412          1.0,   -1.0,   0.0,    1.0,    0.0,
1413          1.0,    0.0,   0.0,    1.0,    1.0,
1414
1415          0.0,    0.0,   0.0,    0.0,    0.0,
1416          0.0,    1.0,   0.0,    0.0,    1.0,
1417          1.0,    0.0,   0.0,    1.0,    0.0,
1418          1.0,    1.0,   0.0,    1.0,    1.0,
1419
1420         -1.0,    0.0,   0.0,    0.0,    0.0,
1421         -1.0,    1.0,   0.0,    0.0,    1.0,
1422          0.0,    0.0,   0.0,    1.0,    0.0,
1423          0.0,    1.0,   0.0,    1.0,    1.0,
1424     };
1425
1426     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
1427     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
1428
1429     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
1430                                         &texture, NULL);
1431     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %s\n", DXGetErrorString9(hr));
1432     if(!texture)
1433     {
1434         skip("Failed to create test texture\n");
1435         return;
1436     }
1437
1438     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
1439     fill_surface(surface, 0xffff0000);
1440     IDirect3DSurface9_Release(surface);
1441     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface);
1442     fill_surface(surface, 0xff00ff00);
1443     IDirect3DSurface9_Release(surface);
1444     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
1445     fill_surface(surface, 0xff0000ff);
1446     IDirect3DSurface9_Release(surface);
1447
1448     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
1449     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
1450     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
1451     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
1452
1453     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
1454     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1455
1456     hr = IDirect3DDevice9_BeginScene(device);
1457     if(SUCCEEDED(hr))
1458     {
1459         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
1460         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1461         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[ 0], 5 * sizeof(float));
1462         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1463
1464         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
1465         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1466         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[20], 5 * sizeof(float));
1467         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1468
1469         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
1470         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1471         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[40], 5 * sizeof(float));
1472         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1473
1474         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
1475         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1476         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[60], 5 * sizeof(float));
1477         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1478         hr = IDirect3DDevice9_EndScene(device);
1479     }
1480
1481     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1482     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1483     /* With mipmapping disabled, the max mip level is ignored, only level 0 is used */
1484     color = getPixelColor(device, 160, 360);
1485     ok(color == 0x00FF0000, "MapMip 0, no mipfilter has color %08x\n", color);
1486     color = getPixelColor(device, 160, 120);
1487     ok(color == 0x00FF0000, "MapMip 3, no mipfilter has color %08x\n", color);
1488     color = getPixelColor(device, 480, 120);
1489     ok(color == 0x00FF0000, "MapMip 2, no mipfilter has color %08x\n", color);
1490     color = getPixelColor(device, 480, 360);
1491     ok(color == 0x00FF0000, "MapMip 1, no mipfilter has color %08x\n", color);
1492
1493     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
1494     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
1495
1496     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
1497     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1498
1499     hr = IDirect3DDevice9_BeginScene(device);
1500     if(SUCCEEDED(hr))
1501     {
1502         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
1503         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1504         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[ 0], 5 * sizeof(float));
1505         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1506
1507         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
1508         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1509         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[20], 5 * sizeof(float));
1510         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1511
1512         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
1513         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1514         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[40], 5 * sizeof(float));
1515         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1516
1517         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
1518         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1519         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[60], 5 * sizeof(float));
1520         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1521         hr = IDirect3DDevice9_EndScene(device);
1522     }
1523
1524     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
1525     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1526     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
1527     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1528
1529     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1530     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1531     /* Max Mip level 0-2 sample from the specified texture level, Max Mip level 3(> levels in texture)
1532      * samples from the highest level in the texture(level 2)
1533      */
1534     color = getPixelColor(device, 160, 360);
1535     ok(color == 0x00FF0000, "MapMip 0, point mipfilter has color %08x\n", color);
1536     color = getPixelColor(device, 160, 120);
1537     ok(color == 0x000000FF, "MapMip 3, point mipfilter has color %08x\n", color);
1538     color = getPixelColor(device, 480, 120);
1539     ok(color == 0x000000FF, "MapMip 2, point mipfilter has color %08x\n", color);
1540     color = getPixelColor(device, 480, 360);
1541     ok(color == 0x0000FF00, "MapMip 1, point mipfilter has color %08x\n", color);
1542
1543     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1544     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
1545     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
1546     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1547     IDirect3DTexture9_Release(texture);
1548 }
1549
1550 static void release_buffer_test(IDirect3DDevice9 *device)
1551 {
1552     IDirect3DVertexBuffer9 *vb = NULL;
1553     IDirect3DIndexBuffer9 *ib = NULL;
1554     HRESULT hr;
1555     BYTE *data;
1556     long ref;
1557
1558     static const struct vertex quad[] = {
1559         {-1.0,      -1.0,       0.1,        0xffff0000},
1560         {-1.0,       1.0,       0.1,        0xffff0000},
1561         { 1.0,       1.0,       0.1,        0xffff0000},
1562
1563         {-1.0,      -1.0,       0.1,        0xff00ff00},
1564         {-1.0,       1.0,       0.1,        0xff00ff00},
1565         { 1.0,       1.0,       0.1,        0xff00ff00}
1566     };
1567     short indices[] = {3, 4, 5};
1568
1569     /* Index and vertex buffers should always be createable */
1570     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1571                                               D3DPOOL_MANAGED, &vb, NULL);
1572     ok(hr == D3D_OK, "CreateVertexBuffer failed with %s\n", DXGetErrorString9(hr));
1573     if(!vb) {
1574         skip("Failed to create a vertex buffer\n");
1575         return;
1576     }
1577     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, NULL);
1578     ok(hr == D3D_OK, "IDirect3DDevice9_CreateIndexBuffer failed with %s\n", DXGetErrorString9(hr));
1579     if(!ib) {
1580         skip("Failed to create an index buffer\n");
1581         return;
1582     }
1583
1584     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), (void **) &data, 0);
1585     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
1586     memcpy(data, quad, sizeof(quad));
1587     hr = IDirect3DVertexBuffer9_Unlock(vb);
1588     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr));
1589
1590     hr = IDirect3DIndexBuffer9_Lock(ib, 0, sizeof(indices), (void **) &data, 0);
1591     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
1592     memcpy(data, indices, sizeof(indices));
1593     hr = IDirect3DIndexBuffer9_Unlock(ib);
1594     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr));
1595
1596     hr = IDirect3DDevice9_SetIndices(device, ib);
1597     ok(hr == D3D_OK, "IDirect3DIndexBuffer8_Unlock failed with %s\n", DXGetErrorString9(hr));
1598     hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad[0]));
1599     ok(hr == D3D_OK, "IDirect3DIndexBuffer8_Unlock failed with %s\n", DXGetErrorString9(hr));
1600     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1601     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
1602
1603     /* Now destroy the bound index buffer and draw again */
1604     ref = IDirect3DIndexBuffer9_Release(ib);
1605     ok(ref == 0, "Index Buffer reference count is %08ld\n", ref);
1606
1607     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
1608     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1609
1610     hr = IDirect3DDevice9_BeginScene(device);
1611     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1612     if(SUCCEEDED(hr))
1613     {
1614         /* Deliberately using minvertexindex = 0 and numVertices = 6 to prevent d3d from
1615          * making assumptions about the indices or vertices
1616          */
1617         hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 3, 3, 0, 1);
1618         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitive failed with %08x\n", hr);
1619         hr = IDirect3DDevice9_EndScene(device);
1620         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1621     }
1622
1623     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1624     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
1625
1626     hr = IDirect3DDevice9_SetIndices(device, NULL);
1627     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
1628     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
1629     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
1630
1631     /* Index buffer was already destroyed as part of the test */
1632     IDirect3DVertexBuffer9_Release(vb);
1633 }
1634
1635 static void float_texture_test(IDirect3DDevice9 *device)
1636 {
1637     IDirect3D9 *d3d = NULL;
1638     HRESULT hr;
1639     IDirect3DTexture9 *texture = NULL;
1640     D3DLOCKED_RECT lr;
1641     float *data;
1642     DWORD color;
1643     float quad[] = {
1644         -1.0,      -1.0,       0.1,     0.0,    0.0,
1645         -1.0,       1.0,       0.1,     0.0,    1.0,
1646          1.0,      -1.0,       0.1,     1.0,    0.0,
1647          1.0,       1.0,       0.1,     1.0,    1.0,
1648     };
1649
1650     memset(&lr, 0, sizeof(lr));
1651     IDirect3DDevice9_GetDirect3D(device, &d3d);
1652     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
1653                                      D3DRTYPE_TEXTURE, D3DFMT_R32F) != D3D_OK) {
1654         skip("D3DFMT_R32F textures not supported\n");
1655         goto out;
1656     }
1657
1658     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_R32F,
1659                                         D3DPOOL_MANAGED, &texture, NULL);
1660     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %s\n", DXGetErrorString9(hr));
1661     if(!texture) {
1662         skip("Failed to create R32F texture\n");
1663         goto out;
1664     }
1665
1666     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
1667     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %s\n", DXGetErrorString9(hr));
1668     data = lr.pBits;
1669     *data = 0.0;
1670     hr = IDirect3DTexture9_UnlockRect(texture, 0);
1671     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %s\n", DXGetErrorString9(hr));
1672
1673     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
1674     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
1675
1676     hr = IDirect3DDevice9_BeginScene(device);
1677     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
1678     if(SUCCEEDED(hr))
1679     {
1680         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
1681         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
1682
1683         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
1684         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1685
1686         hr = IDirect3DDevice9_EndScene(device);
1687         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
1688     }
1689     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1690     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
1691
1692     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1693     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
1694
1695     color = getPixelColor(device, 240, 320);
1696     ok(color == 0x0000FFFF, "R32F with value 0.0 has color %08x, expected 0x0000FFFF\n", color);
1697
1698 out:
1699     if(texture) IDirect3DTexture9_Release(texture);
1700     IDirect3D9_Release(d3d);
1701 }
1702
1703 static void texture_transform_flags_test(IDirect3DDevice9 *device)
1704 {
1705     HRESULT hr;
1706     IDirect3D9 *d3d;
1707     D3DFORMAT fmt = D3DFMT_X8R8G8B8;
1708     D3DCAPS9 caps;
1709     IDirect3DTexture9 *texture = NULL;
1710     IDirect3DVolumeTexture9 *volume = NULL;
1711     unsigned int x, y, z;
1712     D3DLOCKED_RECT lr;
1713     D3DLOCKED_BOX lb;
1714     DWORD color;
1715     IDirect3DVertexDeclaration9 *decl, *decl2;
1716     float identity[16] = {1.0, 0.0, 0.0, 0.0,
1717                            0.0, 1.0, 0.0, 0.0,
1718                            0.0, 0.0, 1.0, 0.0,
1719                            0.0, 0.0, 0.0, 1.0};
1720     static const D3DVERTEXELEMENT9 decl_elements[] = {
1721         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1722         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1723         D3DDECL_END()
1724     };
1725     static const D3DVERTEXELEMENT9 decl_elements2[] = {
1726         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1727         {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1728         D3DDECL_END()
1729     };
1730
1731     memset(&lr, 0, sizeof(lr));
1732     memset(&lb, 0, sizeof(lb));
1733     IDirect3DDevice9_GetDirect3D(device, &d3d);
1734     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
1735                                      D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16) == D3D_OK) {
1736         fmt = D3DFMT_A16B16G16R16;
1737     }
1738     IDirect3D9_Release(d3d);
1739
1740     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
1741     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
1742     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements2, &decl2);
1743     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
1744     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, FALSE);
1745     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_SRGBTEXTURE) returned %s\n", DXGetErrorString9(hr));
1746     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
1747     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MAGFILTER) returned %s\n", DXGetErrorString9(hr));
1748     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
1749     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MINFILTER) returned %s\n", DXGetErrorString9(hr));
1750     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
1751     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MIPFILTER) returned %s\n", DXGetErrorString9(hr));
1752     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1753     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSU) returned %s\n", DXGetErrorString9(hr));
1754     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1755     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSV) returned %s\n", DXGetErrorString9(hr));
1756     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP);
1757     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSW) returned %s\n", DXGetErrorString9(hr));
1758     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1759     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState(D3DRS_LIGHTING) returned %s\n", DXGetErrorString9(hr));
1760     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
1761     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
1762
1763     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1764     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %s\n", DXGetErrorString9(hr));
1765     hr = IDirect3DDevice9_CreateTexture(device, caps.MaxTextureWidth, caps.MaxTextureHeight, 1,
1766                                         0, fmt, D3DPOOL_MANAGED, &texture, NULL);
1767     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %s\n", DXGetErrorString9(hr));
1768     if(!texture) {
1769         skip("Failed to create the test texture\n");
1770         return;
1771     }
1772
1773     /* Unfortunately there is no easy way to set up a texture coordinate passthrough
1774      * in d3d fixed function pipeline, so create a texture that has a gradient from 0.0 to
1775      * 1.0 in red and green for the x and y coords
1776      */
1777     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
1778     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %s\n", DXGetErrorString9(hr));
1779     for(y = 0; y < caps.MaxTextureHeight; y++) {
1780         for(x = 0; x < caps.MaxTextureWidth; x++) {
1781             double r_f = (double) y / (double) caps.MaxTextureHeight;
1782             double g_f = (double) x / (double) caps.MaxTextureWidth;
1783             if(fmt == D3DFMT_A16B16G16R16) {
1784                 unsigned short r, g;
1785                 unsigned short *dst = (unsigned short *) (((char *) lr.pBits) + y * lr.Pitch + x * 8);
1786                 r = (unsigned short) (r_f * 65536.0);
1787                 g = (unsigned short) (g_f * 65536.0);
1788                 dst[0] = r;
1789                 dst[1] = g;
1790                 dst[2] = 0;
1791                 dst[3] = 65535;
1792             } else {
1793                 unsigned char *dst = ((unsigned char *) lr.pBits) + y * lr.Pitch + x * 4;
1794                 unsigned char r = (unsigned char) (r_f * 255.0);
1795                 unsigned char g = (unsigned char) (g_f * 255.0);
1796                 dst[0] = 0;
1797                 dst[1] = g;
1798                 dst[2] = r;
1799                 dst[3] = 255;
1800             }
1801         }
1802     }
1803     hr = IDirect3DTexture9_UnlockRect(texture, 0);
1804     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect returned %s\n", DXGetErrorString9(hr));
1805     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
1806     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
1807
1808     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
1809     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
1810     hr = IDirect3DDevice9_BeginScene(device);
1811     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
1812     if(SUCCEEDED(hr))
1813     {
1814         float quad1[] = {
1815             -1.0,      -1.0,       0.1,     1.0,    1.0,
1816             -1.0,       0.0,       0.1,     1.0,    1.0,
1817              0.0,      -1.0,       0.1,     1.0,    1.0,
1818              0.0,       0.0,       0.1,     1.0,    1.0,
1819         };
1820         float quad2[] = {
1821             -1.0,       0.0,       0.1,     1.0,    1.0,
1822             -1.0,       1.0,       0.1,     1.0,    1.0,
1823              0.0,       0.0,       0.1,     1.0,    1.0,
1824              0.0,       1.0,       0.1,     1.0,    1.0,
1825         };
1826         float quad3[] = {
1827              0.0,       0.0,       0.1,     0.5,    0.5,
1828              0.0,       1.0,       0.1,     0.5,    0.5,
1829              1.0,       0.0,       0.1,     0.5,    0.5,
1830              1.0,       1.0,       0.1,     0.5,    0.5,
1831         };
1832         float quad4[] = {
1833              320,       480,       0.1,     1.0,    0.0,    1.0,
1834              320,       240,       0.1,     1.0,    0.0,    1.0,
1835              640,       480,       0.1,     1.0,    0.0,    1.0,
1836              640,       240,       0.1,     1.0,    0.0,    1.0,
1837         };
1838         float mat[16] = {0.0, 0.0, 0.0, 0.0,
1839                           0.0, 0.0, 0.0, 0.0,
1840                           0.0, 0.0, 0.0, 0.0,
1841                           0.0, 0.0, 0.0, 0.0};
1842
1843         /* What happens with the texture matrix if D3DTSS_TEXTURETRANSFORMFLAGS is disabled? */
1844         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
1845         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
1846         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
1847         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1848
1849         /* What happens with transforms enabled? */
1850         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
1851         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
1852         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
1853         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1854
1855         /* What happens if 4 coords are used, but only 2 given ?*/
1856         mat[8] = 1.0;
1857         mat[13] = 1.0;
1858         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
1859         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
1860         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
1861         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
1862         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
1863         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1864
1865         /* What happens with transformed geometry? This setup lead to 0/0 coords with untransformed
1866          * geometry. If the same applies to transformed vertices, the quad will be black, otherwise red,
1867          * due to the coords in the vertices. (turns out red, indeed)
1868          */
1869         memset(mat, 0, sizeof(mat));
1870         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
1871         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
1872         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_TEX1);
1873         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
1874         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
1875         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
1876         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
1877         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1878
1879         hr = IDirect3DDevice9_EndScene(device);
1880         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
1881     }
1882     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1883     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
1884     color = getPixelColor(device, 160, 360);
1885     ok(color == 0x00FFFF00 || color == 0x00FEFE00, "quad 1 has color %08x, expected 0x00FFFF00\n", color);
1886     color = getPixelColor(device, 160, 120);
1887     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
1888     color = getPixelColor(device, 480, 120);
1889     ok(color == 0x0000FF00 || color == 0x0000FE00, "quad 3 has color %08x, expected 0x0000FF00\n", color);
1890     color = getPixelColor(device, 480, 360);
1891     ok(color == 0x00FF0000 || 0x00FE0000, "quad 4 has color %08x, expected 0x00FF0000\n", color);
1892
1893     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
1894     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
1895
1896     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
1897     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
1898     hr = IDirect3DDevice9_BeginScene(device);
1899     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
1900     if(SUCCEEDED(hr))
1901     {
1902         float quad1[] = {
1903             -1.0,      -1.0,       0.1,     0.8,    0.2,
1904             -1.0,       0.0,       0.1,     0.8,    0.2,
1905              0.0,      -1.0,       0.1,     0.8,    0.2,
1906              0.0,       0.0,       0.1,     0.8,    0.2,
1907         };
1908         float quad2[] = {
1909             -1.0,       0.0,       0.1,     0.5,    1.0,
1910             -1.0,       1.0,       0.1,     0.5,    1.0,
1911              0.0,       0.0,       0.1,     0.5,    1.0,
1912              0.0,       1.0,       0.1,     0.5,    1.0,
1913         };
1914         float quad3[] = {
1915              0.0,       0.0,       0.1,     0.5,    1.0,
1916              0.0,       1.0,       0.1,     0.5,    1.0,
1917              1.0,       0.0,       0.1,     0.5,    1.0,
1918              1.0,       1.0,       0.1,     0.5,    1.0,
1919         };
1920         float quad4[] = {
1921              0.0,      -1.0,       0.1,     0.8,    0.2,
1922              0.0,       0.0,       0.1,     0.8,    0.2,
1923              1.0,      -1.0,       0.1,     0.8,    0.2,
1924              1.0,       0.0,       0.1,     0.8,    0.2,
1925         };
1926         float mat[16] = {0.0, 0.0, 0.0, 0.0,
1927                           0.0, 0.0, 0.0, 0.0,
1928                           0.0, 1.0, 0.0, 0.0,
1929                           0.0, 0.0, 0.0, 0.0};
1930
1931         /* What happens to the default 1 in the 3rd coordinate if it is disabled?
1932          */
1933         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
1934         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
1935         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
1936         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
1937
1938         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
1939         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1940
1941         /* What does this mean? Not sure... */
1942         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
1943         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
1944         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 5 * sizeof(float));
1945         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1946
1947         /* Just to be sure, the same as quad2 above */
1948         memset(mat, 0, sizeof(mat));
1949         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
1950         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
1951         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
1952         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
1953         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
1954         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1955
1956         /* Now, what happens to the 2nd coordinate(that is disabled in the matrix) if it is not
1957          * used? And what happens to the first?
1958          */
1959         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
1960         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
1961         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
1962         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1963
1964         hr = IDirect3DDevice9_EndScene(device);
1965         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
1966     }
1967     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1968     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
1969     color = getPixelColor(device, 160, 360);
1970     ok(color == 0x00FF0000 || color == 0x00FE0000, "quad 1 has color %08x, expected 0x00FF0000\n", color);
1971     color = getPixelColor(device, 160, 120);
1972     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
1973     color = getPixelColor(device, 480, 120);
1974     ok(color == 0x00ff8000 || color == 0x00fe7f00, "quad 3 has color %08x, expected 0x00ff8000\n", color);
1975     color = getPixelColor(device, 480, 360);
1976     ok(color == 0x0033cc00 || color == 0x0032cb00, "quad 4 has color %08x, expected 0x0033cc00\n", color);
1977
1978     IDirect3DTexture9_Release(texture);
1979
1980     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff203040, 0.0, 0);
1981     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
1982     /* Use a smaller volume texture than the biggest possible size for memory and performance reasons
1983      * Thus watch out if sampling from texels between 0 and 1.
1984      */
1985     hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 32, 1, 0, fmt, D3DPOOL_MANAGED, &volume, 0);
1986     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
1987        "IDirect3DDevice9_CreateVolumeTexture failed with %s\n", DXGetErrorString9(hr));
1988     if(!volume) {
1989         skip("Failed to create a volume texture\n");
1990         goto out;
1991     }
1992
1993     hr = IDirect3DVolumeTexture9_LockBox(volume, 0, &lb, NULL, 0);
1994     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_LockBox failed with %s\n", DXGetErrorString9(hr));
1995     for(z = 0; z < 32; z++) {
1996         for(y = 0; y < 32; y++) {
1997             for(x = 0; x < 32; x++) {
1998                 char size = (fmt == D3DFMT_A16B16G16R16 ? 8 : 4);
1999                 void *mem = ((char *)  lb.pBits) + y * lb.RowPitch + z * lb.SlicePitch + x * size;
2000                 float r_f = (float) x / 31.0;
2001                 float g_f = (float) y / 31.0;
2002                 float b_f = (float) z / 31.0;
2003
2004                 if(fmt == D3DFMT_A16B16G16R16) {
2005                     unsigned short *mem_s = mem;
2006                     mem_s[0]  = r_f * 65535.0;
2007                     mem_s[1]  = g_f * 65535.0;
2008                     mem_s[2]  = b_f * 65535.0;
2009                     mem_s[3]  = 65535;
2010                 } else {
2011                     unsigned char *mem_c = mem;
2012                     mem_c[0]  = b_f * 255.0;
2013                     mem_c[1]  = g_f * 255.0;
2014                     mem_c[2]  = r_f * 255.0;
2015                     mem_c[3]  = 255;
2016                 }
2017             }
2018         }
2019     }
2020     hr = IDirect3DVolumeTexture9_UnlockBox(volume, 0);
2021     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %s\n", DXGetErrorString9(hr));
2022
2023     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) volume);
2024     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %s\n", DXGetErrorString9(hr));
2025
2026     hr = IDirect3DDevice9_BeginScene(device);
2027     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
2028     if(SUCCEEDED(hr))
2029     {
2030         float quad1[] = {
2031             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2032             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
2033              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2034              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
2035         };
2036         float quad2[] = {
2037             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
2038             -1.0,       1.0,       0.1,     1.0,    1.0,    1.0,
2039              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
2040              0.0,       1.0,       0.1,     1.0,    1.0,    1.0
2041         };
2042         float quad3[] = {
2043              0.0,       0.0,       0.1,     0.0,    0.0,
2044              0.0,       1.0,       0.1,     0.0,    0.0,
2045              1.0,       0.0,       0.1,     0.0,    0.0,
2046              1.0,       1.0,       0.1,     0.0,    0.0
2047         };
2048         float quad4[] = {
2049              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2050              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
2051              1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2052              1.0,       0.0,       0.1,     1.0,    1.0,    1.0
2053         };
2054         float mat[16] = {1.0, 0.0, 0.0, 0.0,
2055                           0.0, 0.0, 1.0, 0.0,
2056                           0.0, 1.0, 0.0, 0.0,
2057                           0.0, 0.0, 0.0, 1.0};
2058         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2059         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
2060
2061         /* Draw a quad with all 3 coords enabled. Nothing fancy. v and w are swapped, but have the same
2062          * values
2063          */
2064         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
2065         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2066         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
2067         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2068         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
2069         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2070
2071         /* Now disable the w coordinate. Does that change the input, or the output. The coordinates
2072          * are swapped by the matrix. If it changes the input, the v coord will be missing(green),
2073          * otherwise the w will be missing(blue).
2074          * turns out that the blue color is missing, so it is an output modification
2075          */
2076         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
2077         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2078         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
2079         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2080
2081         /* default values? Set up the identity matrix, pass in 2 vertex coords, and enable 4 */
2082         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
2083         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2084         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
2085         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2086         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2087         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2088         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
2089         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2090
2091         /* D3DTTFF_COUNT1. Set a NULL matrix, and count1, pass in all values as 1.0 */
2092         memset(mat, 0, sizeof(mat));
2093         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
2094         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2095         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
2096         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2097         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2098         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
2099         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
2100         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2101
2102         hr = IDirect3DDevice9_EndScene(device);
2103         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
2104     }
2105     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2106     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2107
2108     color = getPixelColor(device, 160, 360);
2109     ok(color == 0x00ffffff, "quad 1 has color %08x, expected 0x00ffffff\n", color);
2110     color = getPixelColor(device, 160, 120);
2111     ok(color == 0x00ffff00, "quad 2 has color %08x, expected 0x00ffff00\n", color);
2112     color = getPixelColor(device, 480, 120);
2113     ok(color == 0x000000ff, "quad 3 has color %08x, expected 0x000000ff\n", color);
2114     color = getPixelColor(device, 480, 360);
2115     ok(color == 0x00ffffff, "quad 4 has color %08x, expected 0x00ffffff\n", color);
2116
2117     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff303030, 0.0, 0);
2118     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
2119     hr = IDirect3DDevice9_BeginScene(device);
2120     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
2121     if(SUCCEEDED(hr))
2122     {
2123         float quad1[] = {
2124             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2125             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
2126              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2127              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
2128         };
2129         float quad2[] = {
2130             -1.0,       0.0,       0.1,
2131             -1.0,       1.0,       0.1,
2132              0.0,       0.0,       0.1,
2133              0.0,       1.0,       0.1,
2134         };
2135         float quad3[] = {
2136              0.0,       0.0,       0.1,     1.0,
2137              0.0,       1.0,       0.1,     1.0,
2138              1.0,       0.0,       0.1,     1.0,
2139              1.0,       1.0,       0.1,     1.0
2140         };
2141         float mat[16] =  {0.0, 0.0, 0.0, 0.0,
2142                            0.0, 0.0, 0.0, 0.0,
2143                            0.0, 0.0, 0.0, 0.0,
2144                            0.0, 1.0, 0.0, 0.0};
2145         float mat2[16] = {0.0, 0.0, 0.0, 1.0,
2146                            1.0, 0.0, 0.0, 0.0,
2147                            0.0, 1.0, 0.0, 0.0,
2148                            0.0, 0.0, 1.0, 0.0};
2149         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2150         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
2151
2152         /* Default values? 4 coords used, 3 passed. What happens to the 4th?
2153          */
2154         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
2155         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2156         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
2157         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2158         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
2159         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2160
2161         /* None passed */
2162         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
2163         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2164         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
2165         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2166         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
2167         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2168
2169         /* 4 used, 1 passed */
2170         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl2);
2171         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
2172         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat2);
2173         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2174         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 4 * sizeof(float));
2175         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2176
2177         hr = IDirect3DDevice9_EndScene(device);
2178         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
2179     }
2180     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2181     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2182     color = getPixelColor(device, 160, 360);
2183     ok(color == 0x0000ff00, "quad 1 has color %08x, expected 0x0000ff00\n", color);
2184     color = getPixelColor(device, 160, 120);
2185     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x00000000\n", color);
2186     color = getPixelColor(device, 480, 120);
2187     ok(color == 0x00ff0000, "quad 3 has color %08x, expected 0x00ff0000\n", color);
2188     /* Quad4: unused */
2189
2190     IDirect3DVolumeTexture9_Release(volume);
2191
2192     out:
2193     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2194     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
2195     IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
2196     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2197     hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &identity);
2198     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2199     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
2200     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
2201     IDirect3DVertexDeclaration9_Release(decl);
2202     IDirect3DVertexDeclaration9_Release(decl2);
2203 }
2204
2205 START_TEST(visual)
2206 {
2207     IDirect3DDevice9 *device_ptr;
2208     D3DCAPS9 caps;
2209     HRESULT hr;
2210     DWORD color;
2211
2212     d3d9_handle = LoadLibraryA("d3d9.dll");
2213     if (!d3d9_handle)
2214     {
2215         skip("Could not load d3d9.dll\n");
2216         return;
2217     }
2218
2219     device_ptr = init_d3d9();
2220     if (!device_ptr)
2221     {
2222         skip("Creating the device failed\n");
2223         return;
2224     }
2225
2226     IDirect3DDevice9_GetDeviceCaps(device_ptr, &caps);
2227
2228     /* Check for the reliability of the returned data */
2229     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
2230     if(FAILED(hr))
2231     {
2232         trace("Clear failed, can't assure correctness of the test results, skipping\n");
2233         goto cleanup;
2234     }
2235     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
2236
2237     color = getPixelColor(device_ptr, 1, 1);
2238     if(color !=0x00ff0000)
2239     {
2240         trace("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
2241         goto cleanup;
2242     }
2243
2244     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xff00ddee, 0.0, 0);
2245     if(FAILED(hr))
2246     {
2247         trace("Clear failed, can't assure correctness of the test results, skipping\n");
2248         goto cleanup;
2249     }
2250     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
2251
2252     color = getPixelColor(device_ptr, 639, 479);
2253     if(color != 0x0000ddee)
2254     {
2255         trace("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
2256         goto cleanup;
2257     }
2258
2259     /* Now execute the real tests */
2260     lighting_test(device_ptr);
2261     clear_test(device_ptr);
2262     fog_test(device_ptr);
2263     if(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
2264     {
2265         test_cube_wrap(device_ptr);
2266     } else {
2267         skip("No cube texture support\n");
2268     }
2269     present_test(device_ptr);
2270     if(caps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)
2271     {
2272         maxmip_test(device_ptr);
2273     }
2274     else
2275     {
2276         skip("No mipmap support\n");
2277     }
2278     offscreen_test(device_ptr);
2279     release_buffer_test(device_ptr);
2280     float_texture_test(device_ptr);
2281     texture_transform_flags_test(device_ptr);
2282
2283
2284     if (caps.VertexShaderVersion >= D3DVS_VERSION(2, 0))
2285     {
2286         test_mova(device_ptr);
2287     }
2288     else skip("No vs_2_0 support\n");
2289
2290     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1) && caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
2291     {
2292         fog_with_shader_test(device_ptr);
2293     }
2294     else skip("No vs_1_1 and ps_1_1 support\n");
2295
2296     if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
2297     {
2298         texbem_test(device_ptr);
2299     }
2300     else skip("No ps_1_1 support\n");
2301
2302 cleanup:
2303     if(device_ptr) IDirect3DDevice9_Release(device_ptr);
2304 }