wined3d: Implement mipmap auto generation.
[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 tvertex
135 {
136     float x, y, z, rhw;
137     DWORD diffuse;
138 };
139
140 struct nvertex
141 {
142     float x, y, z;
143     float nx, ny, nz;
144     DWORD diffuse;
145 };
146
147 static void lighting_test(IDirect3DDevice9 *device)
148 {
149     HRESULT hr;
150     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
151     DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
152     DWORD color;
153
154     float mat[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
155                       0.0f, 1.0f, 0.0f, 0.0f,
156                       0.0f, 0.0f, 1.0f, 0.0f,
157                       0.0f, 0.0f, 0.0f, 1.0f };
158
159     struct vertex unlitquad[] =
160     {
161         {-1.0f, -1.0f,   0.1f,                          0xffff0000},
162         {-1.0f,  0.0f,   0.1f,                          0xffff0000},
163         { 0.0f,  0.0f,   0.1f,                          0xffff0000},
164         { 0.0f, -1.0f,   0.1f,                          0xffff0000},
165     };
166     struct vertex litquad[] =
167     {
168         {-1.0f,  0.0f,   0.1f,                          0xff00ff00},
169         {-1.0f,  1.0f,   0.1f,                          0xff00ff00},
170         { 0.0f,  1.0f,   0.1f,                          0xff00ff00},
171         { 0.0f,  0.0f,   0.1f,                          0xff00ff00},
172     };
173     struct nvertex unlitnquad[] =
174     {
175         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
176         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
177         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
178         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
179     };
180     struct nvertex litnquad[] =
181     {
182         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
183         { 0.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
184         { 1.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
185         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
186     };
187     WORD Indices[] = {0, 1, 2, 2, 3, 0};
188
189     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
190     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
191
192     /* Setup some states that may cause issues */
193     hr = IDirect3DDevice9_SetTransform(device, D3DTS_WORLDMATRIX(0), (D3DMATRIX *) mat);
194     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %s\n", DXGetErrorString9(hr));
195     hr = IDirect3DDevice9_SetTransform(device, D3DTS_VIEW, (D3DMATRIX *)mat);
196     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %s\n", DXGetErrorString9(hr));
197     hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, (D3DMATRIX *) mat);
198     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform returned %s\n", DXGetErrorString9(hr));
199     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
200     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
201     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, FALSE);
202     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
203     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
204     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
205     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
206     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
207     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHATESTENABLE, FALSE);
208     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
209     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
210     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
211     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SCISSORTESTENABLE, FALSE);
212     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
213     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
214     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %s\n", DXGetErrorString9(hr));
215     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
216     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState failed with %s\n", DXGetErrorString9(hr));
217
218     hr = IDirect3DDevice9_SetFVF(device, fvf);
219     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
220
221     hr = IDirect3DDevice9_BeginScene(device);
222     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
223     if(hr == D3D_OK)
224     {
225         /* No lights are defined... That means, lit vertices should be entirely black */
226         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
227         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
228         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
229                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitquad, sizeof(unlitquad[0]));
230         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
231
232         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
233         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
234         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
235                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litquad, sizeof(litquad[0]));
236         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
237
238         hr = IDirect3DDevice9_SetFVF(device, nfvf);
239         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
240
241         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
242         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
243         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
244                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitnquad, sizeof(unlitnquad[0]));
245         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
246
247         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, TRUE);
248         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
249         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
250                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litnquad, sizeof(litnquad[0]));
251         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
252
253         IDirect3DDevice9_EndScene(device);
254         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
255     }
256
257     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
258
259     color = getPixelColor(device, 160, 360); /* lower left quad - unlit without normals */
260     ok(color == 0x00ff0000, "Unlit quad without normals has color %08x\n", color);
261     color = getPixelColor(device, 160, 120); /* upper left quad - lit without normals */
262     ok(color == 0x00000000, "Lit quad without normals has color %08x\n", color);
263     color = getPixelColor(device, 480, 360); /* lower left quad - unlit width normals */
264     ok(color == 0x000000ff, "Unlit quad width normals has color %08x\n", color);
265     color = getPixelColor(device, 480, 120); /* upper left quad - lit width normals */
266     ok(color == 0x00000000, "Lit quad width normals has color %08x\n", color);
267
268     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
269     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
270 }
271
272 static void clear_test(IDirect3DDevice9 *device)
273 {
274     /* Tests the correctness of clearing parameters */
275     HRESULT hr;
276     D3DRECT rect[2];
277     D3DRECT rect_negneg;
278     DWORD color;
279
280     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
281     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
282
283     /* Positive x, negative y */
284     rect[0].x1 = 0;
285     rect[0].y1 = 480;
286     rect[0].x2 = 320;
287     rect[0].y2 = 240;
288
289     /* Positive x, positive y */
290     rect[1].x1 = 0;
291     rect[1].y1 = 0;
292     rect[1].x2 = 320;
293     rect[1].y2 = 240;
294     /* Clear 2 rectangles with one call. Shows that a positive value is returned, but the negative rectangle
295      * is ignored, the positive is still cleared afterwards
296      */
297     hr = IDirect3DDevice9_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
298     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
299
300     /* negative x, negative y */
301     rect_negneg.x1 = 640;
302     rect_negneg.x1 = 240;
303     rect_negneg.x2 = 320;
304     rect_negneg.y2 = 0;
305     hr = IDirect3DDevice9_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
306     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %s\n", DXGetErrorString9(hr));
307
308     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
309
310     color = getPixelColor(device, 160, 360); /* lower left quad */
311     ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
312     color = getPixelColor(device, 160, 120); /* upper left quad */
313     ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
314     color = getPixelColor(device, 480, 360); /* lower right quad  */
315     ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
316     color = getPixelColor(device, 480, 120); /* upper right quad */
317     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
318 }
319
320 typedef struct {
321     float in[4];
322     DWORD out;
323 } test_data_t;
324
325 /*
326  *  c7      rounded     ARGB
327  * -2.4     -2          0x00ffff00
328  * -1.6     -2          0x00ffff00
329  * -0.4      0          0x0000ffff
330  *  0.4      0          0x0000ffff
331  *  1.6      2          0x00ff00ff
332  *  2.4      2          0x00ff00ff
333  */
334 static void test_mova(IDirect3DDevice9 *device)
335 {
336     static const DWORD mova_test[] = {
337         0xfffe0200,                                                             /* vs_2_0                       */
338         0x0200001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
339         0x05000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0   */
340         0x05000051, 0xa00f0001, 0x3f800000, 0x3f800000, 0x00000000, 0x3f800000, /* def c1, 1.0, 1.0, 0.0, 1.0   */
341         0x05000051, 0xa00f0002, 0x00000000, 0x3f800000, 0x00000000, 0x3f800000, /* def c2, 0.0, 1.0, 0.0, 1.0   */
342         0x05000051, 0xa00f0003, 0x00000000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c3, 0.0, 1.0, 1.0, 1.0   */
343         0x05000051, 0xa00f0004, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c4, 0.0, 0.0, 1.0, 1.0   */
344         0x05000051, 0xa00f0005, 0x3f800000, 0x00000000, 0x3f800000, 0x3f800000, /* def c5, 1.0, 0.0, 1.0, 1.0   */
345         0x05000051, 0xa00f0006, 0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000, /* def c6, 1.0, 1.0, 1.0, 1.0   */
346         0x0200002e, 0xb0010000, 0xa0000007,                                     /* mova a0.x, c7.x              */
347         0x03000001, 0xd00f0000, 0xa0e42003, 0xb0000000,                         /* mov oD0, c[a0.x + 3]         */
348         0x02000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
349         0x0000ffff                                                              /* END                          */
350     };
351
352     static const test_data_t test_data[] = {
353         {{-2.4f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
354         {{-1.6f, 0.0f, 0.0f, 0.0f}, 0x00ffff00},
355         {{-0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
356         {{ 0.4f, 0.0f, 0.0f, 0.0f}, 0x0000ffff},
357         {{ 1.6f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff},
358         {{ 2.4f, 0.0f, 0.0f, 0.0f}, 0x00ff00ff}
359     };
360
361     static const float quad[][3] = {
362         {-1.0f, -1.0f, 0.0f},
363         {-1.0f,  1.0f, 0.0f},
364         { 1.0f, -1.0f, 0.0f},
365         { 1.0f,  1.0f, 0.0f},
366     };
367
368     static const D3DVERTEXELEMENT9 decl_elements[] = {
369         {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
370         D3DDECL_END()
371     };
372
373     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
374     IDirect3DVertexShader9 *mova_shader = NULL;
375     HRESULT hr;
376     int i;
377
378     hr = IDirect3DDevice9_CreateVertexShader(device, mova_test, &mova_shader);
379     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
380     hr = IDirect3DDevice9_SetVertexShader(device, mova_shader);
381     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
382
383     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
384     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
385     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
386     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
387
388     for (i = 0; i < (sizeof(test_data) / sizeof(test_data_t)); ++i)
389     {
390         DWORD color;
391
392         hr = IDirect3DDevice9_SetVertexShaderConstantF(device, 7, test_data[i].in, 1);
393         ok(SUCCEEDED(hr), "SetVertexShaderConstantF failed (%08x)\n", hr);
394
395         hr = IDirect3DDevice9_BeginScene(device);
396         ok(SUCCEEDED(hr), "BeginScene failed (%08x)\n", hr);
397
398         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], 3 * sizeof(float));
399         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
400
401         hr = IDirect3DDevice9_EndScene(device);
402         ok(SUCCEEDED(hr), "EndScene failed (%08x)\n", hr);
403
404         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
405         ok(SUCCEEDED(hr), "Present failed (%08x)\n", hr);
406
407         color = getPixelColor(device, 320, 240);
408         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]);
409
410         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
411         ok(SUCCEEDED(hr), "Clear failed (%08x)\n", hr);
412     }
413
414     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
415     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
416
417     IDirect3DVertexDeclaration9_Release(vertex_declaration);
418     IDirect3DVertexShader9_Release(mova_shader);
419 }
420
421 struct sVertex {
422     float x, y, z;
423     DWORD diffuse;
424     DWORD specular;
425 };
426
427 struct sVertexT {
428     float x, y, z, rhw;
429     DWORD diffuse;
430     DWORD specular;
431 };
432
433 static void fog_test(IDirect3DDevice9 *device)
434 {
435     HRESULT hr;
436     DWORD color;
437     float start = 0.0f, end = 1.0f;
438     D3DCAPS9 caps;
439
440     /* Gets full z based fog with linear fog, no fog with specular color */
441     struct sVertex unstransformed_1[] = {
442         {-1,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
443         {-1,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
444         { 0,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
445         { 0,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
446     };
447     /* Ok, I am too lazy to deal with transform matrices */
448     struct sVertex unstransformed_2[] = {
449         {-1,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
450         {-1,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
451         { 0,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
452         { 0,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
453     };
454     /* Untransformed ones. Give them a different diffuse color to make the test look
455      * nicer. It also makes making sure that they are drawn correctly easier.
456      */
457     struct sVertexT transformed_1[] = {
458         {320,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
459         {640,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
460         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
461         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
462     };
463     struct sVertexT transformed_2[] = {
464         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
465         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
466         {640,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
467         {320,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
468     };
469     WORD Indices[] = {0, 1, 2, 2, 3, 0};
470
471     memset(&caps, 0, sizeof(caps));
472     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
473     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %s\n", DXGetErrorString9(hr));
474     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
475     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
476
477     /* Setup initial states: No lighting, fog on, fog color */
478     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
479     ok(hr == D3D_OK, "Turning off lighting returned %s\n", DXGetErrorString9(hr));
480     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
481     ok(hr == D3D_OK, "Turning on fog calculations returned %s\n", DXGetErrorString9(hr));
482     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
483     ok(hr == D3D_OK, "Turning on fog calculations returned %s\n", DXGetErrorString9(hr));
484
485     /* First test: Both table fog and vertex fog off */
486     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
487     ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString9(hr));
488     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
489     ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString9(hr));
490
491     /* Start = 0, end = 1. Should be default, but set them */
492     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
493     ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
494     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
495     ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
496
497     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
498     {
499         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
500         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
501         /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
502         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
503                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_1,
504                                                      sizeof(unstransformed_1[0]));
505         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
506
507         /* That makes it use the Z value */
508         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
509         ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString9(hr));
510         /* Untransformed, vertex fog != none (or table fog != none):
511          * Use the Z value as input into the equation
512          */
513         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
514                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_2,
515                                                      sizeof(unstransformed_1[0]));
516         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
517
518         /* transformed verts */
519         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
520         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
521         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
522         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
523                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
524                                                      sizeof(transformed_1[0]));
525         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
526
527         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
528         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %s\n", DXGetErrorString9(hr));
529         /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
530          * equation
531          */
532         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
533                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_2,
534                                                      sizeof(transformed_2[0]));
535
536         hr = IDirect3DDevice9_EndScene(device);
537         ok(hr == D3D_OK, "EndScene returned %s\n", DXGetErrorString9(hr));
538     }
539     else
540     {
541         ok(FALSE, "BeginScene failed\n");
542     }
543
544     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
545     color = getPixelColor(device, 160, 360);
546     ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color);
547     color = getPixelColor(device, 160, 120);
548     ok(color == 0x0000FF00, "Untransformed vertex with linear vertex fog has color %08x\n", color);
549     color = getPixelColor(device, 480, 120);
550     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
551     if(caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
552     {
553         color = getPixelColor(device, 480, 360);
554         ok(color == 0x0000FF00, "Transformed vertex with linear table fog has color %08x\n", color);
555     }
556     else
557     {
558         /* Without fog table support the vertex fog is still applied, even though table fog is turned on.
559          * The settings above result in no fogging with vertex fog
560          */
561         color = getPixelColor(device, 480, 120);
562         ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
563         trace("Info: Table fog not supported by this device\n");
564     }
565
566     /* Now test the special case fogstart == fogend */
567     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
568     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
569
570     if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
571     {
572         start = 512;
573         end = 512;
574         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
575         ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
576         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
577         ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
578
579         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
580         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
581         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
582         ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState %s\n", DXGetErrorString9(hr));
583         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
584         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %s\n", DXGetErrorString9(hr));
585
586         /* Untransformed vertex, z coord = 0.1, fogstart = 512, fogend = 512. Would result in
587          * a completely fog-free primitive because start > zcoord, but because start == end, the primitive
588          * is fully covered by fog. The same happens to the 2nd untransformed quad with z = 1.0.
589          * The third transformed quad remains unfogged because the fogcoords are read from the specular
590          * color and has fixed fogstart and fogend.
591          */
592         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
593                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_1,
594                 sizeof(unstransformed_1[0]));
595         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
596         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
597                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_2,
598                 sizeof(unstransformed_1[0]));
599         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
600
601         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
602         ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
603         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
604         hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
605                 2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
606                 sizeof(transformed_1[0]));
607         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
608
609         hr = IDirect3DDevice9_EndScene(device);
610         ok(hr == D3D_OK, "EndScene returned %s\n", DXGetErrorString9(hr));
611     }
612     else
613     {
614         ok(FALSE, "BeginScene failed\n");
615     }
616     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
617     color = getPixelColor(device, 160, 360);
618     ok(color == 0x0000FF00, "Untransformed vertex with vertex fog and z = 0.1 has color %08x\n", color);
619     color = getPixelColor(device, 160, 120);
620     ok(color == 0x0000FF00, "Untransformed vertex with vertex fog and z = 1.0 has color %08x\n", color);
621     color = getPixelColor(device, 480, 120);
622     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
623
624     /* Turn off the fog master switch to avoid confusing other tests */
625     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
626     ok(hr == D3D_OK, "Turning off fog calculations returned %s\n", DXGetErrorString9(hr));
627     start = 0.0;
628     end = 1.0;
629     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
630     ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
631     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
632     ok(hr == D3D_OK, "Setting fog end returned %s\n", DXGetErrorString9(hr));
633     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
634     ok( hr == D3D_OK, "IDirect3DDevice9_SetRenderState %s\n", DXGetErrorString9(hr));
635     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
636     ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %s\n", DXGetErrorString9(hr));
637 }
638
639 /* This test verifies the behaviour of cube maps wrt. texture wrapping.
640  * D3D cube map wrapping always behaves like GL_CLAMP_TO_EDGE,
641  * regardless of the actual addressing mode set. */
642 static void test_cube_wrap(IDirect3DDevice9 *device)
643 {
644     static const float quad[][6] = {
645         {-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
646         {-1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
647         { 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
648         { 1.0f,  1.0f, 0.0f, 1.0f, 1.0f, 1.0f},
649     };
650
651     static const D3DVERTEXELEMENT9 decl_elements[] = {
652         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
653         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
654         D3DDECL_END()
655     };
656
657     static const struct {
658         D3DTEXTUREADDRESS mode;
659         const char *name;
660     } address_modes[] = {
661         {D3DTADDRESS_WRAP, "D3DTADDRESS_WRAP"},
662         {D3DTADDRESS_MIRROR, "D3DTADDRESS_MIRROR"},
663         {D3DTADDRESS_CLAMP, "D3DTADDRESS_CLAMP"},
664         {D3DTADDRESS_BORDER, "D3DTADDRESS_BORDER"},
665         {D3DTADDRESS_MIRRORONCE, "D3DTADDRESS_MIRRORONCE"},
666     };
667
668     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
669     IDirect3DCubeTexture9 *texture = NULL;
670     IDirect3DSurface9 *surface = NULL;
671     D3DLOCKED_RECT locked_rect;
672     HRESULT hr;
673     INT x, y, face;
674
675     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
676     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
677     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
678     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
679
680     hr = IDirect3DDevice9_CreateOffscreenPlainSurface(device, 128, 128,
681             D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, NULL);
682     ok(SUCCEEDED(hr), "CreateOffscreenPlainSurface failed (0x%08x)\n", hr);
683
684     hr = IDirect3DSurface9_LockRect(surface, &locked_rect, NULL, D3DLOCK_DISCARD);
685     ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
686
687     for (y = 0; y < 128; ++y)
688     {
689         DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
690         for (x = 0; x < 64; ++x)
691         {
692             *ptr++ = 0xffff0000;
693         }
694         for (x = 64; x < 128; ++x)
695         {
696             *ptr++ = 0xff0000ff;
697         }
698     }
699
700     hr = IDirect3DSurface9_UnlockRect(surface);
701     ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
702
703     hr = IDirect3DDevice9_CreateCubeTexture(device, 128, 1, 0, D3DFMT_A8R8G8B8,
704             D3DPOOL_DEFAULT, &texture, NULL);
705     ok(SUCCEEDED(hr), "CreateCubeTexture failed (0x%08x)\n", hr);
706
707     /* Create cube faces */
708     for (face = 0; face < 6; ++face)
709     {
710         IDirect3DSurface9 *face_surface = NULL;
711
712         hr= IDirect3DCubeTexture9_GetCubeMapSurface(texture, face, 0, &face_surface);
713         ok(SUCCEEDED(hr), "GetCubeMapSurface failed (0x%08x)\n", hr);
714
715         hr = IDirect3DDevice9_UpdateSurface(device, surface, NULL, face_surface, NULL);
716         ok(SUCCEEDED(hr), "UpdateSurface failed (0x%08x)\n", hr);
717
718         IDirect3DSurface9_Release(face_surface);
719     }
720
721     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *)texture);
722     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
723
724     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
725     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
726     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
727     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
728     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_BORDERCOLOR, 0xff00ff00);
729     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_BORDERCOLOR failed (0x%08x)\n", hr);
730
731     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
732     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
733
734     for (x = 0; x < (sizeof(address_modes) / sizeof(*address_modes)); ++x)
735     {
736         DWORD color;
737
738         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, address_modes[x].mode);
739         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU (%s) failed (0x%08x)\n", address_modes[x].name, hr);
740         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, address_modes[x].mode);
741         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV (%s) failed (0x%08x)\n", address_modes[x].name, hr);
742
743         hr = IDirect3DDevice9_BeginScene(device);
744         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
745
746         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
747         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
748
749         hr = IDirect3DDevice9_EndScene(device);
750         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
751
752         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
753         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
754
755         /* Due to the nature of this test, we sample essentially at the edge
756          * between two faces. Because of this it's undefined from which face
757          * the driver will sample. Furtunately that's not important for this
758          * test, since all we care about is that it doesn't sample from the
759          * other side of the surface or from the border. */
760         color = getPixelColor(device, 320, 240);
761         ok(color == 0x00ff0000 || color == 0x000000ff,
762                 "Got color 0x%08x for addressing mode %s, expected 0x00ff0000 or 0x000000ff.\n",
763                 color, address_modes[x].name);
764
765         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
766         ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
767     }
768
769     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
770     ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
771
772     IDirect3DVertexDeclaration9_Release(vertex_declaration);
773     IDirect3DCubeTexture9_Release(texture);
774     IDirect3DSurface9_Release(surface);
775 }
776
777 static void offscreen_test(IDirect3DDevice9 *device)
778 {
779     HRESULT hr;
780     IDirect3DTexture9 *offscreenTexture = NULL;
781     IDirect3DSurface9 *backbuffer = NULL, *offscreen = NULL;
782     DWORD color;
783
784     static const float quad[][5] = {
785         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
786         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
787         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
788         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
789     };
790
791     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
792     ok(hr == D3D_OK, "Clear failed, hr = %s\n", DXGetErrorString9(hr));
793
794     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
795     ok(hr == D3D_OK || D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %s\n", DXGetErrorString9(hr));
796     if(!offscreenTexture) {
797         trace("Failed to create an X8R8G8B8 offscreen texture, trying R5G6B5\n");
798         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &offscreenTexture, NULL);
799         ok(hr == D3D_OK || D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %s\n", DXGetErrorString9(hr));
800         if(!offscreenTexture) {
801             skip("Cannot create an offscreen render target\n");
802             goto out;
803         }
804     }
805
806     hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
807     ok(hr == D3D_OK, "Can't get back buffer, hr = %s\n", DXGetErrorString9(hr));
808     if(!backbuffer) {
809         goto out;
810     }
811
812     hr = IDirect3DTexture9_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
813     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %s\n", DXGetErrorString9(hr));
814     if(!offscreen) {
815         goto out;
816     }
817
818     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
819     ok(hr == D3D_OK, "SetFVF failed, hr = %s\n", DXGetErrorString9(hr));
820
821     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
822     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
823     hr = IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
824     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %s\n", DXGetErrorString9(hr));
825     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_NONE);
826     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
827     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_NONE);
828     ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
829     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
830     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
831
832     if(IDirect3DDevice9_BeginScene(device) == D3D_OK) {
833         hr = IDirect3DDevice9_SetRenderTarget(device, 0, offscreen);
834         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %s\n", DXGetErrorString9(hr));
835         hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
836         ok(hr == D3D_OK, "Clear failed, hr = %s\n", DXGetErrorString9(hr));
837
838         /* Draw without textures - Should resut in a white quad */
839         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
840         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %s\n", DXGetErrorString9(hr));
841
842         hr = IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
843         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %s\n", DXGetErrorString9(hr));
844         hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) offscreenTexture);
845         ok(hr == D3D_OK, "SetTexture failed, %s\n", DXGetErrorString9(hr));
846
847         /* This time with the texture */
848         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
849         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %s\n", DXGetErrorString9(hr));
850
851         IDirect3DDevice9_EndScene(device);
852     }
853
854     IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
855
856     /* Center quad - should be white */
857     color = getPixelColor(device, 320, 240);
858     ok(color == 0x00ffffff, "Offscreen failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
859     /* Some quad in the cleared part of the texture */
860     color = getPixelColor(device, 170, 240);
861     ok(color == 0x00ff00ff, "Offscreen failed: Got color 0x%08x, expected 0x00ff00ff.\n", color);
862     /* Part of the originally cleared back buffer */
863     color = getPixelColor(device, 10, 10);
864     ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
865     if(0) {
866         /* Lower left corner of the screen, where back buffer offscreen rendering draws the offscreen texture.
867          * It should be red, but the offscreen texture may leave some junk there. Not tested yet. Depending on
868          * the offscreen rendering mode this test would succeed or fail
869          */
870         color = getPixelColor(device, 10, 470);
871         ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
872     }
873
874 out:
875     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
876
877     /* restore things */
878     if(backbuffer) {
879         IDirect3DDevice9_SetRenderTarget(device, 0, backbuffer);
880         IDirect3DSurface9_Release(backbuffer);
881     }
882     if(offscreenTexture) {
883         IDirect3DTexture9_Release(offscreenTexture);
884     }
885     if(offscreen) {
886         IDirect3DSurface9_Release(offscreen);
887     }
888 }
889
890 /* This test tests fog in combination with shaders.
891  * What's tested: linear fog (vertex and table) with pixel shader
892  *                linear table fog with non foggy vertex shader
893  *                vertex fog with foggy vertex shader
894  * What's not tested: non linear fog with shader
895  *                    table fog with foggy vertex shader
896  */
897 static void fog_with_shader_test(IDirect3DDevice9 *device)
898 {
899     HRESULT hr;
900     DWORD color;
901     union {
902         float f;
903         DWORD i;
904     } start, end;
905     unsigned int i, j;
906
907     /* basic vertex shader without fog computation ("non foggy") */
908     static const DWORD vertex_shader_code1[] = {
909         0xfffe0101,                                                             /* vs_1_1                       */
910         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0              */
911         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                */
912         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
913         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                  */
914         0x0000ffff
915     };
916     /* basic vertex shader with reversed fog computation ("foggy") */
917     static const DWORD vertex_shader_code2[] = {
918         0xfffe0101,                                                             /* vs_1_1                        */
919         0x0000001f, 0x80000000, 0x900f0000,                                     /* dcl_position v0               */
920         0x0000001f, 0x8000000a, 0x900f0001,                                     /* dcl_color0 v1                 */
921         0x00000051, 0xa00f0000, 0xbfa00000, 0x00000000, 0xbf666666, 0x00000000, /* def c0, -1.25, 0.0, -0.9, 0.0 */
922         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                  */
923         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                   */
924         0x00000002, 0x800f0000, 0x90aa0000, 0xa0aa0000,                         /* add r0, v0.z, c0.z            */
925         0x00000005, 0xc00f0001, 0x80000000, 0xa0000000,                         /* mul oFog, r0.x, c0.x          */
926         0x0000ffff
927     };
928     /* basic pixel shader */
929     static const DWORD pixel_shader_code[] = {
930         0xffff0101,                                                             /* ps_1_1     */
931         0x00000001, 0x800f0000, 0x90e40000,                                     /* mov r0, vo */
932         0x0000ffff
933     };
934
935     static struct vertex quad[] = {
936         {-1.0f, -1.0f,  0.0f,          0xFFFF0000  },
937         {-1.0f,  1.0f,  0.0f,          0xFFFF0000  },
938         { 1.0f, -1.0f,  0.0f,          0xFFFF0000  },
939         { 1.0f,  1.0f,  0.0f,          0xFFFF0000  },
940     };
941
942     static const D3DVERTEXELEMENT9 decl_elements[] = {
943         {0,  0, D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
944         {0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT,    D3DDECLUSAGE_COLOR, 0},
945         D3DDECL_END()
946     };
947
948     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
949     IDirect3DVertexShader9      *vertex_shader[3]   = {NULL, NULL, NULL};
950     IDirect3DPixelShader9       *pixel_shader[2]    = {NULL, NULL};
951
952     /* This reference data was collected on a nVidia GeForce 7600GS driver version 84.19 DirectX version 9.0c on Windows XP */
953     static const struct test_data_t {
954         int vshader;
955         int pshader;
956         D3DFOGMODE vfog;
957         D3DFOGMODE tfog;
958         unsigned int color[11];
959     } test_data[] = {
960         /* only pixel shader: */
961         {0, 1, 0, 3,
962         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
963          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
964         {0, 1, 1, 3,
965         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
966          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
967         {0, 1, 2, 3,
968         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
969          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
970         {0, 1, 3, 0,
971         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
972          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
973         {0, 1, 3, 3,
974         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
975          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
976
977         /* vertex shader */
978         {1, 0, 0, 0,
979         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
980          0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
981         {1, 0, 0, 3,
982         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
983          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
984         {1, 0, 1, 3,
985         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
986          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
987         {1, 0, 2, 3,
988         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
989          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
990         {1, 0, 3, 3,
991         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
992          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
993
994         /* vertex shader and pixel shader */
995         {1, 1, 0, 3,
996         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
997          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
998         {1, 1, 1, 3,
999         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1000          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1001         {1, 1, 2, 3,
1002         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1003          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1004         {1, 1, 3, 3,
1005         {0x0000ff00, 0x0000ff00, 0x0020df00, 0x0040bf00, 0x005fa000, 0x007f8000,
1006          0x009f6000, 0x00bf4000, 0x00df2000, 0x00ff0000, 0x00ff0000}},
1007
1008 #if 0  /* FIXME: these fail on GeForce 8500 */
1009         /* foggy vertex shader */
1010         {2, 0, 0, 0,
1011         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1012          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1013         {2, 0, 1, 0,
1014         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1015          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1016         {2, 0, 2, 0,
1017         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1018          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1019         {2, 0, 3, 0,
1020         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1021          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1022 #endif
1023
1024         /* foggy vertex shader and pixel shader */
1025         {2, 1, 0, 0,
1026         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1027          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1028         {2, 1, 1, 0,
1029         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1030          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1031         {2, 1, 2, 0,
1032         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1033          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1034         {2, 1, 3, 0,
1035         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
1036          0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
1037
1038     };
1039
1040     /* NOTE: changing these values will not affect the tests with foggy vertex shader, as the values are hardcoded in the shader*/
1041     start.f=0.9f;
1042     end.f=0.1f;
1043
1044     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code1, &vertex_shader[1]);
1045     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1046     hr = IDirect3DDevice9_CreateVertexShader(device, vertex_shader_code2, &vertex_shader[2]);
1047     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
1048     hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader[1]);
1049     ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1050     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &vertex_declaration);
1051     ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (%08x)\n", hr);
1052
1053     /* Setup initial states: No lighting, fog on, fog color */
1054     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1055     ok(hr == D3D_OK, "Turning off lighting failed (%08x)\n", hr);
1056     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
1057     ok(hr == D3D_OK, "Turning on fog calculations failed (%08x)\n", hr);
1058     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
1059     ok(hr == D3D_OK, "Setting fog color failed (%08x)\n", hr);
1060     hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1061     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1062
1063     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
1064     ok(hr == D3D_OK, "Turning off table fog failed (%08x)\n", hr);
1065     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
1066     ok(hr == D3D_OK, "Turning off vertex fog failed (%08x)\n", hr);
1067
1068     /* Use fogtart = 0.1 and end = 0.9 to test behavior outside the fog transition phase, too*/
1069     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, start.i);
1070     ok(hr == D3D_OK, "Setting fog start failed (%08x)\n", hr);
1071     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, end.i);
1072     ok(hr == D3D_OK, "Setting fog end failed (%08x)\n", hr);
1073
1074     for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); i++)
1075     {
1076         hr = IDirect3DDevice9_SetVertexShader(device, vertex_shader[test_data[i].vshader]);
1077         ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1078         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader[test_data[i].pshader]);
1079         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1080         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, test_data[i].vfog);
1081         ok( hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1082         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, test_data[i].tfog);
1083         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR failed (%08x)\n", hr);
1084
1085         for(j=0; j < 11; j++)
1086         {
1087             /* Don't use the whole zrange to prevent rounding errors */
1088             quad[0].z = 0.001f + (float)j / 10.02f;
1089             quad[1].z = 0.001f + (float)j / 10.02f;
1090             quad[2].z = 0.001f + (float)j / 10.02f;
1091             quad[3].z = 0.001f + (float)j / 10.02f;
1092
1093             hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1094             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
1095
1096             hr = IDirect3DDevice9_BeginScene(device);
1097             ok( hr == D3D_OK, "BeginScene returned failed (%08x)\n", hr);
1098
1099             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1100             ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1101
1102             hr = IDirect3DDevice9_EndScene(device);
1103             ok(hr == D3D_OK, "EndScene failed (%08x)\n", hr);
1104
1105             IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1106
1107             /* As the red and green component are the result of blending use 5% tolerance on the expected value */
1108             color = getPixelColor(device, 128, 240);
1109             ok((unsigned char)(color) == ((unsigned char)test_data[i].color[j])
1110                     && abs( ((unsigned char)(color>>8)) - (unsigned char)(test_data[i].color[j]>>8) ) < 13
1111                     && abs( ((unsigned char)(color>>16)) - (unsigned char)(test_data[i].color[j]>>16) ) < 13,
1112                     "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]);
1113         }
1114     }
1115
1116     /* reset states */
1117     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
1118     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1119     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1120     ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1121     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1122     ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1123     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
1124     ok(hr == D3D_OK, "Turning off fog calculations failed (%08x)\n", hr);
1125
1126     IDirect3DVertexShader9_Release(vertex_shader[1]);
1127     IDirect3DVertexShader9_Release(vertex_shader[2]);
1128     IDirect3DPixelShader9_Release(pixel_shader[1]);
1129     IDirect3DVertexDeclaration9_Release(vertex_declaration);
1130 }
1131
1132 /* test the behavior of the texbem instruction
1133  * with normal 2D and projective 2D textures
1134  */
1135 static void texbem_test(IDirect3DDevice9 *device)
1136 {
1137     HRESULT hr;
1138     DWORD color;
1139     unsigned int i, x, y;
1140
1141     static const DWORD pixel_shader_code[] = {
1142         0xffff0101,                         /* ps_1_1*/
1143         0x00000042, 0xb00f0000,             /* tex t0*/
1144         0x00000043, 0xb00f0001, 0xb0e40000, /* texbem t1, t0*/
1145         0x00000001, 0x800f0000, 0xb0e40001, /* mov r0, t1*/
1146         0x0000ffff
1147     };
1148
1149     static const float quad[][7] = {
1150         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f, 0.0f, 0.0f},
1151         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f, 0.0f, 1.0f},
1152         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 1.0f, 0.0f},
1153         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 1.0f, 1.0f},
1154     };
1155     static const float quad_proj[][9] = {
1156         {-128.0f/640.0f, -128.0f/480.0f, 0.1f, 0.0f, 0.0f,   0.0f,   0.0f, 0.0f, 128.0f},
1157         {-128.0f/640.0f,  128.0f/480.0f, 0.1f, 0.0f, 1.0f,   0.0f, 128.0f, 0.0f, 128.0f},
1158         { 128.0f/640.0f, -128.0f/480.0f, 0.1f, 1.0f, 0.0f, 128.0f,   0.0f, 0.0f, 128.0f},
1159         { 128.0f/640.0f,  128.0f/480.0f, 0.1f, 1.0f, 1.0f, 128.0f, 128.0f, 0.0f, 128.0f},
1160     };
1161
1162     static const D3DVERTEXELEMENT9 decl_elements[][4] = { {
1163         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1164         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1165         {0, 20, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1166         D3DDECL_END()
1167     },{
1168         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1169         {0, 12, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1170         {0, 20, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
1171         D3DDECL_END()
1172     } };
1173
1174     /* use assymetric matrix to test loading */
1175     float bumpenvmat[4] = {0.0,0.5,-0.5,0.0};
1176
1177     IDirect3DVertexDeclaration9 *vertex_declaration = NULL;
1178     IDirect3DPixelShader9       *pixel_shader       = NULL;
1179     IDirect3DTexture9           *texture[2]         = {NULL, NULL};
1180     D3DLOCKED_RECT locked_rect;
1181
1182     /* Generate the textures */
1183     for(i=0; i<2; i++)
1184     {
1185         hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 1, 0, i?D3DFMT_A8R8G8B8:D3DFMT_V8U8,
1186                 D3DPOOL_MANAGED, &texture[i], NULL);
1187         ok(SUCCEEDED(hr), "CreateTexture failed (0x%08x)\n", hr);
1188
1189         hr = IDirect3DTexture9_LockRect(texture[i], 0, &locked_rect, NULL, D3DLOCK_DISCARD);
1190         ok(SUCCEEDED(hr), "LockRect failed (0x%08x)\n", hr);
1191         for (y = 0; y < 128; ++y)
1192         {
1193             if(i)
1194             { /* Set up black texture with 2x2 texel white spot in the middle */
1195                 DWORD *ptr = (DWORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1196                 for (x = 0; x < 128; ++x)
1197                 {
1198                     if(y>62 && y<66 && x>62 && x<66)
1199                         *ptr++ = 0xffffffff;
1200                     else
1201                         *ptr++ = 0xff000000;
1202                 }
1203             }
1204             else
1205             { /* Set up a displacement map which points away from the center parallel to the closest axis.
1206               * (if multiplied with bumpenvmat)
1207               */
1208                 WORD *ptr = (WORD *)(((BYTE *)locked_rect.pBits) + (y * locked_rect.Pitch));
1209                 for (x = 0; x < 128; ++x)
1210                 {
1211                     if(abs(x-64)>abs(y-64))
1212                     {
1213                         if(x < 64)
1214                             *ptr++ = 0xc000;
1215                         else
1216                             *ptr++ = 0x4000;
1217                     }
1218                     else
1219                     {
1220                         if(y < 64)
1221                             *ptr++ = 0x0040;
1222                         else
1223                             *ptr++ = 0x00c0;
1224                     }
1225                 }
1226             }
1227         }
1228         hr = IDirect3DTexture9_UnlockRect(texture[i], 0);
1229         ok(SUCCEEDED(hr), "UnlockRect failed (0x%08x)\n", hr);
1230
1231         hr = IDirect3DDevice9_SetTexture(device, i, (IDirect3DBaseTexture9 *)texture[i]);
1232         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1233
1234         /* Disable texture filtering */
1235         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MINFILTER, D3DTEXF_POINT);
1236         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
1237         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
1238         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
1239
1240         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1241         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSU failed (0x%08x)\n", hr);
1242         hr = IDirect3DDevice9_SetSamplerState(device, i, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1243         ok(SUCCEEDED(hr), "SetSamplerState D3DSAMP_ADDRESSV failed (0x%08x)\n", hr);
1244     }
1245
1246     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT00, *(LPDWORD)&bumpenvmat[0]);
1247     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT01, *(LPDWORD)&bumpenvmat[1]);
1248     IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT10, *(LPDWORD)&bumpenvmat[2]);
1249     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_BUMPENVMAT11, *(LPDWORD)&bumpenvmat[3]);
1250     ok(SUCCEEDED(hr), "SetTextureStageState failed (%08x)\n", hr);
1251
1252     hr = IDirect3DDevice9_SetVertexShader(device, NULL);
1253     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
1254
1255     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1256     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
1257
1258     for(i=0; i<2; i++)
1259     {
1260         if(i)
1261         {
1262             hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4|D3DTTFF_PROJECTED);
1263             ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
1264         }
1265
1266         hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements[i], &vertex_declaration);
1267         ok(SUCCEEDED(hr), "CreateVertexDeclaration failed (0x%08x)\n", hr);
1268         hr = IDirect3DDevice9_SetVertexDeclaration(device, vertex_declaration);
1269         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (0x%08x)\n", hr);
1270
1271         hr = IDirect3DDevice9_CreatePixelShader(device, pixel_shader_code, &pixel_shader);
1272         ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
1273         hr = IDirect3DDevice9_SetPixelShader(device, pixel_shader);
1274         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1275
1276         hr = IDirect3DDevice9_BeginScene(device);
1277         ok(SUCCEEDED(hr), "BeginScene failed (0x%08x)\n", hr);
1278
1279         if(!i)
1280             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
1281         else
1282             hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad_proj[0], sizeof(quad_proj[0]));
1283         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (0x%08x)\n", hr);
1284
1285         hr = IDirect3DDevice9_EndScene(device);
1286         ok(SUCCEEDED(hr), "EndScene failed (0x%08x)\n", hr);
1287
1288         hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1289         ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1290
1291         color = getPixelColor(device, 320-32, 240);
1292         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1293         color = getPixelColor(device, 320+32, 240);
1294         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1295         color = getPixelColor(device, 320, 240-32);
1296         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1297         color = getPixelColor(device, 320, 240+32);
1298         ok(color == 0x00ffffff, "texbem failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1299
1300         hr = IDirect3DDevice9_SetPixelShader(device, NULL);
1301         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
1302         IDirect3DPixelShader9_Release(pixel_shader);
1303
1304         hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1305         ok(SUCCEEDED(hr), "SetVertexDeclaration failed (%08x)\n", hr);
1306         IDirect3DVertexDeclaration9_Release(vertex_declaration);
1307     }
1308
1309     /* clean up */
1310     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0f, 0);
1311     ok(SUCCEEDED(hr), "Clear failed (0x%08x)\n", hr);
1312
1313     hr = IDirect3DDevice9_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
1314     ok(SUCCEEDED(hr), "SetTextureStageState D3DTSS_TEXTURETRANSFORMFLAGS failed (0x%08x)\n", hr);
1315
1316     for(i=0; i<2; i++)
1317     {
1318         hr = IDirect3DDevice9_SetTexture(device, i, NULL);
1319         ok(SUCCEEDED(hr), "SetTexture failed (0x%08x)\n", hr);
1320         IDirect3DCubeTexture9_Release(texture[i]);
1321     }
1322 }
1323
1324 static void z_range_test(IDirect3DDevice9 *device)
1325 {
1326     const struct vertex quad[] =
1327     {
1328         {-1.0f,  0.0f,   1.1f,                          0xffff0000},
1329         {-1.0f,  1.0f,   1.1f,                          0xffff0000},
1330         { 1.0f,  0.0f,  -1.1f,                          0xffff0000},
1331         { 1.0f,  1.0f,  -1.1f,                          0xffff0000},
1332     };
1333     const struct vertex quad2[] =
1334     {
1335         {-1.0f,  0.0f,   1.1f,                          0xff0000ff},
1336         {-1.0f,  1.0f,   1.1f,                          0xff0000ff},
1337         { 1.0f,  0.0f,  -1.1f,                          0xff0000ff},
1338         { 1.0f,  1.0f,  -1.1f,                          0xff0000ff},
1339     };
1340
1341     const struct tvertex quad3[] =
1342     {
1343         {    0,   240,   1.1f,  1.0,                    0xffffff00},
1344         {    0,   480,   1.1f,  1.0,                    0xffffff00},
1345         {  640,   240,  -1.1f,  1.0,                    0xffffff00},
1346         {  640,   480,  -1.1f,  1.0,                    0xffffff00},
1347     };
1348     const struct tvertex quad4[] =
1349     {
1350         {    0,   240,   1.1f,  1.0,                    0xff00ff00},
1351         {    0,   480,   1.1f,  1.0,                    0xff00ff00},
1352         {  640,   240,  -1.1f,  1.0,                    0xff00ff00},
1353         {  640,   480,  -1.1f,  1.0,                    0xff00ff00},
1354     };
1355     HRESULT hr;
1356     DWORD color;
1357     IDirect3DVertexShader9 *shader;
1358     IDirect3DVertexDeclaration9 *decl;
1359     const DWORD shader_code[] = {
1360         0xfffe0101,                                     /* vs_1_1           */
1361         0x0000001f, 0x80000000, 0x900f0000,             /* dcl_position v0  */
1362         0x00000001, 0xc00f0000, 0x90e40000,             /* mov oPos, v0     */
1363         0x00000001, 0xd00f0000, 0xa0e40000,             /* mov oD0, c0      */
1364         0x0000ffff                                      /* end              */
1365     };
1366     static const D3DVERTEXELEMENT9 decl_elements[] = {
1367         {0, 0,  D3DDECLTYPE_FLOAT3,   D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1368         D3DDECL_END()
1369     };
1370     /* Does the Present clear the depth stencil? Clear the depth buffer with some value != 0,
1371      * then call Present. Then clear the color buffer to make sure it has some defined content
1372      * after the Present with D3DSWAPEFFECT_DISCARD. After that draw a plane that is somewhere cut
1373      * by the depth value.
1374      */
1375     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.75, 0);
1376     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
1377     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1378     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4, 0);
1379
1380     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, TRUE);
1381     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1382     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
1383     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1384     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
1385     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1386     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
1387     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1388     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1389     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
1390
1391     hr = IDirect3DDevice9_BeginScene(device);
1392     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
1393     if(hr == D3D_OK)
1394     {
1395         /* Test the untransformed vertex path */
1396         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
1397         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1398         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS);
1399         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1400         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad2, sizeof(quad2[0]));
1401         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1402
1403         /* Test the transformed vertex path */
1404         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
1405         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
1406
1407         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad4, sizeof(quad4[0]));
1408         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1409         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
1410         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1411         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad3, sizeof(quad3[0]));
1412         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1413
1414         hr = IDirect3DDevice9_EndScene(device);
1415         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
1416     }
1417
1418     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1419     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1420
1421     /* Do not test the exact corner pixels, but go pretty close to them */
1422
1423     /* Clipped because z > 1.0 */
1424     color = getPixelColor(device, 28, 238);
1425     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1426     color = getPixelColor(device, 28, 241);
1427     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1428
1429     /* Not clipped, > z buffer clear value(0.75) */
1430     color = getPixelColor(device, 31, 238);
1431     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1432     color = getPixelColor(device, 31, 241);
1433     ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
1434     color = getPixelColor(device, 100, 238);
1435     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1436     color = getPixelColor(device, 100, 241);
1437     ok(color == 0x00ffff00, "Z range failed: Got color 0x%08x, expected 0x00ffff00.\n", color);
1438
1439     /* Not clipped, < z buffer clear value */
1440     color = getPixelColor(device, 104, 238);
1441     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
1442     color = getPixelColor(device, 104, 241);
1443     ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color);
1444     color = getPixelColor(device, 318, 238);
1445     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
1446     color = getPixelColor(device, 318, 241);
1447     ok(color == 0x0000ff00, "Z range failed: Got color 0x%08x, expected 0x0000ff00.\n", color);
1448
1449     /* Clipped because z < 0.0 */
1450     color = getPixelColor(device, 321, 238);
1451     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1452     color = getPixelColor(device, 321, 241);
1453     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1454
1455     /* Test the shader path */
1456     hr = IDirect3DDevice9_CreateVertexShader(device, shader_code, &shader);
1457     if(FAILED(hr)) {
1458         skip("Can't create test vertex shader, most likely shaders not supported\n");
1459         goto out;
1460     }
1461     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
1462
1463     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4, 0);
1464
1465     IDirect3DDevice9_SetVertexDeclaration(device, decl);
1466     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
1467     IDirect3DDevice9_SetVertexShader(device, shader);
1468     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
1469
1470     hr = IDirect3DDevice9_BeginScene(device);
1471     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
1472     if(hr == D3D_OK)
1473     {
1474         float colorf[] = {1.0, 0.0, 0.0, 1.0};
1475         float colorf2[] = {0.0, 0.0, 1.0, 1.0};
1476         IDirect3DDevice9_SetVertexShaderConstantF(device, 0, colorf, 1);
1477         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
1478         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1479         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESS);
1480         ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1481         IDirect3DDevice9_SetVertexShaderConstantF(device, 0, colorf2, 1);
1482         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad2, sizeof(quad2[0]));
1483         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitiveUP failed with %s\n", DXGetErrorString9(hr));
1484
1485         hr = IDirect3DDevice9_EndScene(device);
1486         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
1487     }
1488
1489     IDirect3DDevice9_SetVertexDeclaration(device, NULL);
1490     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration returned %s\n", DXGetErrorString9(hr));
1491     IDirect3DDevice9_SetVertexShader(device, NULL);
1492     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexShader returned %s\n", DXGetErrorString9(hr));
1493
1494     IDirect3DVertexDeclaration9_Release(decl);
1495     IDirect3DVertexShader9_Release(shader);
1496
1497     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1498     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1499     /* Z < 1.0 */
1500     color = getPixelColor(device, 28, 238);
1501     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1502
1503     /* 1.0 < z < 0.75 */
1504     color = getPixelColor(device, 31, 238);
1505     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1506     color = getPixelColor(device, 100, 238);
1507     ok(color == 0x00ff0000, "Z range failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1508
1509     /* 0.75 < z < 0.0 */
1510     color = getPixelColor(device, 104, 238);
1511     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
1512     color = getPixelColor(device, 318, 238);
1513     ok(color == 0x000000ff, "Z range failed: Got color 0x%08x, expected 0x000000ff.\n", color);
1514
1515     /* 0.0 < z */
1516     color = getPixelColor(device, 321, 238);
1517     ok(color == 0x00ffffff, "Z range failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1518
1519     out:
1520     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
1521     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1522     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_CLIPPING, FALSE);
1523     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1524     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
1525     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
1526 }
1527
1528 static void fill_surface(IDirect3DSurface9 *surface, DWORD color)
1529 {
1530     D3DSURFACE_DESC desc;
1531     D3DLOCKED_RECT l;
1532     HRESULT hr;
1533     unsigned int x, y;
1534     DWORD *mem;
1535
1536     memset(&desc, 0, sizeof(desc));
1537     memset(&l, 0, sizeof(l));
1538     hr = IDirect3DSurface9_GetDesc(surface, &desc);
1539     ok(hr == D3D_OK, "IDirect3DSurface9_GetDesc failed with %s\n", DXGetErrorString9(hr));
1540     hr = IDirect3DSurface9_LockRect(surface, &l, NULL, D3DLOCK_DISCARD);
1541     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect failed with %s\n", DXGetErrorString9(hr));
1542     if(FAILED(hr)) return;
1543
1544     for(y = 0; y < desc.Height; y++)
1545     {
1546         mem = (DWORD *) ((BYTE *) l.pBits + y * l.Pitch);
1547         for(x = 0; x < l.Pitch / sizeof(DWORD); x++)
1548         {
1549             mem[x] = color;
1550         }
1551     }
1552     hr = IDirect3DSurface9_UnlockRect(surface);
1553     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect failed with %s\n", DXGetErrorString9(hr));
1554 }
1555
1556 static void maxmip_test(IDirect3DDevice9 *device)
1557 {
1558     IDirect3DTexture9 *texture = NULL;
1559     IDirect3DSurface9 *surface = NULL;
1560     HRESULT hr;
1561     DWORD color;
1562     const float quads[] = {
1563         -1.0,   -1.0,   0.0,    0.0,    0.0,
1564         -1.0,    0.0,   0.0,    0.0,    1.0,
1565          0.0,   -1.0,   0.0,    1.0,    0.0,
1566          0.0,    0.0,   0.0,    1.0,    1.0,
1567
1568          0.0,   -1.0,   0.0,    0.0,    0.0,
1569          0.0,    0.0,   0.0,    0.0,    1.0,
1570          1.0,   -1.0,   0.0,    1.0,    0.0,
1571          1.0,    0.0,   0.0,    1.0,    1.0,
1572
1573          0.0,    0.0,   0.0,    0.0,    0.0,
1574          0.0,    1.0,   0.0,    0.0,    1.0,
1575          1.0,    0.0,   0.0,    1.0,    0.0,
1576          1.0,    1.0,   0.0,    1.0,    1.0,
1577
1578         -1.0,    0.0,   0.0,    0.0,    0.0,
1579         -1.0,    1.0,   0.0,    0.0,    1.0,
1580          0.0,    0.0,   0.0,    1.0,    0.0,
1581          0.0,    1.0,   0.0,    1.0,    1.0,
1582     };
1583
1584     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
1585     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
1586
1587     hr = IDirect3DDevice9_CreateTexture(device, 128, 128, 3, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
1588                                         &texture, NULL);
1589     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %s\n", DXGetErrorString9(hr));
1590     if(!texture)
1591     {
1592         skip("Failed to create test texture\n");
1593         return;
1594     }
1595
1596     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
1597     fill_surface(surface, 0xffff0000);
1598     IDirect3DSurface9_Release(surface);
1599     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 1, &surface);
1600     fill_surface(surface, 0xff00ff00);
1601     IDirect3DSurface9_Release(surface);
1602     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 2, &surface);
1603     fill_surface(surface, 0xff0000ff);
1604     IDirect3DSurface9_Release(surface);
1605
1606     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
1607     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
1608     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
1609     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
1610
1611     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
1612     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1613
1614     hr = IDirect3DDevice9_BeginScene(device);
1615     if(SUCCEEDED(hr))
1616     {
1617         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
1618         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1619         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[ 0], 5 * sizeof(float));
1620         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1621
1622         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
1623         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1624         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[20], 5 * sizeof(float));
1625         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1626
1627         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
1628         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1629         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[40], 5 * sizeof(float));
1630         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1631
1632         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
1633         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1634         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[60], 5 * sizeof(float));
1635         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1636         hr = IDirect3DDevice9_EndScene(device);
1637     }
1638
1639     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1640     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1641     /* With mipmapping disabled, the max mip level is ignored, only level 0 is used */
1642     color = getPixelColor(device, 160, 360);
1643     ok(color == 0x00FF0000, "MapMip 0, no mipfilter has color %08x\n", color);
1644     color = getPixelColor(device, 160, 120);
1645     ok(color == 0x00FF0000, "MapMip 3, no mipfilter has color %08x\n", color);
1646     color = getPixelColor(device, 480, 120);
1647     ok(color == 0x00FF0000, "MapMip 2, no mipfilter has color %08x\n", color);
1648     color = getPixelColor(device, 480, 360);
1649     ok(color == 0x00FF0000, "MapMip 1, no mipfilter has color %08x\n", color);
1650
1651     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0, 0);
1652     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
1653
1654     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
1655     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1656
1657     hr = IDirect3DDevice9_BeginScene(device);
1658     if(SUCCEEDED(hr))
1659     {
1660         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
1661         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1662         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[ 0], 5 * sizeof(float));
1663         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1664
1665         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 1);
1666         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1667         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[20], 5 * sizeof(float));
1668         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1669
1670         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 2);
1671         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1672         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[40], 5 * sizeof(float));
1673         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1674
1675         hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 3);
1676         ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1677         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quads[60], 5 * sizeof(float));
1678         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1679         hr = IDirect3DDevice9_EndScene(device);
1680     }
1681
1682     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
1683     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1684     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
1685     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1686
1687     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1688     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1689     /* Max Mip level 0-2 sample from the specified texture level, Max Mip level 3(> levels in texture)
1690      * samples from the highest level in the texture(level 2)
1691      */
1692     color = getPixelColor(device, 160, 360);
1693     ok(color == 0x00FF0000, "MapMip 0, point mipfilter has color %08x\n", color);
1694     color = getPixelColor(device, 160, 120);
1695     ok(color == 0x000000FF, "MapMip 3, point mipfilter has color %08x\n", color);
1696     color = getPixelColor(device, 480, 120);
1697     ok(color == 0x000000FF, "MapMip 2, point mipfilter has color %08x\n", color);
1698     color = getPixelColor(device, 480, 360);
1699     ok(color == 0x0000FF00, "MapMip 1, point mipfilter has color %08x\n", color);
1700
1701     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1702     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
1703     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAXMIPLEVEL, 0);
1704     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
1705     IDirect3DTexture9_Release(texture);
1706 }
1707
1708 static void release_buffer_test(IDirect3DDevice9 *device)
1709 {
1710     IDirect3DVertexBuffer9 *vb = NULL;
1711     IDirect3DIndexBuffer9 *ib = NULL;
1712     HRESULT hr;
1713     BYTE *data;
1714     long ref;
1715
1716     static const struct vertex quad[] = {
1717         {-1.0,      -1.0,       0.1,        0xffff0000},
1718         {-1.0,       1.0,       0.1,        0xffff0000},
1719         { 1.0,       1.0,       0.1,        0xffff0000},
1720
1721         {-1.0,      -1.0,       0.1,        0xff00ff00},
1722         {-1.0,       1.0,       0.1,        0xff00ff00},
1723         { 1.0,       1.0,       0.1,        0xff00ff00}
1724     };
1725     short indices[] = {3, 4, 5};
1726
1727     /* Index and vertex buffers should always be creatable */
1728     hr = IDirect3DDevice9_CreateVertexBuffer(device, sizeof(quad), 0, D3DFVF_XYZ | D3DFVF_DIFFUSE,
1729                                               D3DPOOL_MANAGED, &vb, NULL);
1730     ok(hr == D3D_OK, "CreateVertexBuffer failed with %s\n", DXGetErrorString9(hr));
1731     if(!vb) {
1732         skip("Failed to create a vertex buffer\n");
1733         return;
1734     }
1735     hr = IDirect3DDevice9_CreateIndexBuffer(device, sizeof(indices), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &ib, NULL);
1736     ok(hr == D3D_OK, "IDirect3DDevice9_CreateIndexBuffer failed with %s\n", DXGetErrorString9(hr));
1737     if(!ib) {
1738         skip("Failed to create an index buffer\n");
1739         return;
1740     }
1741
1742     hr = IDirect3DVertexBuffer9_Lock(vb, 0, sizeof(quad), (void **) &data, 0);
1743     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
1744     memcpy(data, quad, sizeof(quad));
1745     hr = IDirect3DVertexBuffer9_Unlock(vb);
1746     ok(hr == D3D_OK, "IDirect3DVertexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr));
1747
1748     hr = IDirect3DIndexBuffer9_Lock(ib, 0, sizeof(indices), (void **) &data, 0);
1749     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Lock failed with %s\n", DXGetErrorString9(hr));
1750     memcpy(data, indices, sizeof(indices));
1751     hr = IDirect3DIndexBuffer9_Unlock(ib);
1752     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %s\n", DXGetErrorString9(hr));
1753
1754     hr = IDirect3DDevice9_SetIndices(device, ib);
1755     ok(hr == D3D_OK, "IDirect3DIndexBuffer8_Unlock failed with %s\n", DXGetErrorString9(hr));
1756     hr = IDirect3DDevice9_SetStreamSource(device, 0, vb, 0, sizeof(quad[0]));
1757     ok(hr == D3D_OK, "IDirect3DIndexBuffer8_Unlock failed with %s\n", DXGetErrorString9(hr));
1758     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1759     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
1760
1761     /* Now destroy the bound index buffer and draw again */
1762     ref = IDirect3DIndexBuffer9_Release(ib);
1763     ok(ref == 0, "Index Buffer reference count is %08ld\n", ref);
1764
1765     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
1766     ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed with %08x\n", hr);
1767
1768     hr = IDirect3DDevice9_BeginScene(device);
1769     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %08x\n", hr);
1770     if(SUCCEEDED(hr))
1771     {
1772         /* Deliberately using minvertexindex = 0 and numVertices = 6 to prevent d3d from
1773          * making assumptions about the indices or vertices
1774          */
1775         hr = IDirect3DDevice9_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, 0, 3, 3, 0, 1);
1776         ok(hr == D3D_OK, "IDirect3DDevice9_DrawIndexedPrimitive failed with %08x\n", hr);
1777         hr = IDirect3DDevice9_EndScene(device);
1778         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %08x\n", hr);
1779     }
1780
1781     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1782     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %08x\n", hr);
1783
1784     hr = IDirect3DDevice9_SetIndices(device, NULL);
1785     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
1786     hr = IDirect3DDevice9_SetStreamSource(device, 0, NULL, 0, 0);
1787     ok(hr == D3D_OK, "IDirect3DIndexBuffer9_Unlock failed with %08x\n", hr);
1788
1789     /* Index buffer was already destroyed as part of the test */
1790     IDirect3DVertexBuffer9_Release(vb);
1791 }
1792
1793 static void float_texture_test(IDirect3DDevice9 *device)
1794 {
1795     IDirect3D9 *d3d = NULL;
1796     HRESULT hr;
1797     IDirect3DTexture9 *texture = NULL;
1798     D3DLOCKED_RECT lr;
1799     float *data;
1800     DWORD color;
1801     float quad[] = {
1802         -1.0,      -1.0,       0.1,     0.0,    0.0,
1803         -1.0,       1.0,       0.1,     0.0,    1.0,
1804          1.0,      -1.0,       0.1,     1.0,    0.0,
1805          1.0,       1.0,       0.1,     1.0,    1.0,
1806     };
1807
1808     memset(&lr, 0, sizeof(lr));
1809     IDirect3DDevice9_GetDirect3D(device, &d3d);
1810     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
1811                                      D3DRTYPE_TEXTURE, D3DFMT_R32F) != D3D_OK) {
1812         skip("D3DFMT_R32F textures not supported\n");
1813         goto out;
1814     }
1815
1816     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_R32F,
1817                                         D3DPOOL_MANAGED, &texture, NULL);
1818     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed with %s\n", DXGetErrorString9(hr));
1819     if(!texture) {
1820         skip("Failed to create R32F texture\n");
1821         goto out;
1822     }
1823
1824     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
1825     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed with %s\n", DXGetErrorString9(hr));
1826     data = lr.pBits;
1827     *data = 0.0;
1828     hr = IDirect3DTexture9_UnlockRect(texture, 0);
1829     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed with %s\n", DXGetErrorString9(hr));
1830
1831     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
1832     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
1833
1834     hr = IDirect3DDevice9_BeginScene(device);
1835     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
1836     if(SUCCEEDED(hr))
1837     {
1838         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
1839         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
1840
1841         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
1842         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
1843
1844         hr = IDirect3DDevice9_EndScene(device);
1845         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
1846     }
1847     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
1848     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed with %s\n", DXGetErrorString9(hr));
1849
1850     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
1851     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
1852
1853     color = getPixelColor(device, 240, 320);
1854     ok(color == 0x0000FFFF, "R32F with value 0.0 has color %08x, expected 0x0000FFFF\n", color);
1855
1856 out:
1857     if(texture) IDirect3DTexture9_Release(texture);
1858     IDirect3D9_Release(d3d);
1859 }
1860
1861 static void texture_transform_flags_test(IDirect3DDevice9 *device)
1862 {
1863     HRESULT hr;
1864     IDirect3D9 *d3d;
1865     D3DFORMAT fmt = D3DFMT_X8R8G8B8;
1866     D3DCAPS9 caps;
1867     IDirect3DTexture9 *texture = NULL;
1868     IDirect3DVolumeTexture9 *volume = NULL;
1869     unsigned int x, y, z;
1870     D3DLOCKED_RECT lr;
1871     D3DLOCKED_BOX lb;
1872     DWORD color;
1873     IDirect3DVertexDeclaration9 *decl, *decl2;
1874     float identity[16] = {1.0, 0.0, 0.0, 0.0,
1875                            0.0, 1.0, 0.0, 0.0,
1876                            0.0, 0.0, 1.0, 0.0,
1877                            0.0, 0.0, 0.0, 1.0};
1878     static const D3DVERTEXELEMENT9 decl_elements[] = {
1879         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1880         {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1881         D3DDECL_END()
1882     };
1883     static const D3DVERTEXELEMENT9 decl_elements2[] = {
1884         {0, 0,  D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
1885         {0, 12, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
1886         D3DDECL_END()
1887     };
1888
1889     memset(&lr, 0, sizeof(lr));
1890     memset(&lb, 0, sizeof(lb));
1891     IDirect3DDevice9_GetDirect3D(device, &d3d);
1892     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
1893                                      D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16) == D3D_OK) {
1894         fmt = D3DFMT_A16B16G16R16;
1895     }
1896     IDirect3D9_Release(d3d);
1897
1898     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements, &decl);
1899     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
1900     hr = IDirect3DDevice9_CreateVertexDeclaration(device, decl_elements2, &decl2);
1901     ok(hr == D3D_OK, "IDirect3DDevice9_CreateVertexDeclaration returned %s\n", DXGetErrorString9(hr));
1902     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_SRGBTEXTURE, FALSE);
1903     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_SRGBTEXTURE) returned %s\n", DXGetErrorString9(hr));
1904     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
1905     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MAGFILTER) returned %s\n", DXGetErrorString9(hr));
1906     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
1907     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MINFILTER) returned %s\n", DXGetErrorString9(hr));
1908     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
1909     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_MIPFILTER) returned %s\n", DXGetErrorString9(hr));
1910     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1911     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSU) returned %s\n", DXGetErrorString9(hr));
1912     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1913     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSV) returned %s\n", DXGetErrorString9(hr));
1914     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP);
1915     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState(D3DSAMP_ADDRESSW) returned %s\n", DXGetErrorString9(hr));
1916     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1917     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState(D3DRS_LIGHTING) returned %s\n", DXGetErrorString9(hr));
1918     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
1919     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
1920
1921     hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
1922     ok(hr == D3D_OK, "IDirect3DDevice9_GetDeviceCaps returned %s\n", DXGetErrorString9(hr));
1923     hr = IDirect3DDevice9_CreateTexture(device, caps.MaxTextureWidth, caps.MaxTextureHeight, 1,
1924                                         0, fmt, D3DPOOL_MANAGED, &texture, NULL);
1925     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %s\n", DXGetErrorString9(hr));
1926     if(!texture) {
1927         skip("Failed to create the test texture\n");
1928         return;
1929     }
1930
1931     /* Unfortunately there is no easy way to set up a texture coordinate passthrough
1932      * in d3d fixed function pipeline, so create a texture that has a gradient from 0.0 to
1933      * 1.0 in red and green for the x and y coords
1934      */
1935     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
1936     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect returned %s\n", DXGetErrorString9(hr));
1937     for(y = 0; y < caps.MaxTextureHeight; y++) {
1938         for(x = 0; x < caps.MaxTextureWidth; x++) {
1939             double r_f = (double) y / (double) caps.MaxTextureHeight;
1940             double g_f = (double) x / (double) caps.MaxTextureWidth;
1941             if(fmt == D3DFMT_A16B16G16R16) {
1942                 unsigned short r, g;
1943                 unsigned short *dst = (unsigned short *) (((char *) lr.pBits) + y * lr.Pitch + x * 8);
1944                 r = (unsigned short) (r_f * 65536.0);
1945                 g = (unsigned short) (g_f * 65536.0);
1946                 dst[0] = r;
1947                 dst[1] = g;
1948                 dst[2] = 0;
1949                 dst[3] = 65535;
1950             } else {
1951                 unsigned char *dst = ((unsigned char *) lr.pBits) + y * lr.Pitch + x * 4;
1952                 unsigned char r = (unsigned char) (r_f * 255.0);
1953                 unsigned char g = (unsigned char) (g_f * 255.0);
1954                 dst[0] = 0;
1955                 dst[1] = g;
1956                 dst[2] = r;
1957                 dst[3] = 255;
1958             }
1959         }
1960     }
1961     hr = IDirect3DTexture9_UnlockRect(texture, 0);
1962     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect returned %s\n", DXGetErrorString9(hr));
1963     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
1964     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
1965
1966     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
1967     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
1968     hr = IDirect3DDevice9_BeginScene(device);
1969     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
1970     if(SUCCEEDED(hr))
1971     {
1972         float quad1[] = {
1973             -1.0,      -1.0,       0.1,     1.0,    1.0,
1974             -1.0,       0.0,       0.1,     1.0,    1.0,
1975              0.0,      -1.0,       0.1,     1.0,    1.0,
1976              0.0,       0.0,       0.1,     1.0,    1.0,
1977         };
1978         float quad2[] = {
1979             -1.0,       0.0,       0.1,     1.0,    1.0,
1980             -1.0,       1.0,       0.1,     1.0,    1.0,
1981              0.0,       0.0,       0.1,     1.0,    1.0,
1982              0.0,       1.0,       0.1,     1.0,    1.0,
1983         };
1984         float quad3[] = {
1985              0.0,       0.0,       0.1,     0.5,    0.5,
1986              0.0,       1.0,       0.1,     0.5,    0.5,
1987              1.0,       0.0,       0.1,     0.5,    0.5,
1988              1.0,       1.0,       0.1,     0.5,    0.5,
1989         };
1990         float quad4[] = {
1991              320,       480,       0.1,     1.0,    0.0,    1.0,
1992              320,       240,       0.1,     1.0,    0.0,    1.0,
1993              640,       480,       0.1,     1.0,    0.0,    1.0,
1994              640,       240,       0.1,     1.0,    0.0,    1.0,
1995         };
1996         float mat[16] = {0.0, 0.0, 0.0, 0.0,
1997                           0.0, 0.0, 0.0, 0.0,
1998                           0.0, 0.0, 0.0, 0.0,
1999                           0.0, 0.0, 0.0, 0.0};
2000
2001         /* What happens with the texture matrix if D3DTSS_TEXTURETRANSFORMFLAGS is disabled? */
2002         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
2003         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2004         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
2005         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2006
2007         /* What happens with transforms enabled? */
2008         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
2009         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2010         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
2011         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2012
2013         /* What happens if 4 coords are used, but only 2 given ?*/
2014         mat[8] = 1.0;
2015         mat[13] = 1.0;
2016         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
2017         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2018         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
2019         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2020         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
2021         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2022
2023         /* What happens with transformed geometry? This setup lead to 0/0 coords with untransformed
2024          * geometry. If the same applies to transformed vertices, the quad will be black, otherwise red,
2025          * due to the coords in the vertices. (turns out red, indeed)
2026          */
2027         memset(mat, 0, sizeof(mat));
2028         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
2029         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2030         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_TEX1);
2031         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
2032         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2033         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2034         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
2035         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2036
2037         hr = IDirect3DDevice9_EndScene(device);
2038         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
2039     }
2040     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2041     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2042     color = getPixelColor(device, 160, 360);
2043     ok(color == 0x00FFFF00 || color == 0x00FEFE00, "quad 1 has color %08x, expected 0x00FFFF00\n", color);
2044     color = getPixelColor(device, 160, 120);
2045     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
2046     color = getPixelColor(device, 480, 120);
2047     ok(color == 0x0000FF00 || color == 0x0000FE00, "quad 3 has color %08x, expected 0x0000FF00\n", color);
2048     color = getPixelColor(device, 480, 360);
2049     ok(color == 0x00FF0000 || 0x00FE0000, "quad 4 has color %08x, expected 0x00FF0000\n", color);
2050
2051     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0, 0);
2052     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
2053
2054     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2055     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2056     hr = IDirect3DDevice9_BeginScene(device);
2057     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
2058     if(SUCCEEDED(hr))
2059     {
2060         float quad1[] = {
2061             -1.0,      -1.0,       0.1,     0.8,    0.2,
2062             -1.0,       0.0,       0.1,     0.8,    0.2,
2063              0.0,      -1.0,       0.1,     0.8,    0.2,
2064              0.0,       0.0,       0.1,     0.8,    0.2,
2065         };
2066         float quad2[] = {
2067             -1.0,       0.0,       0.1,     0.5,    1.0,
2068             -1.0,       1.0,       0.1,     0.5,    1.0,
2069              0.0,       0.0,       0.1,     0.5,    1.0,
2070              0.0,       1.0,       0.1,     0.5,    1.0,
2071         };
2072         float quad3[] = {
2073              0.0,       0.0,       0.1,     0.5,    1.0,
2074              0.0,       1.0,       0.1,     0.5,    1.0,
2075              1.0,       0.0,       0.1,     0.5,    1.0,
2076              1.0,       1.0,       0.1,     0.5,    1.0,
2077         };
2078         float quad4[] = {
2079              0.0,      -1.0,       0.1,     0.8,    0.2,
2080              0.0,       0.0,       0.1,     0.8,    0.2,
2081              1.0,      -1.0,       0.1,     0.8,    0.2,
2082              1.0,       0.0,       0.1,     0.8,    0.2,
2083         };
2084         float mat[16] = {0.0, 0.0, 0.0, 0.0,
2085                           0.0, 0.0, 0.0, 0.0,
2086                           0.0, 1.0, 0.0, 0.0,
2087                           0.0, 0.0, 0.0, 0.0};
2088
2089         /* What happens to the default 1 in the 3rd coordinate if it is disabled?
2090          */
2091         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
2092         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2093         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
2094         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2095
2096         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 5 * sizeof(float));
2097         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2098
2099         /* What does this mean? Not sure... */
2100         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
2101         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2102         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 5 * sizeof(float));
2103         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2104
2105         /* Just to be sure, the same as quad2 above */
2106         memset(mat, 0, sizeof(mat));
2107         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &mat);
2108         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2109         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
2110         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2111         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
2112         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2113
2114         /* Now, what happens to the 2nd coordinate(that is disabled in the matrix) if it is not
2115          * used? And what happens to the first?
2116          */
2117         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
2118         ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2119         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
2120         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
2121
2122         hr = IDirect3DDevice9_EndScene(device);
2123         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
2124     }
2125     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2126     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2127     color = getPixelColor(device, 160, 360);
2128     ok(color == 0x00FF0000 || color == 0x00FE0000, "quad 1 has color %08x, expected 0x00FF0000\n", color);
2129     color = getPixelColor(device, 160, 120);
2130     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x0000000\n", color);
2131     color = getPixelColor(device, 480, 120);
2132     ok(color == 0x00ff8000 || color == 0x00fe7f00, "quad 3 has color %08x, expected 0x00ff8000\n", color);
2133     color = getPixelColor(device, 480, 360);
2134     ok(color == 0x0033cc00 || color == 0x0032cb00, "quad 4 has color %08x, expected 0x0033cc00\n", color);
2135
2136     IDirect3DTexture9_Release(texture);
2137
2138     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff203040, 0.0, 0);
2139     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
2140     /* Use a smaller volume texture than the biggest possible size for memory and performance reasons
2141      * Thus watch out if sampling from texels between 0 and 1.
2142      */
2143     hr = IDirect3DDevice9_CreateVolumeTexture(device, 32, 32, 32, 1, 0, fmt, D3DPOOL_MANAGED, &volume, 0);
2144     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL,
2145        "IDirect3DDevice9_CreateVolumeTexture failed with %s\n", DXGetErrorString9(hr));
2146     if(!volume) {
2147         skip("Failed to create a volume texture\n");
2148         goto out;
2149     }
2150
2151     hr = IDirect3DVolumeTexture9_LockBox(volume, 0, &lb, NULL, 0);
2152     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_LockBox failed with %s\n", DXGetErrorString9(hr));
2153     for(z = 0; z < 32; z++) {
2154         for(y = 0; y < 32; y++) {
2155             for(x = 0; x < 32; x++) {
2156                 char size = (fmt == D3DFMT_A16B16G16R16 ? 8 : 4);
2157                 void *mem = ((char *)  lb.pBits) + y * lb.RowPitch + z * lb.SlicePitch + x * size;
2158                 float r_f = (float) x / 31.0;
2159                 float g_f = (float) y / 31.0;
2160                 float b_f = (float) z / 31.0;
2161
2162                 if(fmt == D3DFMT_A16B16G16R16) {
2163                     unsigned short *mem_s = mem;
2164                     mem_s[0]  = r_f * 65535.0;
2165                     mem_s[1]  = g_f * 65535.0;
2166                     mem_s[2]  = b_f * 65535.0;
2167                     mem_s[3]  = 65535;
2168                 } else {
2169                     unsigned char *mem_c = mem;
2170                     mem_c[0]  = b_f * 255.0;
2171                     mem_c[1]  = g_f * 255.0;
2172                     mem_c[2]  = r_f * 255.0;
2173                     mem_c[3]  = 255;
2174                 }
2175             }
2176         }
2177     }
2178     hr = IDirect3DVolumeTexture9_UnlockBox(volume, 0);
2179     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %s\n", DXGetErrorString9(hr));
2180
2181     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) volume);
2182     ok(hr == D3D_OK, "IDirect3DVolumeTexture9_UnlockBox failed with %s\n", DXGetErrorString9(hr));
2183
2184     hr = IDirect3DDevice9_BeginScene(device);
2185     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
2186     if(SUCCEEDED(hr))
2187     {
2188         float quad1[] = {
2189             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2190             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
2191              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2192              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
2193         };
2194         float quad2[] = {
2195             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
2196             -1.0,       1.0,       0.1,     1.0,    1.0,    1.0,
2197              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
2198              0.0,       1.0,       0.1,     1.0,    1.0,    1.0
2199         };
2200         float quad3[] = {
2201              0.0,       0.0,       0.1,     0.0,    0.0,
2202              0.0,       1.0,       0.1,     0.0,    0.0,
2203              1.0,       0.0,       0.1,     0.0,    0.0,
2204              1.0,       1.0,       0.1,     0.0,    0.0
2205         };
2206         float quad4[] = {
2207              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2208              0.0,       0.0,       0.1,     1.0,    1.0,    1.0,
2209              1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2210              1.0,       0.0,       0.1,     1.0,    1.0,    1.0
2211         };
2212         float mat[16] = {1.0, 0.0, 0.0, 0.0,
2213                           0.0, 0.0, 1.0, 0.0,
2214                           0.0, 1.0, 0.0, 0.0,
2215                           0.0, 0.0, 0.0, 1.0};
2216         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2217         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
2218
2219         /* Draw a quad with all 3 coords enabled. Nothing fancy. v and w are swapped, but have the same
2220          * values
2221          */
2222         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
2223         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2224         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
2225         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2226         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
2227         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2228
2229         /* Now disable the w coordinate. Does that change the input, or the output. The coordinates
2230          * are swapped by the matrix. If it changes the input, the v coord will be missing(green),
2231          * otherwise the w will be missing(blue).
2232          * turns out that the blue color is missing, so it is an output modification
2233          */
2234         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
2235         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2236         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 6 * sizeof(float));
2237         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2238
2239         /* default values? Set up the identity matrix, pass in 2 vertex coords, and enable 4 */
2240         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
2241         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2242         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
2243         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2244         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2245         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2246         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 5 * sizeof(float));
2247         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2248
2249         /* D3DTTFF_COUNT1. Set a NULL matrix, and count1, pass in all values as 1.0 */
2250         memset(mat, 0, sizeof(mat));
2251         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
2252         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2253         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT1);
2254         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2255         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2256         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
2257         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, 6 * sizeof(float));
2258         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2259
2260         hr = IDirect3DDevice9_EndScene(device);
2261         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
2262     }
2263     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2264     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2265
2266     color = getPixelColor(device, 160, 360);
2267     ok(color == 0x00ffffff, "quad 1 has color %08x, expected 0x00ffffff\n", color);
2268     color = getPixelColor(device, 160, 120);
2269     ok(color == 0x00ffff00, "quad 2 has color %08x, expected 0x00ffff00\n", color);
2270     color = getPixelColor(device, 480, 120);
2271     ok(color == 0x000000ff, "quad 3 has color %08x, expected 0x000000ff\n", color);
2272     color = getPixelColor(device, 480, 360);
2273     ok(color == 0x00ffffff, "quad 4 has color %08x, expected 0x00ffffff\n", color);
2274
2275     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff303030, 0.0, 0);
2276     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
2277     hr = IDirect3DDevice9_BeginScene(device);
2278     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed with %s\n", DXGetErrorString9(hr));
2279     if(SUCCEEDED(hr))
2280     {
2281         float quad1[] = {
2282             -1.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2283             -1.0,       0.0,       0.1,     1.0,    1.0,    1.0,
2284              0.0,      -1.0,       0.1,     1.0,    1.0,    1.0,
2285              0.0,       0.0,       0.1,     1.0,    1.0,    1.0
2286         };
2287         float quad2[] = {
2288             -1.0,       0.0,       0.1,
2289             -1.0,       1.0,       0.1,
2290              0.0,       0.0,       0.1,
2291              0.0,       1.0,       0.1,
2292         };
2293         float quad3[] = {
2294              0.0,       0.0,       0.1,     1.0,
2295              0.0,       1.0,       0.1,     1.0,
2296              1.0,       0.0,       0.1,     1.0,
2297              1.0,       1.0,       0.1,     1.0
2298         };
2299         float mat[16] =  {0.0, 0.0, 0.0, 0.0,
2300                            0.0, 0.0, 0.0, 0.0,
2301                            0.0, 0.0, 0.0, 0.0,
2302                            0.0, 1.0, 0.0, 0.0};
2303         float mat2[16] = {0.0, 0.0, 0.0, 1.0,
2304                            1.0, 0.0, 0.0, 0.0,
2305                            0.0, 1.0, 0.0, 0.0,
2306                            0.0, 0.0, 1.0, 0.0};
2307         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl);
2308         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
2309
2310         /* Default values? 4 coords used, 3 passed. What happens to the 4th?
2311          */
2312         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat);
2313         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2314         IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT4);
2315         ok(hr == D3D_OK, "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2316         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, 6 * sizeof(float));
2317         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2318
2319         /* None passed */
2320         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) identity);
2321         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2322         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
2323         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %s\n", DXGetErrorString9(hr));
2324         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 3 * sizeof(float));
2325         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2326
2327         /* 4 used, 1 passed */
2328         hr = IDirect3DDevice9_SetVertexDeclaration(device, decl2);
2329         ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
2330         hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) mat2);
2331         ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2332         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, 4 * sizeof(float));
2333         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2334
2335         hr = IDirect3DDevice9_EndScene(device);
2336         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene failed with %s\n", DXGetErrorString9(hr));
2337     }
2338     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2339     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2340     color = getPixelColor(device, 160, 360);
2341     ok(color == 0x0000ff00, "quad 1 has color %08x, expected 0x0000ff00\n", color);
2342     color = getPixelColor(device, 160, 120);
2343     ok(color == 0x00000000, "quad 2 has color %08x, expected 0x00000000\n", color);
2344     color = getPixelColor(device, 480, 120);
2345     ok(color == 0x00ff0000, "quad 3 has color %08x, expected 0x00ff0000\n", color);
2346     /* Quad4: unused */
2347
2348     IDirect3DVolumeTexture9_Release(volume);
2349
2350     out:
2351     hr = IDirect3DDevice9_SetVertexDeclaration(device, NULL);
2352     ok(hr == D3D_OK, "IDirect3DDevice9_SetVertexDeclaration failed with %s\n", DXGetErrorString9(hr));
2353     IDirect3DDevice9_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
2354     ok(SUCCEEDED(hr), "IDirect3DDevice9_SetTextureStageState failed (%08x)\n", hr);
2355     hr = IDirect3DDevice9_SetTransform(device, D3DTS_TEXTURE0, (D3DMATRIX *) &identity);
2356     ok(hr == D3D_OK, "IDirect3DDevice9_SetTransform failed with %s\n", DXGetErrorString9(hr));
2357     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
2358     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
2359     IDirect3DVertexDeclaration9_Release(decl);
2360     IDirect3DVertexDeclaration9_Release(decl2);
2361 }
2362
2363 static void texdepth_test(IDirect3DDevice9 *device)
2364 {
2365     IDirect3DPixelShader9 *shader;
2366     HRESULT hr;
2367     const float texdepth_test_data1[] = { 0.25,  2.0, 0.0, 0.0};
2368     const float texdepth_test_data2[] = { 0.25,  0.5, 0.0, 0.0};
2369     const float texdepth_test_data3[] = {-1.00,  0.1, 0.0, 0.0};
2370     const float texdepth_test_data4[] = {-0.25, -0.5, 0.0, 0.0};
2371     const float texdepth_test_data5[] = { 1.00, -0.1, 0.0, 0.0};
2372     const float texdepth_test_data6[] = { 1.00,  0.5, 0.0, 0.0};
2373     const float texdepth_test_data7[] = { 0.50,  0.0, 0.0, 0.0};
2374     DWORD shader_code[] = {
2375         0xffff0104,                                                                 /* ps_1_4               */
2376         0x00000051, 0xa00f0001, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000,     /* def c1, 0, 0, 1, 1   */
2377         0x00000001, 0x800f0005, 0xa0e40000,                                         /* mov r5, c0           */
2378         0x0000fffd,                                                                 /* phase                */
2379         0x00000057, 0x800f0005,                                                     /* texdepth r5          */
2380         0x00000001, 0x800f0000, 0xa0e40001,                                         /* mov r0, c1           */
2381         0x0000ffff                                                                  /* end                  */
2382     };
2383     DWORD color;
2384     float vertex[] = {
2385        -1.0,   -1.0,    0.0,
2386         1.0,   -1.0,    1.0,
2387        -1.0,    1.0,    0.0,
2388         1.0,    1.0,    1.0
2389     };
2390
2391     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
2392     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
2393
2394     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffff00, 0.0, 0);
2395     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
2396     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
2397     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2398     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
2399     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2400     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
2401     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2402     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ);
2403
2404     /* Fill the depth buffer with a gradient */
2405     hr = IDirect3DDevice9_BeginScene(device);
2406     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2407     if(SUCCEEDED(hr))
2408     {
2409         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2410         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2411         hr = IDirect3DDevice9_EndScene(device);
2412         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2413     }
2414
2415     /* Now perform the actual tests. Same geometry, but with the shader */
2416     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
2417     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2418     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
2419     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2420     hr = IDirect3DDevice9_SetPixelShader(device, shader);
2421     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
2422
2423     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data1, 1);
2424     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
2425     hr = IDirect3DDevice9_BeginScene(device);
2426     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2427     if(SUCCEEDED(hr))
2428     {
2429         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2430         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2431
2432         hr = IDirect3DDevice9_EndScene(device);
2433         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2434     }
2435
2436     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2437     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2438     color = getPixelColor(device, 158, 240);
2439     ok(color == 0x000000ff, "Pixel 158(25%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
2440     color = getPixelColor(device, 162, 240);
2441     ok(color == 0x00ffffff, "Pixel 158(25%% + 2 pixel) has color %08x, expected 0x00ffffff\n", color);
2442
2443     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
2444
2445     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data2, 1);
2446     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
2447     hr = IDirect3DDevice9_BeginScene(device);
2448     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2449     if(SUCCEEDED(hr))
2450     {
2451         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2452         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2453
2454         hr = IDirect3DDevice9_EndScene(device);
2455         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2456     }
2457
2458     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2459     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2460     color = getPixelColor(device, 318, 240);
2461     ok(color == 0x000000ff, "Pixel 318(50%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
2462     color = getPixelColor(device, 322, 240);
2463     ok(color == 0x00ffff00, "Pixel 322(50%% + 2 pixel) has color %08x, expected 0x00ffff00\n", color);
2464
2465     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
2466
2467     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data3, 1);
2468     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
2469     hr = IDirect3DDevice9_BeginScene(device);
2470     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2471     if(SUCCEEDED(hr))
2472     {
2473         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2474         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2475
2476         hr = IDirect3DDevice9_EndScene(device);
2477         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2478     }
2479     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2480     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2481
2482     color = getPixelColor(device, 1, 240);
2483     ok(color == 0x00ff0000, "Pixel 1(0%% + 2 pixel) has color %08x, expected 0x00ff0000\n", color);
2484
2485     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
2486
2487     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data4, 1);
2488     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
2489     hr = IDirect3DDevice9_BeginScene(device);
2490     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2491     if(SUCCEEDED(hr))
2492     {
2493         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2494         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2495
2496         hr = IDirect3DDevice9_EndScene(device);
2497         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2498     }
2499     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2500     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2501     color = getPixelColor(device, 318, 240);
2502     ok(color == 0x000000ff, "Pixel 318(50%% - 2 pixel) has color %08x, expected 0x000000ff\n", color);
2503     color = getPixelColor(device, 322, 240);
2504     ok(color == 0x0000ff00, "Pixel 322(50%% + 2 pixel) has color %08x, expected 0x0000ff00\n", color);
2505
2506     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
2507
2508     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data5, 1);
2509     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
2510     hr = IDirect3DDevice9_BeginScene(device);
2511     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2512     if(SUCCEEDED(hr))
2513     {
2514         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2515         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2516
2517         hr = IDirect3DDevice9_EndScene(device);
2518         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2519     }
2520     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2521     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2522
2523     color = getPixelColor(device, 1, 240);
2524     ok(color == 0x00ffff00, "Pixel 1(0%% + 2 pixel) has color %08x, expected 0x00ffff00\n", color);
2525
2526     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
2527
2528     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data6, 1);
2529     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
2530     hr = IDirect3DDevice9_BeginScene(device);
2531     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2532     if(SUCCEEDED(hr))
2533     {
2534         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2535         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2536
2537         hr = IDirect3DDevice9_EndScene(device);
2538         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2539     }
2540     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2541     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2542
2543     color = getPixelColor(device, 638, 240);
2544     ok(color == 0x000000ff, "Pixel 638(100%% + 2 pixel) has color %08x, expected 0x000000ff\n", color);
2545
2546     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
2547
2548     hr = IDirect3DDevice9_SetPixelShaderConstantF(device, 0, texdepth_test_data7, 1);
2549     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShaderConstantF returned %s\n", DXGetErrorString9(hr));
2550     hr = IDirect3DDevice9_BeginScene(device);
2551     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2552     if(SUCCEEDED(hr))
2553     {
2554         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 3 * sizeof(float));
2555         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2556
2557         hr = IDirect3DDevice9_EndScene(device);
2558         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2559     }
2560     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2561     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2562
2563     color = getPixelColor(device, 638, 240);
2564     ok(color == 0x000000ff, "Pixel 638(100%% + 2 pixel) has color %08x, expected 0x000000ff\n", color);
2565
2566     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
2567     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
2568     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
2569     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2570     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
2571     ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %s\n", DXGetErrorString9(hr));
2572 }
2573
2574 static void texkill_test(IDirect3DDevice9 *device)
2575 {
2576     IDirect3DPixelShader9 *shader;
2577     HRESULT hr;
2578     DWORD color;
2579
2580     const float vertex[] = {
2581     /*                          bottom  top    right    left */
2582         -1.0,   -1.0,   1.0,   -0.1,    0.9,    0.9,   -0.1,
2583          1.0,   -1.0,   0.0,    0.9,   -0.1,    0.9,   -0.1,
2584         -1.0,    1.0,   1.0,   -0.1,    0.9,   -0.1,    0.9,
2585          1.0,    1.0,   0.0,    0.9,   -0.1,   -0.1,    0.9,
2586     };
2587
2588     DWORD shader_code_11[] = {
2589     0xffff0101,                                                             /* ps_1_1                     */
2590     0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x3f800000, /* def c0, 1.0, 0.0, 0.0, 1.0 */
2591     0x00000041, 0xb00f0000,                                                 /* texkill t0                 */
2592     0x00000001, 0x800f0000, 0xa0e40000,                                     /* mov r0, c0                 */
2593     0x0000ffff                                                              /* end                        */
2594     };
2595     DWORD shader_code_20[] = {
2596     0xffff0200,                                                             /* ps_2_0                     */
2597     0x0200001f, 0x80000000, 0xb00f0000,                                     /* dcl t0                     */
2598     0x05000051, 0xa00f0000, 0x00000000, 0x00000000, 0x3f800000, 0x3f800000, /* def c0, 0.0, 0.0, 1.0, 1.0 */
2599     0x01000041, 0xb00f0000,                                                 /* texkill t0                 */
2600     0x02000001, 0x800f0800, 0xa0e40000,                                     /* mov oC0, c0                */
2601     0x0000ffff                                                              /* end                        */
2602     };
2603
2604     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
2605     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
2606     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_11, &shader);
2607     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
2608
2609     hr = IDirect3DDevice9_SetPixelShader(device, shader);
2610     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
2611     hr = IDirect3DDevice9_BeginScene(device);
2612     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2613     if(SUCCEEDED(hr))
2614     {
2615         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEX1);
2616         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
2617         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 7 * sizeof(float));
2618         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2619         hr = IDirect3DDevice9_EndScene(device);
2620         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2621     }
2622     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2623     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2624     color = getPixelColor(device, 63, 46);
2625     ok(color == 0x0000ff00, "Pixel 63/46 has color %08x, expected 0x0000ff00\n", color);
2626     color = getPixelColor(device, 66, 46);
2627     ok(color == 0x0000ff00, "Pixel 66/64 has color %08x, expected 0x0000ff00\n", color);
2628     color = getPixelColor(device, 63, 49);
2629     ok(color == 0x0000ff00, "Pixel 63/49 has color %08x, expected 0x0000ff00\n", color);
2630     color = getPixelColor(device, 66, 49);
2631     ok(color == 0x00ff0000, "Pixel 66/49 has color %08x, expected 0x00ff0000\n", color);
2632
2633     color = getPixelColor(device, 578, 46);
2634     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
2635     color = getPixelColor(device, 575, 46);
2636     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
2637     color = getPixelColor(device, 578, 49);
2638     ok(color == 0x0000ff00, "Pixel 578/49 has color %08x, expected 0x0000ff00\n", color);
2639     color = getPixelColor(device, 575, 49);
2640     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
2641
2642     color = getPixelColor(device, 63, 430);
2643     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
2644     color = getPixelColor(device, 63, 433);
2645     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
2646     color = getPixelColor(device, 66, 433);
2647     ok(color == 0x00ff0000, "Pixel 578/49 has color %08x, expected 0x00ff0000\n", color);
2648     color = getPixelColor(device, 66, 430);
2649     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
2650
2651     color = getPixelColor(device, 578, 430);
2652     ok(color == 0x0000ff00, "Pixel 578/46 has color %08x, expected 0x0000ff00\n", color);
2653     color = getPixelColor(device, 578, 433);
2654     ok(color == 0x0000ff00, "Pixel 575/64 has color %08x, expected 0x0000ff00\n", color);
2655     color = getPixelColor(device, 575, 433);
2656     ok(color == 0x00ff0000, "Pixel 578/49 has color %08x, expected 0x00ff0000\n", color);
2657     color = getPixelColor(device, 575, 430);
2658     ok(color == 0x00ff0000, "Pixel 575/49 has color %08x, expected 0x00ff0000\n", color);
2659
2660     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
2661     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
2662     IDirect3DPixelShader9_Release(shader);
2663
2664     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
2665     ok(hr == D3D_OK, "IDirect3DDevice9_CreatePixelShader returned %s\n", DXGetErrorString9(hr));
2666     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code_20, &shader);
2667     if(FAILED(hr)) {
2668         skip("Failed to create 2.0 test shader, most likely not supported\n");
2669         return;
2670     }
2671
2672     hr = IDirect3DDevice9_SetPixelShader(device, shader);
2673     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader returned %s\n", DXGetErrorString9(hr));
2674     hr = IDirect3DDevice9_BeginScene(device);
2675     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2676     if(SUCCEEDED(hr))
2677     {
2678         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, vertex, 7 * sizeof(float));
2679         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2680         hr = IDirect3DDevice9_EndScene(device);
2681         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2682     }
2683     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2684
2685     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2686     color = getPixelColor(device, 63, 46);
2687     ok(color == 0x00ffff00, "Pixel 63/46 has color %08x, expected 0x00ffff00\n", color);
2688     color = getPixelColor(device, 66, 46);
2689     ok(color == 0x00ffff00, "Pixel 66/64 has color %08x, expected 0x00ffff00\n", color);
2690     color = getPixelColor(device, 63, 49);
2691     ok(color == 0x00ffff00, "Pixel 63/49 has color %08x, expected 0x00ffff00\n", color);
2692     color = getPixelColor(device, 66, 49);
2693     ok(color == 0x000000ff, "Pixel 66/49 has color %08x, expected 0x000000ff\n", color);
2694
2695     color = getPixelColor(device, 578, 46);
2696     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
2697     color = getPixelColor(device, 575, 46);
2698     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
2699     color = getPixelColor(device, 578, 49);
2700     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
2701     color = getPixelColor(device, 575, 49);
2702     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
2703
2704     color = getPixelColor(device, 63, 430);
2705     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
2706     color = getPixelColor(device, 63, 433);
2707     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
2708     color = getPixelColor(device, 66, 433);
2709     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
2710     color = getPixelColor(device, 66, 430);
2711     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
2712
2713     color = getPixelColor(device, 578, 430);
2714     ok(color == 0x00ffff00, "Pixel 578/46 has color %08x, expected 0x00ffff00\n", color);
2715     color = getPixelColor(device, 578, 433);
2716     ok(color == 0x00ffff00, "Pixel 575/64 has color %08x, expected 0x00ffff00\n", color);
2717     color = getPixelColor(device, 575, 433);
2718     ok(color == 0x00ffff00, "Pixel 578/49 has color %08x, expected 0x00ffff00\n", color);
2719     color = getPixelColor(device, 575, 430);
2720     ok(color == 0x000000ff, "Pixel 575/49 has color %08x, expected 0x000000ff\n", color);
2721 }
2722
2723 static void x8l8v8u8_test(IDirect3DDevice9 *device)
2724 {
2725     IDirect3D9 *d3d9;
2726     HRESULT hr;
2727     IDirect3DTexture9 *texture;
2728     IDirect3DPixelShader9 *shader;
2729     IDirect3DPixelShader9 *shader2;
2730     D3DLOCKED_RECT lr;
2731     DWORD color;
2732     DWORD shader_code[] = {
2733         0xffff0101,                             /* ps_1_1       */
2734         0x00000042, 0xb00f0000,                 /* tex t0       */
2735         0x00000001, 0x800f0000, 0xb0e40000,     /* mov r0, t0   */
2736         0x0000ffff                              /* end          */
2737     };
2738     DWORD shader_code2[] = {
2739         0xffff0101,                             /* ps_1_1       */
2740         0x00000042, 0xb00f0000,                 /* tex t0       */
2741         0x00000001, 0x800f0000, 0xb0ff0000,     /* mov r0, t0.w */
2742         0x0000ffff                              /* end          */
2743     };
2744
2745     float quad[] = {
2746        -1.0,   -1.0,   0.1,     0.5,    0.5,
2747         1.0,   -1.0,   0.1,     0.5,    0.5,
2748        -1.0,    1.0,   0.1,     0.5,    0.5,
2749         1.0,    1.0,   0.1,     0.5,    0.5,
2750     };
2751
2752     memset(&lr, 0, sizeof(lr));
2753     IDirect3DDevice9_GetDirect3D(device, &d3d9);
2754     hr = IDirect3D9_CheckDeviceFormat(d3d9, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
2755                                       0,  D3DRTYPE_TEXTURE, D3DFMT_X8L8V8U8);
2756     IDirect3D9_Release(d3d9);
2757     if(FAILED(hr)) {
2758         skip("No D3DFMT_X8L8V8U8 support\n");
2759     };
2760
2761     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
2762     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
2763
2764     hr = IDirect3DDevice9_CreateTexture(device, 1, 1, 1, 0, D3DFMT_X8L8V8U8, D3DPOOL_MANAGED, &texture, NULL);
2765     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture failed (%08x)\n", hr);
2766     hr = IDirect3DTexture9_LockRect(texture, 0, &lr, NULL, 0);
2767     ok(hr == D3D_OK, "IDirect3DTexture9_LockRect failed (%08x)\n", hr);
2768     *((DWORD *) lr.pBits) = 0x11ca3141;
2769     hr = IDirect3DTexture9_UnlockRect(texture, 0);
2770     ok(hr == D3D_OK, "IDirect3DTexture9_UnlockRect failed (%08x)\n", hr);
2771
2772     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code, &shader);
2773     ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr);
2774     hr = IDirect3DDevice9_CreatePixelShader(device, shader_code2, &shader2);
2775     ok(hr == D3D_OK, "IDirect3DDevice9_CreateShader failed (%08x)\n", hr);
2776
2777     hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2778     ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed (%08x)\n", hr);
2779     hr = IDirect3DDevice9_SetPixelShader(device, shader);
2780     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
2781     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
2782     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
2783
2784     hr = IDirect3DDevice9_BeginScene(device);
2785     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
2786     if(SUCCEEDED(hr))
2787     {
2788         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
2789         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2790
2791         hr = IDirect3DDevice9_EndScene(device);
2792         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
2793     }
2794     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2795     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2796     color = getPixelColor(device, 578, 430);
2797     ok(color == 0x008262ca, "D3DFMT_X8L8V8U8 = 0x112131ca returns color %08x, expected 0x008262ca\n", color);
2798
2799     hr = IDirect3DDevice9_SetPixelShader(device, shader2);
2800     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
2801     hr = IDirect3DDevice9_BeginScene(device);
2802     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
2803     if(SUCCEEDED(hr))
2804     {
2805         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
2806         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2807
2808         hr = IDirect3DDevice9_EndScene(device);
2809         ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene failed (%08x)\n", hr);
2810     }
2811     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2812     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2813     color = getPixelColor(device, 578, 430);
2814     ok(color == 0x00ffffff, "w component of D3DFMT_X8L8V8U8 = 0x11ca3141 returns color %08x\n", color);
2815
2816     hr = IDirect3DDevice9_SetPixelShader(device, NULL);
2817     ok(hr == D3D_OK, "IDirect3DDevice9_SetPixelShader failed (%08x)\n", hr);
2818     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
2819     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture failed (%08x)\n", hr);
2820     IDirect3DPixelShader9_Release(shader);
2821     IDirect3DPixelShader9_Release(shader2);
2822     IDirect3DTexture9_Release(texture);
2823 }
2824
2825 static void autogen_mipmap_test(IDirect3DDevice9 *device)
2826 {
2827     HRESULT hr;
2828     IDirect3D9 *d3d;
2829     IDirect3DTexture9 *texture = NULL;
2830     IDirect3DSurface9 *surface;
2831     DWORD color;
2832     const RECT r1 = {256, 256, 512, 512};
2833     const RECT r2 = {512, 256, 768, 512};
2834     const RECT r3 = {256, 512, 512, 768};
2835     const RECT r4 = {512, 512, 768, 768};
2836     unsigned int x, y;
2837     D3DLOCKED_RECT lr;
2838     memset(&lr, 0, sizeof(lr));
2839
2840     IDirect3DDevice9_GetDirect3D(device, &d3d);
2841     if(IDirect3D9_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
2842        D3DUSAGE_AUTOGENMIPMAP,  D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8) != D3D_OK) {
2843         skip("No autogenmipmap support\n");
2844         IDirect3D9_Release(d3d);
2845         return;
2846     }
2847     IDirect3D9_Release(d3d);
2848
2849     hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffff00, 0.0, 0);
2850     ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
2851
2852     /* Make the mipmap big, so that a smaller mipmap is used
2853      */
2854     hr = IDirect3DDevice9_CreateTexture(device, 1024, 1024, 0, D3DUSAGE_AUTOGENMIPMAP,
2855                                         D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, &texture, 0);
2856     ok(hr == D3D_OK, "IDirect3DDevice9_CreateTexture returned %s\n", DXGetErrorString9(hr));
2857
2858     hr = IDirect3DTexture9_GetSurfaceLevel(texture, 0, &surface);
2859     ok(hr == D3D_OK, "IDirect3DTexture9_GetSurfaceLevel returned %s\n", DXGetErrorString9(hr));
2860     hr = IDirect3DSurface9_LockRect(surface, &lr, NULL, 0);
2861     ok(hr == D3D_OK, "IDirect3DSurface9_LockRect returned %s\n", DXGetErrorString9(hr));
2862     for(y = 0; y < 1024; y++) {
2863         for(x = 0; x < 1024; x++) {
2864             DWORD *dst = (DWORD *) (((BYTE *) lr.pBits) + y * lr.Pitch + x * 4);
2865             POINT pt;
2866
2867             pt.x = x;
2868             pt.y = y;
2869             if(PtInRect(&r1, pt)) {
2870                 *dst = 0xffff0000;
2871             } else if(PtInRect(&r2, pt)) {
2872                 *dst = 0xff00ff00;
2873             } else if(PtInRect(&r3, pt)) {
2874                 *dst = 0xff0000ff;
2875             } else if(PtInRect(&r4, pt)) {
2876                 *dst = 0xff000000;
2877             } else {
2878                 *dst = 0xffffffff;
2879             }
2880         }
2881     }
2882     hr = IDirect3DSurface9_UnlockRect(surface);
2883     ok(hr == D3D_OK, "IDirect3DSurface9_UnlockRect returned %s\n", DXGetErrorString9(hr));
2884     IDirect3DSurface9_Release(surface);
2885
2886     hr = IDirect3DDevice9_SetTexture(device, 0, (IDirect3DBaseTexture9 *) texture);
2887     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
2888     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_POINT);
2889     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
2890
2891     hr = IDirect3DDevice9_BeginScene(device);
2892     ok(hr == D3D_OK, "IDirect3DDevice9_BeginScene returned %s\n", DXGetErrorString9(hr));
2893     if(SUCCEEDED(hr)) {
2894         const float quad[] =  {
2895            -0.5,   -0.5,    0.1,    0.0,    0.0,
2896            -0.5,    0.5,    0.1,    0.0,    1.0,
2897             0.5,   -0.5,    0.1,    1.0,    0.0,
2898             0.5,    0.5,    0.1,    1.0,    1.0
2899         };
2900
2901         hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_TEX1);
2902         ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF returned %s\n", DXGetErrorString9(hr));
2903         hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
2904         ok(hr == D3D_OK, "DrawPrimitiveUP failed (%08x)\n", hr);
2905         hr = IDirect3DDevice9_EndScene(device);
2906         ok(hr == D3D_OK, "IDirect3DDevice9_EndScene returned %s\n", DXGetErrorString9(hr));
2907     }
2908     hr = IDirect3DDevice9_SetTexture(device, 0, NULL);
2909     ok(hr == D3D_OK, "IDirect3DDevice9_SetTexture returned %s\n", DXGetErrorString9(hr));
2910     hr = IDirect3DDevice9_SetSamplerState(device, 0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
2911     ok(hr == D3D_OK, "IDirect3DDevice9_SetSamplerState failed with %s\n", DXGetErrorString9(hr));
2912     IDirect3DTexture9_Release(texture);
2913
2914     hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
2915     ok(hr == D3D_OK, "IDirect3DDevice9_Present failed with %s\n", DXGetErrorString9(hr));
2916     color = getPixelColor(device, 200, 200);
2917     ok(color == 0x00ffffff, "pixel 200/200 has color %08x, expected 0x00ffffff\n", color);
2918     color = getPixelColor(device, 280, 200);
2919     ok(color == 0x000000ff, "pixel 280/200 has color %08x, expected 0x000000ff\n", color);
2920     color = getPixelColor(device, 360, 200);
2921     ok(color == 0x00000000, "pixel 360/200 has color %08x, expected 0x00000000\n", color);
2922     color = getPixelColor(device, 440, 200);
2923     ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
2924     color = getPixelColor(device, 200, 270);
2925     ok(color == 0x00ffffff, "pixel 200/270 has color %08x, expected 0x00ffffff\n", color);
2926     color = getPixelColor(device, 280, 270);
2927     ok(color == 0x00ff0000, "pixel 280/270 has color %08x, expected 0x00ff0000\n", color);
2928     color = getPixelColor(device, 360, 270);
2929     ok(color == 0x0000ff00, "pixel 360/270 has color %08x, expected 0x0000ff00\n", color);
2930     color = getPixelColor(device, 440, 270);
2931     ok(color == 0x00ffffff, "pixel 440/200 has color %08x, expected 0x00ffffff\n", color);
2932 }
2933
2934 START_TEST(visual)
2935 {
2936     IDirect3DDevice9 *device_ptr;
2937     D3DCAPS9 caps;
2938     HRESULT hr;
2939     DWORD color;
2940
2941     d3d9_handle = LoadLibraryA("d3d9.dll");
2942     if (!d3d9_handle)
2943     {
2944         skip("Could not load d3d9.dll\n");
2945         return;
2946     }
2947
2948     device_ptr = init_d3d9();
2949     if (!device_ptr)
2950     {
2951         skip("Creating the device failed\n");
2952         return;
2953     }
2954
2955     IDirect3DDevice9_GetDeviceCaps(device_ptr, &caps);
2956
2957     /* Check for the reliability of the returned data */
2958     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
2959     if(FAILED(hr))
2960     {
2961         trace("Clear failed, can't assure correctness of the test results, skipping\n");
2962         goto cleanup;
2963     }
2964     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
2965
2966     color = getPixelColor(device_ptr, 1, 1);
2967     if(color !=0x00ff0000)
2968     {
2969         trace("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
2970         goto cleanup;
2971     }
2972
2973     hr = IDirect3DDevice9_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xff00ddee, 0.0, 0);
2974     if(FAILED(hr))
2975     {
2976         trace("Clear failed, can't assure correctness of the test results, skipping\n");
2977         goto cleanup;
2978     }
2979     IDirect3DDevice9_Present(device_ptr, NULL, NULL, NULL, NULL);
2980
2981     color = getPixelColor(device_ptr, 639, 479);
2982     if(color != 0x0000ddee)
2983     {
2984         trace("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
2985         goto cleanup;
2986     }
2987
2988     /* Now execute the real tests */
2989     lighting_test(device_ptr);
2990     clear_test(device_ptr);
2991     fog_test(device_ptr);
2992     if(caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP)
2993     {
2994         test_cube_wrap(device_ptr);
2995     } else {
2996         skip("No cube texture support\n");
2997     }
2998     z_range_test(device_ptr);
2999     if(caps.TextureCaps & D3DPTEXTURECAPS_MIPMAP)
3000     {
3001         maxmip_test(device_ptr);
3002     }
3003     else
3004     {
3005         skip("No mipmap support\n");
3006     }
3007     offscreen_test(device_ptr);
3008     release_buffer_test(device_ptr);
3009     float_texture_test(device_ptr);
3010     texture_transform_flags_test(device_ptr);
3011     autogen_mipmap_test(device_ptr);
3012
3013
3014     if (caps.VertexShaderVersion >= D3DVS_VERSION(2, 0))
3015     {
3016         test_mova(device_ptr);
3017     }
3018     else skip("No vs_2_0 support\n");
3019
3020     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1) && caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
3021     {
3022         fog_with_shader_test(device_ptr);
3023     }
3024     else skip("No vs_1_1 and ps_1_1 support\n");
3025
3026     if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
3027     {
3028         texbem_test(device_ptr);
3029         texdepth_test(device_ptr);
3030         texkill_test(device_ptr);
3031         x8l8v8u8_test(device_ptr);
3032     }
3033     else skip("No ps_1_1 support\n");
3034
3035 cleanup:
3036     if(device_ptr) IDirect3DDevice9_Release(device_ptr);
3037 }