wined3d: Recognize Nvidia GT520 cards.
[wine] / dlls / d3d8 / tests / visual.c
1 /*
2  * Copyright (C) 2005 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 /* See comment in dlls/d3d9/tests/visual.c for general guidelines */
21
22 #define COBJMACROS
23 #include <d3d8.h>
24 #include "wine/test.h"
25
26 static HMODULE d3d8_handle = 0;
27
28 struct vec3
29 {
30     float x, y, z;
31 };
32
33 struct vec4
34 {
35     float x, y, z, w;
36 };
37
38 static HWND create_window(void)
39 {
40     WNDCLASS wc = {0};
41     HWND ret;
42     wc.lpfnWndProc = DefWindowProc;
43     wc.lpszClassName = "d3d8_test_wc";
44     RegisterClass(&wc);
45
46     ret = CreateWindow("d3d8_test_wc", "d3d8_test",
47                        WS_POPUP | WS_SYSMENU , 20, 20, 640, 480, 0, 0, 0, 0);
48     ShowWindow(ret, SW_SHOW);
49     return ret;
50 }
51
52 static BOOL color_match(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
53 {
54     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
55     c1 >>= 8; c2 >>= 8;
56     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
57     c1 >>= 8; c2 >>= 8;
58     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
59     c1 >>= 8; c2 >>= 8;
60     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
61     return TRUE;
62 }
63
64 static DWORD getPixelColor(IDirect3DDevice8 *device, UINT x, UINT y)
65 {
66     DWORD ret;
67     IDirect3DTexture8 *tex = NULL;
68     IDirect3DSurface8 *surf = NULL, *backbuf = NULL;
69     HRESULT hr;
70     D3DLOCKED_RECT lockedRect;
71     RECT rectToLock = {x, y, x+1, y+1};
72
73     hr = IDirect3DDevice8_CreateTexture(device, 640, 480, 1 /* Levels */, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &tex);
74     if(FAILED(hr) || !tex )  /* This is not a test */
75     {
76         trace("Can't create an offscreen plain surface to read the render target data, hr=%#08x\n", hr);
77         return 0xdeadbeef;
78     }
79     hr = IDirect3DTexture8_GetSurfaceLevel(tex, 0, &surf);
80     if(FAILED(hr) || !tex )  /* This is not a test */
81     {
82         trace("Can't get surface from texture, hr=%#08x\n", hr);
83         ret = 0xdeadbeee;
84         goto out;
85     }
86
87     hr = IDirect3DDevice8_GetRenderTarget(device, &backbuf);
88     if(FAILED(hr))
89     {
90         trace("Can't get the render target, hr=%#08x\n", hr);
91         ret = 0xdeadbeed;
92         goto out;
93     }
94     hr = IDirect3DDevice8_CopyRects(device, backbuf, NULL, 0, surf, NULL);
95     if(FAILED(hr))
96     {
97         trace("Can't read the render target, hr=%#08x\n", hr);
98         ret = 0xdeadbeec;
99         goto out;
100     }
101
102     hr = IDirect3DSurface8_LockRect(surf, &lockedRect, &rectToLock, D3DLOCK_READONLY);
103     if(FAILED(hr))
104     {
105         trace("Can't lock the offscreen surface, hr=%#08x\n", hr);
106         ret = 0xdeadbeeb;
107         goto out;
108     }
109     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
110      * really important for these tests
111      */
112     ret = ((DWORD *) lockedRect.pBits)[0] & 0x00ffffff;
113     hr = IDirect3DSurface8_UnlockRect(surf);
114     if(FAILED(hr))
115     {
116         trace("Can't unlock the offscreen surface, hr=%#08x\n", hr);
117     }
118
119 out:
120     if(backbuf) IDirect3DSurface8_Release(backbuf);
121     if(surf) IDirect3DSurface8_Release(surf);
122     if(tex) IDirect3DTexture8_Release(tex);
123     return ret;
124 }
125
126 static IDirect3DDevice8 *init_d3d8(void)
127 {
128     IDirect3D8 * (__stdcall * d3d8_create)(UINT SDKVersion) = 0;
129     IDirect3D8 *d3d8_ptr = 0;
130     IDirect3DDevice8 *device_ptr = 0;
131     D3DPRESENT_PARAMETERS present_parameters;
132     HRESULT hr;
133
134     d3d8_create = (void *)GetProcAddress(d3d8_handle, "Direct3DCreate8");
135     ok(d3d8_create != NULL, "Failed to get address of Direct3DCreate8\n");
136     if (!d3d8_create) return NULL;
137
138     d3d8_ptr = d3d8_create(D3D_SDK_VERSION);
139     if (!d3d8_ptr)
140     {
141         skip("could not create D3D8\n");
142         return NULL;
143     }
144
145     ZeroMemory(&present_parameters, sizeof(present_parameters));
146     present_parameters.Windowed = TRUE;
147     present_parameters.hDeviceWindow = create_window();
148     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
149     present_parameters.BackBufferWidth = 640;
150     present_parameters.BackBufferHeight = 480;
151     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
152     present_parameters.EnableAutoDepthStencil = TRUE;
153     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
154
155     hr = IDirect3D8_CreateDevice(d3d8_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
156             present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
157     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D_CreateDevice returned: %#08x\n", hr);
158
159     return device_ptr;
160 }
161
162 struct vertex
163 {
164     float x, y, z;
165     DWORD diffuse;
166 };
167
168 struct tvertex
169 {
170     float x, y, z, w;
171     DWORD diffuse;
172 };
173
174 struct nvertex
175 {
176     float x, y, z;
177     float nx, ny, nz;
178     DWORD diffuse;
179 };
180
181 static void lighting_test(IDirect3DDevice8 *device)
182 {
183     HRESULT hr;
184     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
185     DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
186     DWORD color;
187
188     float mat[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
189                       0.0f, 1.0f, 0.0f, 0.0f,
190                       0.0f, 0.0f, 1.0f, 0.0f,
191                       0.0f, 0.0f, 0.0f, 1.0f };
192
193     struct vertex unlitquad[] =
194     {
195         {-1.0f, -1.0f,   0.1f,                          0xffff0000},
196         {-1.0f,  0.0f,   0.1f,                          0xffff0000},
197         { 0.0f,  0.0f,   0.1f,                          0xffff0000},
198         { 0.0f, -1.0f,   0.1f,                          0xffff0000},
199     };
200     struct vertex litquad[] =
201     {
202         {-1.0f,  0.0f,   0.1f,                          0xff00ff00},
203         {-1.0f,  1.0f,   0.1f,                          0xff00ff00},
204         { 0.0f,  1.0f,   0.1f,                          0xff00ff00},
205         { 0.0f,  0.0f,   0.1f,                          0xff00ff00},
206     };
207     struct nvertex unlitnquad[] =
208     {
209         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
210         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
211         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
212         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
213     };
214     struct nvertex litnquad[] =
215     {
216         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
217         { 0.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
218         { 1.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
219         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
220     };
221     WORD Indices[] = {0, 1, 2, 2, 3, 0};
222
223     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
224     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %#08x\n", hr);
225
226     /* Setup some states that may cause issues */
227     hr = IDirect3DDevice8_SetTransform(device, D3DTS_WORLDMATRIX(0), (D3DMATRIX *) mat);
228     ok(hr == D3D_OK, "IDirect3DDevice8_SetTransform returned %#08x\n", hr);
229     hr = IDirect3DDevice8_SetTransform(device, D3DTS_VIEW, (D3DMATRIX *)mat);
230     ok(hr == D3D_OK, "IDirect3DDevice8_SetTransform returned %#08x\n", hr);
231     hr = IDirect3DDevice8_SetTransform(device, D3DTS_PROJECTION, (D3DMATRIX *) mat);
232     ok(hr == D3D_OK, "IDirect3DDevice8_SetTransform returned %#08x\n", hr);
233     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPING, FALSE);
234     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
235     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, FALSE);
236     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
237     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
238     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
239     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
240     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
241     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHATESTENABLE, FALSE);
242     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
243     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
244     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
245     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
246     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed with %#08x\n", hr);
247     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
248     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed with %#08x\n", hr);
249
250     hr = IDirect3DDevice8_SetVertexShader(device, fvf);
251     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
252
253     hr = IDirect3DDevice8_BeginScene(device);
254     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
255     if(hr == D3D_OK)
256     {
257         /* No lights are defined... That means, lit vertices should be entirely black */
258         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
259         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
260         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
261                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitquad, sizeof(unlitquad[0]));
262         ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %#08x\n", hr);
263
264         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, TRUE);
265         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
266         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
267                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litquad, sizeof(litquad[0]));
268         ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %#08x\n", hr);
269
270         hr = IDirect3DDevice8_SetVertexShader(device, nfvf);
271         ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader failed with %#08x\n", hr);
272
273         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
274         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
275         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
276                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitnquad, sizeof(unlitnquad[0]));
277         ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %#08x\n", hr);
278
279         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, TRUE);
280         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
281         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
282                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litnquad, sizeof(litnquad[0]));
283         ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %#08x\n", hr);
284
285         hr = IDirect3DDevice8_EndScene(device);
286         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
287     }
288
289     color = getPixelColor(device, 160, 360); /* Lower left quad - unlit without normals */
290     ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x, expected 0x00ff0000.\n", color);
291     color = getPixelColor(device, 160, 120); /* Upper left quad - lit without normals */
292     ok(color == 0x00000000, "Lit quad without normals has color 0x%08x, expected 0x00000000.\n", color);
293     color = getPixelColor(device, 480, 360); /* Lower right quad - unlit with normals */
294     ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x, expected 0x000000ff.\n", color);
295     color = getPixelColor(device, 480, 120); /* Upper right quad - lit with normals */
296     ok(color == 0x00000000, "Lit quad with normals has color 0x%08x, expected 0x00000000.\n", color);
297
298     IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
299
300     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
301     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
302 }
303
304 static void clear_test(IDirect3DDevice8 *device)
305 {
306     /* Tests the correctness of clearing parameters */
307     HRESULT hr;
308     D3DRECT rect[2];
309     D3DRECT rect_negneg;
310     DWORD color;
311
312     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
313     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %#08x\n", hr);
314
315     /* Positive x, negative y */
316     rect[0].x1 = 0;
317     rect[0].y1 = 480;
318     rect[0].x2 = 320;
319     rect[0].y2 = 240;
320
321     /* Positive x, positive y */
322     rect[1].x1 = 0;
323     rect[1].y1 = 0;
324     rect[1].x2 = 320;
325     rect[1].y2 = 240;
326     /* Clear 2 rectangles with one call. Shows that a positive value is returned, but the negative rectangle
327      * is ignored, the positive is still cleared afterwards
328      */
329     hr = IDirect3DDevice8_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
330     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %#08x\n", hr);
331
332     /* negative x, negative y */
333     rect_negneg.x1 = 640;
334     rect_negneg.y1 = 240;
335     rect_negneg.x2 = 320;
336     rect_negneg.y2 = 0;
337     hr = IDirect3DDevice8_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
338     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %#08x\n", hr);
339
340     color = getPixelColor(device, 160, 360); /* lower left quad */
341     ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
342     color = getPixelColor(device, 160, 120); /* upper left quad */
343     ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
344     color = getPixelColor(device, 480, 360); /* lower right quad  */
345     ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
346     color = getPixelColor(device, 480, 120); /* upper right quad */
347     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
348
349     IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
350 }
351
352 struct sVertex {
353     float x, y, z;
354     DWORD diffuse;
355     DWORD specular;
356 };
357
358 struct sVertexT {
359     float x, y, z, rhw;
360     DWORD diffuse;
361     DWORD specular;
362 };
363
364 static void fog_test(IDirect3DDevice8 *device)
365 {
366     HRESULT hr;
367     DWORD color;
368     float start = 0.0, end = 1.0;
369
370     /* Gets full z based fog with linear fog, no fog with specular color */
371     struct sVertex untransformed_1[] = {
372         {-1,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
373         {-1,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
374         { 0,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
375         { 0,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
376     };
377     /* Ok, I am too lazy to deal with transform matrices */
378     struct sVertex untransformed_2[] = {
379         {-1,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
380         {-1,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
381         { 0,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
382         { 0,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
383     };
384     /* Untransformed ones. Give them a different diffuse color to make the test look
385      * nicer. It also makes making sure that they are drawn correctly easier.
386      */
387     struct sVertexT transformed_1[] = {
388         {320,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
389         {640,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
390         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
391         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
392     };
393     struct sVertexT transformed_2[] = {
394         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
395         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
396         {640,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
397         {320,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
398     };
399     WORD Indices[] = {0, 1, 2, 2, 3, 0};
400
401     D3DCAPS8 caps;
402     float ident_mat[16] =
403     {
404         1.0f, 0.0f, 0.0f, 0.0f,
405         0.0f, 1.0f, 0.0f, 0.0f,
406         0.0f, 0.0f, 1.0f, 0.0f,
407         0.0f, 0.0f, 0.0f, 1.0f
408     };
409     float world_mat1[16] =
410     {
411         1.0f, 0.0f,  0.0f, 0.0f,
412         0.0f, 1.0f,  0.0f, 0.0f,
413         0.0f, 0.0f,  1.0f, 0.0f,
414         0.0f, 0.0f, -0.5f, 1.0f
415     };
416     float world_mat2[16] =
417     {
418         1.0f, 0.0f, 0.0f, 0.0f,
419         0.0f, 1.0f, 0.0f, 0.0f,
420         0.0f, 0.0f, 1.0f, 0.0f,
421         0.0f, 0.0f, 1.0f, 1.0f
422     };
423     float proj_mat[16] =
424     {
425         1.0f, 0.0f,  0.0f, 0.0f,
426         0.0f, 1.0f,  0.0f, 0.0f,
427         0.0f, 0.0f,  1.0f, 0.0f,
428         0.0f, 0.0f, -1.0f, 1.0f
429     };
430
431     struct sVertex far_quad1[] =
432     {
433         {-1.0f, -1.0f, 0.5f, 0xffff0000, 0xff000000},
434         {-1.0f,  0.0f, 0.5f, 0xffff0000, 0xff000000},
435         { 0.0f,  0.0f, 0.5f, 0xffff0000, 0xff000000},
436         { 0.0f, -1.0f, 0.5f, 0xffff0000, 0xff000000},
437     };
438     struct sVertex far_quad2[] =
439     {
440         {-1.0f, 0.0f, 1.5f, 0xffff0000, 0xff000000},
441         {-1.0f, 1.0f, 1.5f, 0xffff0000, 0xff000000},
442         { 0.0f, 1.0f, 1.5f, 0xffff0000, 0xff000000},
443         { 0.0f, 0.0f, 1.5f, 0xffff0000, 0xff000000},
444     };
445
446     memset(&caps, 0, sizeof(caps));
447     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
448     ok(hr == D3D_OK, "IDirect3DDevice8_GetDeviceCaps returned %08x\n", hr);
449
450     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
451     ok(hr == D3D_OK, "IDirect3DDevice8_Clear returned %#08x\n", hr);
452
453     /* Setup initial states: No lighting, fog on, fog color */
454     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
455     ok(hr == D3D_OK, "Turning off lighting returned %#08x\n", hr);
456     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
457     ok(hr == D3D_OK, "Turning on fog calculations returned %#08x\n", hr);
458     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
459     ok(hr == D3D_OK, "Setting fog color returned %#08x\n", hr);
460
461     /* First test: Both table fog and vertex fog off */
462     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
463     ok(hr == D3D_OK, "Turning off table fog returned %#08x\n", hr);
464     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
465     ok(hr == D3D_OK, "Turning off vertex fog returned %#08x\n", hr);
466
467     /* Start = 0, end = 1. Should be default, but set them */
468     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
469     ok(hr == D3D_OK, "Setting fog start returned %#08x\n", hr);
470     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
471     ok(hr == D3D_OK, "Setting fog start returned %#08x\n", hr);
472
473     if(IDirect3DDevice8_BeginScene(device) == D3D_OK)
474     {
475         hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
476         ok( hr == D3D_OK, "SetVertexShader returned %#08x\n", hr);
477         /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
478         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
479                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, untransformed_1,
480                                                      sizeof(untransformed_1[0]));
481         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
482
483         /* That makes it use the Z value */
484         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
485         ok(hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR returned %#08x\n", hr);
486         /* Untransformed, vertex fog != none (or table fog != none):
487          * Use the Z value as input into the equation
488          */
489         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
490                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, untransformed_2,
491                                                      sizeof(untransformed_2[0]));
492         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
493
494         /* transformed verts */
495         hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
496         ok( hr == D3D_OK, "SetVertexShader returned %#08x\n", hr);
497         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
498         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
499                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
500                                                      sizeof(transformed_1[0]));
501         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
502
503         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
504         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %#08x\n", hr);
505         /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
506          * equation
507          */
508         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
509                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_2,
510                                                      sizeof(transformed_2[0]));
511         ok(SUCCEEDED(hr), "IDirect3DDevice8_DrawIndexedPrimitiveUP returned %#x.\n", hr);
512
513         hr = IDirect3DDevice8_EndScene(device);
514         ok(hr == D3D_OK, "EndScene returned %#08x\n", hr);
515     }
516     else
517     {
518         ok(FALSE, "BeginScene failed\n");
519     }
520
521     color = getPixelColor(device, 160, 360);
522     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xFF, 0x00, 0x00), 1),
523             "Untransformed vertex with no table or vertex fog has color %08x\n", color);
524     color = getPixelColor(device, 160, 120);
525     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xFF, 0x00), 1),
526             "Untransformed vertex with linear vertex fog has color %08x\n", color);
527     color = getPixelColor(device, 480, 120);
528     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xFF, 0xFF, 0x00), 1),
529             "Transformed vertex with linear vertex fog has color %08x\n", color);
530     color = getPixelColor(device, 480, 360);
531     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xFF, 0x00), 1),
532             "Transformed vertex with linear table fog has color %08x\n", color);
533
534     IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
535
536     if (caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE)
537     {
538         /* A simple fog + non-identity world matrix test */
539         hr = IDirect3DDevice8_SetTransform(device, D3DTS_WORLDMATRIX(0), (D3DMATRIX *) world_mat1);
540         ok(hr == D3D_OK, "IDirect3DDevice8_SetTransform returned %#08x\n", hr);
541
542         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
543         ok(hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %#08x\n", hr);
544         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
545         ok(hr == D3D_OK, "Turning off vertex fog returned %#08x\n", hr);
546
547         hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
548         ok(hr == D3D_OK, "IDirect3DDevice8_Clear returned %#08x\n", hr);
549
550         if (IDirect3DDevice8_BeginScene(device) == D3D_OK)
551         {
552             hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
553             ok(hr == D3D_OK, "SetVertexShader returned %#08x\n", hr);
554
555             hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4,
556                     2, Indices, D3DFMT_INDEX16, far_quad1, sizeof(far_quad1[0]));
557             ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
558
559             hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4,
560                     2, Indices, D3DFMT_INDEX16, far_quad2, sizeof(far_quad2[0]));
561             ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
562
563             hr = IDirect3DDevice8_EndScene(device);
564             ok(hr == D3D_OK, "EndScene returned %#08x\n", hr);
565         }
566         else
567         {
568             ok(FALSE, "BeginScene failed\n");
569         }
570
571         color = getPixelColor(device, 160, 360);
572         ok(color_match(color, 0x00ff0000, 4), "Unfogged quad has color %08x\n", color);
573         color = getPixelColor(device, 160, 120);
574         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 1),
575                 "Fogged out quad has color %08x\n", color);
576
577         IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
578
579         /* Test fog behavior with an orthogonal (but not identity) projection matrix */
580         hr = IDirect3DDevice8_SetTransform(device, D3DTS_WORLDMATRIX(0), (D3DMATRIX *) world_mat2);
581         ok(hr == D3D_OK, "SetTransform returned %#08x\n", hr);
582         hr = IDirect3DDevice8_SetTransform(device, D3DTS_PROJECTION, (D3DMATRIX *) proj_mat);
583         ok(hr == D3D_OK, "SetTransform returned %#08x\n", hr);
584
585         hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
586         ok(hr == D3D_OK, "Clear returned %#08x\n", hr);
587
588         if (IDirect3DDevice8_BeginScene(device) == D3D_OK)
589         {
590             hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
591             ok(hr == D3D_OK, "SetVertexShader returned %#08x\n", hr);
592
593             hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4,
594                     2, Indices, D3DFMT_INDEX16, untransformed_1, sizeof(untransformed_1[0]));
595             ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
596
597             hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0, 4,
598                     2, Indices, D3DFMT_INDEX16, untransformed_2, sizeof(untransformed_2[0]));
599             ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
600
601             hr = IDirect3DDevice8_EndScene(device);
602             ok(hr == D3D_OK, "EndScene returned %#08x\n", hr);
603         }
604         else
605         {
606             ok(FALSE, "BeginScene failed\n");
607         }
608
609         color = getPixelColor(device, 160, 360);
610         todo_wine ok(color_match(color, 0x00e51900, 4), "Partially fogged quad has color %08x\n", color);
611         color = getPixelColor(device, 160, 120);
612         ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 1),
613                 "Fogged out quad has color %08x\n", color);
614
615         IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
616
617         hr = IDirect3DDevice8_SetTransform(device, D3DTS_WORLDMATRIX(0), (D3DMATRIX *) ident_mat);
618         ok(hr == D3D_OK, "SetTransform returned %#08x\n", hr);
619         hr = IDirect3DDevice8_SetTransform(device, D3DTS_PROJECTION, (D3DMATRIX *) ident_mat);
620         ok(hr == D3D_OK, "SetTransform returned %#08x\n", hr);
621     }
622     else
623     {
624         skip("D3DPRASTERCAPS_FOGTABLE not supported, skipping some fog tests\n");
625     }
626
627     /* Turn off the fog master switch to avoid confusing other tests */
628     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
629     ok(hr == D3D_OK, "Turning off fog calculations returned %#08x\n", hr);
630 }
631
632 /* This tests fog in combination with shaders.
633  * What's tested: linear fog (vertex and table) with pixel shader
634  *                linear table fog with non foggy vertex shader
635  *                vertex fog with foggy vertex shader, non-linear
636  *                fog with shader, non-linear fog with foggy shader,
637  *                linear table fog with foggy shader */
638 static void fog_with_shader_test(IDirect3DDevice8 *device)
639 {
640     HRESULT hr;
641     DWORD color;
642     union
643     {
644         float f;
645         DWORD i;
646     } start, end;
647     unsigned int i, j;
648
649     /* Basic vertex shader without fog computation ("non foggy") */
650     static const DWORD vertex_shader_code1[] =
651     {
652         0xfffe0100,                                                             /* vs.1.0                       */
653         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                 */
654         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                  */
655         0x0000ffff
656     };
657     /* Basic vertex shader with reversed fog computation ("foggy") */
658     static const DWORD vertex_shader_code2[] =
659     {
660         0xfffe0100,                                                             /* vs.1.0                        */
661         0x00000001, 0xc00f0000, 0x90e40000,                                     /* mov oPos, v0                  */
662         0x00000001, 0xd00f0000, 0x90e40001,                                     /* mov oD0, v1                   */
663         0x00000002, 0x800f0000, 0x90aa0000, 0xa0aa0000,                         /* add r0, v0.z, c0.z            */
664         0x00000005, 0xc00f0001, 0x80000000, 0xa0000000,                         /* mul oFog, r0.x, c0.x          */
665         0x0000ffff
666     };
667     /* Basic pixel shader */
668     static const DWORD pixel_shader_code[] =
669     {
670         0xffff0101,                                                             /* ps_1_1     */
671         0x00000001, 0x800f0000, 0x90e40000,                                     /* mov r0, v0 */
672         0x0000ffff
673     };
674     static struct vertex quad[] =
675     {
676         {-1.0f, -1.0f,  0.0f, 0xffff0000},
677         {-1.0f,  1.0f,  0.0f, 0xffff0000},
678         { 1.0f, -1.0f,  0.0f, 0xffff0000},
679         { 1.0f,  1.0f,  0.0f, 0xffff0000},
680     };
681     static const DWORD decl[] =
682     {
683         D3DVSD_STREAM(0),
684         D3DVSD_REG(0, D3DVSDT_FLOAT3),  /* position, v0 */
685         D3DVSD_REG(1, D3DVSDT_D3DCOLOR),  /* diffuse color, v1 */
686         D3DVSD_END()
687     };
688     static const float vs_constant[4] = {-1.25f, 0.0f, -0.9f, 0.0f};
689     /* Fill the null-shader entry with the FVF (SetVertexShader is "overloaded" on d3d8...) */
690     DWORD vertex_shader[3] = {D3DFVF_XYZ | D3DFVF_DIFFUSE, 0, 0};
691     DWORD pixel_shader[2] = {0, 0};
692
693     /* This reference data was collected on a nVidia GeForce 7600GS
694      * driver version 84.19 DirectX version 9.0c on Windows XP */
695     static const struct test_data_t
696     {
697         int vshader;
698         int pshader;
699         D3DFOGMODE vfog;
700         D3DFOGMODE tfog;
701         unsigned int color[11];
702     }
703     test_data[] =
704     {
705         /* Only pixel shader */
706         {0, 1, D3DFOG_NONE, D3DFOG_LINEAR,
707         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
708         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
709         {0, 1, D3DFOG_EXP, D3DFOG_LINEAR,
710         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
711         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
712         {0, 1, D3DFOG_EXP2, D3DFOG_LINEAR,
713         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
714         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
715         {0, 1, D3DFOG_LINEAR, D3DFOG_NONE,
716         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
717         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
718         {0, 1, D3DFOG_LINEAR, D3DFOG_LINEAR,
719         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
720         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
721
722         /* Vertex shader */
723         {1, 0, D3DFOG_NONE, D3DFOG_NONE,
724         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
725          0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
726         {1, 0, D3DFOG_NONE, D3DFOG_LINEAR,
727         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
728         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
729         {1, 0, D3DFOG_EXP, D3DFOG_LINEAR,
730         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
731         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
732
733         {1, 0, D3DFOG_EXP2, D3DFOG_LINEAR,
734         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
735         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
736         {1, 0, D3DFOG_LINEAR, D3DFOG_LINEAR,
737         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
738         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
739
740         /* Vertex shader and pixel shader */
741         /* The next 4 tests would read the fog coord output, but it isn't available.
742          * The result is a fully fogged quad, no matter what the Z coord is. */
743         {1, 1, D3DFOG_NONE, D3DFOG_NONE,
744         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
745         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
746         {1, 1, D3DFOG_LINEAR, D3DFOG_NONE,
747         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
748         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
749         {1, 1, D3DFOG_EXP, D3DFOG_NONE,
750         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
751         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
752         {1, 1, D3DFOG_EXP2, D3DFOG_NONE,
753         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00,
754         0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00, 0x0000ff00}},
755
756         /* These use the Z coordinate with linear table fog */
757         {1, 1, D3DFOG_NONE, D3DFOG_LINEAR,
758         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
759         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
760         {1, 1, D3DFOG_EXP, D3DFOG_LINEAR,
761         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
762         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
763         {1, 1, D3DFOG_EXP2, D3DFOG_LINEAR,
764         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
765         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
766         {1, 1, D3DFOG_LINEAR, D3DFOG_LINEAR,
767         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
768         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
769
770         /* Non-linear table fog without fog coord */
771         {1, 1, D3DFOG_NONE, D3DFOG_EXP,
772         {0x00ff0000, 0x00e71800, 0x00d12e00, 0x00bd4200, 0x00ab5400, 0x009b6400,
773         0x008d7200, 0x007f8000, 0x00738c00, 0x00689700, 0x005ea100}},
774         {1, 1, D3DFOG_NONE, D3DFOG_EXP2,
775         {0x00fd0200, 0x00f50200, 0x00f50a00, 0x00e91600, 0x00d92600, 0x00c73800,
776         0x00b24d00, 0x009c6300, 0x00867900, 0x00728d00, 0x005ea100}},
777
778         /* These tests fail on older Nvidia drivers */
779         /* Foggy vertex shader */
780         {2, 0, D3DFOG_NONE, D3DFOG_NONE,
781         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
782         0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
783         {2, 0, D3DFOG_EXP, D3DFOG_NONE,
784         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
785         0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
786         {2, 0, D3DFOG_EXP2, D3DFOG_NONE,
787         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
788         0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
789         {2, 0, D3DFOG_LINEAR, D3DFOG_NONE,
790         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
791         0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
792
793         /* Foggy vertex shader and pixel shader. First 4 tests with vertex fog,
794          * all using the fixed fog-coord linear fog */
795         {2, 1, D3DFOG_NONE, D3DFOG_NONE,
796         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
797         0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
798         {2, 1, D3DFOG_EXP, D3DFOG_NONE,
799         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
800         0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
801         {2, 1, D3DFOG_EXP2, D3DFOG_NONE,
802         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
803         0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
804         {2, 1, D3DFOG_LINEAR, D3DFOG_NONE,
805         {0x00ff0000, 0x00fe0100, 0x00de2100, 0x00bf4000, 0x009f6000, 0x007f8000,
806         0x005fa000, 0x003fc000, 0x001fe000, 0x0000ff00, 0x0000ff00}},
807
808         /* These use table fog. Here the shader-provided fog coordinate is
809          * ignored and the z coordinate used instead */
810         {2, 1, D3DFOG_NONE, D3DFOG_EXP,
811         {0x00ff0000, 0x00e71800, 0x00d12e00, 0x00bd4200, 0x00ab5400, 0x009b6400,
812         0x008d7200, 0x007f8000, 0x00738c00, 0x00689700, 0x005ea100}},
813         {2, 1, D3DFOG_NONE, D3DFOG_EXP2,
814         {0x00fd0200, 0x00f50200, 0x00f50a00, 0x00e91600, 0x00d92600, 0x00c73800,
815         0x00b24d00, 0x009c6300, 0x00867900, 0x00728d00, 0x005ea100}},
816         {2, 1, D3DFOG_NONE, D3DFOG_LINEAR,
817         {0x00ff0000, 0x00ff0000, 0x00df2000, 0x00bf4000, 0x009f6000, 0x007f8000,
818         0x005fa000, 0x0040bf00, 0x0020df00, 0x0000ff00, 0x0000ff00}},
819     };
820
821     /* NOTE: changing these values will not affect the tests with foggy vertex shader,
822      * as the values are hardcoded in the shader constant */
823     start.f = 0.1f;
824     end.f = 0.9f;
825
826     hr = IDirect3DDevice8_CreateVertexShader(device, decl, vertex_shader_code1, &vertex_shader[1], 0);
827     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
828     hr = IDirect3DDevice8_CreateVertexShader(device, decl, vertex_shader_code2, &vertex_shader[2], 0);
829     ok(SUCCEEDED(hr), "CreateVertexShader failed (%08x)\n", hr);
830     hr = IDirect3DDevice8_CreatePixelShader(device, pixel_shader_code, &pixel_shader[1]);
831     ok(SUCCEEDED(hr), "CreatePixelShader failed (%08x)\n", hr);
832
833     /* Set shader constant value */
834     hr = IDirect3DDevice8_SetVertexShader(device, vertex_shader[2]);
835     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
836     hr = IDirect3DDevice8_SetVertexShaderConstant(device, 0, vs_constant, 1);
837     ok(hr == D3D_OK, "Setting vertex shader constant failed (%08x)\n", hr);
838
839     /* Setup initial states: No lighting, fog on, fog color */
840     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
841     ok(hr == D3D_OK, "Turning off lighting failed (%08x)\n", hr);
842     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
843     ok(hr == D3D_OK, "Turning on fog calculations failed (%08x)\n", hr);
844     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
845     ok(hr == D3D_OK, "Setting fog color failed (%08x)\n", hr);
846
847     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
848     ok(hr == D3D_OK, "Turning off table fog failed (%08x)\n", hr);
849     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
850     ok(hr == D3D_OK, "Turning off vertex fog failed (%08x)\n", hr);
851
852     /* Use fogtart = 0.1 and end = 0.9 to test behavior outside the fog transition phase, too */
853     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGSTART, start.i);
854     ok(hr == D3D_OK, "Setting fog start failed (%08x)\n", hr);
855     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGEND, end.i);
856     ok(hr == D3D_OK, "Setting fog end failed (%08x)\n", hr);
857
858     for (i = 0; i < sizeof(test_data)/sizeof(test_data[0]); ++i)
859     {
860         hr = IDirect3DDevice8_SetVertexShader(device, vertex_shader[test_data[i].vshader]);
861         ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
862         hr = IDirect3DDevice8_SetPixelShader(device, pixel_shader[test_data[i].pshader]);
863         ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
864         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGVERTEXMODE, test_data[i].vfog);
865         ok( hr == D3D_OK, "Setting fog vertex mode to D3DFOG_LINEAR failed (%08x)\n", hr);
866         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGTABLEMODE, test_data[i].tfog);
867         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR failed (%08x)\n", hr);
868
869         for(j = 0; j < 11; ++j)
870         {
871             /* Don't use the whole zrange to prevent rounding errors */
872             quad[0].z = 0.001f + j / 10.02f;
873             quad[1].z = 0.001f + j / 10.02f;
874             quad[2].z = 0.001f + j / 10.02f;
875             quad[3].z = 0.001f + j / 10.02f;
876
877             hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0f, 0);
878             ok(hr == D3D_OK, "IDirect3DDevice9_Clear failed (%08x)\n", hr);
879
880             hr = IDirect3DDevice8_BeginScene(device);
881             ok( hr == D3D_OK, "BeginScene returned failed (%08x)\n", hr);
882
883             hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], sizeof(quad[0]));
884             ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%08x)\n", hr);
885
886             hr = IDirect3DDevice8_EndScene(device);
887             ok(hr == D3D_OK, "EndScene failed (%08x)\n", hr);
888
889             /* As the red and green component are the result of blending use 5% tolerance on the expected value */
890             color = getPixelColor(device, 128, 240);
891             ok(color_match(color, test_data[i].color[j], 13),
892                     "fog vs%i ps%i fvm%i ftm%i %d: got color %08x, expected %08x +-5%%\n",
893                     test_data[i].vshader, test_data[i].pshader,
894                     test_data[i].vfog, test_data[i].tfog, j, color, test_data[i].color[j]);
895
896             IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
897         }
898     }
899
900     /* Reset states */
901     hr = IDirect3DDevice8_SetVertexShader(device, 0);
902     ok(SUCCEEDED(hr), "SetVertexShader failed (%08x)\n", hr);
903     hr = IDirect3DDevice8_SetPixelShader(device, 0);
904     ok(SUCCEEDED(hr), "SetPixelShader failed (%08x)\n", hr);
905     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
906     ok(hr == D3D_OK, "Turning off fog calculations failed (%08x)\n", hr);
907
908     IDirect3DDevice8_DeleteVertexShader(device, vertex_shader[1]);
909     IDirect3DDevice8_DeleteVertexShader(device, vertex_shader[2]);
910     IDirect3DDevice8_DeleteVertexShader(device, pixel_shader[1]);
911 }
912
913 static void present_test(IDirect3DDevice8 *device)
914 {
915     struct vertex quad[] =
916     {
917         {-1.0f, -1.0f,   0.9f,                          0xffff0000},
918         {-1.0f,  1.0f,   0.9f,                          0xffff0000},
919         { 1.0f, -1.0f,   0.1f,                          0xffff0000},
920         { 1.0f,  1.0f,   0.1f,                          0xffff0000},
921     };
922     HRESULT hr;
923     DWORD color;
924
925     /* Does the Present clear the depth stencil? Clear the depth buffer with some value != 0,
926     * then call Present. Then clear the color buffer to make sure it has some defined content
927     * after the Present with D3DSWAPEFFECT_DISCARD. After that draw a plane that is somewhere cut
928     * by the depth value.
929     */
930     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.75, 0);
931     ok(hr == D3D_OK, "IDirect3DDevice8_Clear returned %08x\n", hr);
932     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
933     ok(SUCCEEDED(hr), "IDirect3DDevice8_Present returned %#x.\n", hr);
934     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4f, 0);
935     ok(SUCCEEDED(hr), "IDirect3DDevice8_Clear returned %#x.\n", hr);
936
937     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
938     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %08x\n", hr);
939     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
940     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %08x\n", hr);
941     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
942     ok(hr == D3D_OK, "IDirect3DDevice8_SetFVF returned %08x\n", hr);
943
944     hr = IDirect3DDevice8_BeginScene(device);
945     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %08x\n", hr);
946     if(hr == D3D_OK)
947     {
948         /* No lights are defined... That means, lit vertices should be entirely black */
949         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
950         ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %08x\n", hr);
951
952         hr = IDirect3DDevice8_EndScene(device);
953         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %08x\n", hr);
954     }
955
956     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
957     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %08x\n", hr);
958
959     color = getPixelColor(device, 512, 240);
960     ok(color == 0x00ffffff, "Present failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
961     color = getPixelColor(device, 64, 240);
962     ok(color == 0x00ff0000, "Present failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
963
964     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
965     ok(SUCCEEDED(hr), "Present failed (%#08x)\n", hr);
966 }
967
968 static void test_rcp_rsq(IDirect3DDevice8 *device)
969 {
970     HRESULT hr;
971     DWORD shader;
972     DWORD color;
973     float constant[4] = {1.0, 1.0, 1.0, 2.0};
974
975     static const float quad[][3] = {
976         {-1.0f, -1.0f, 0.0f},
977         {-1.0f,  1.0f, 0.0f},
978         { 1.0f, -1.0f, 0.0f},
979         { 1.0f,  1.0f, 0.0f},
980     };
981
982     const DWORD rcp_test[] = {
983         0xfffe0101,                                         /* vs.1.1 */
984
985         0x0009fffe, 0x30303030, 0x30303030,                 /* Shaders have to have a minimal size. */
986         0x30303030, 0x30303030, 0x30303030,                 /* Add a filler comment. Usually D3DX8's*/
987         0x30303030, 0x30303030, 0x30303030,                 /* version comment makes the shader big */
988         0x00303030,                                         /* enough to make windows happy         */
989
990         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0 */
991         0x00000006, 0xd00f0000, 0xa0e40000,                 /* rcp oD0, c0 */
992         0x0000ffff                                          /* END */
993     };
994
995     const DWORD rsq_test[] = {
996         0xfffe0101,                                         /* vs.1.1 */
997
998         0x0009fffe, 0x30303030, 0x30303030,                 /* Shaders have to have a minimal size. */
999         0x30303030, 0x30303030, 0x30303030,                 /* Add a filler comment. Usually D3DX8's*/
1000         0x30303030, 0x30303030, 0x30303030,                 /* version comment makes the shader big */
1001         0x00303030,                                         /* enough to make windows happy         */
1002
1003         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0 */
1004         0x00000007, 0xd00f0000, 0xa0e40000,                 /* rsq oD0, c0 */
1005         0x0000ffff                                          /* END */
1006     };
1007
1008     DWORD decl[] =
1009     {
1010         D3DVSD_STREAM(0),
1011         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
1012         D3DVSD_END()
1013     };
1014
1015     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff336699, 0.0f, 0);
1016     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %#08x\n", hr);
1017
1018     hr = IDirect3DDevice8_CreateVertexShader(device, decl, rcp_test, &shader, 0);
1019     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned with %#08x\n", hr);
1020
1021     hr = IDirect3DDevice8_SetVertexShader(device, shader);
1022     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1023     IDirect3DDevice8_SetVertexShaderConstant(device, 0, constant, 1);
1024
1025     hr = IDirect3DDevice8_BeginScene(device);
1026     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene returned %#08x\n", hr);
1027     if(SUCCEEDED(hr))
1028     {
1029         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], 3 * sizeof(float));
1030         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%#08x)\n", hr);
1031         hr = IDirect3DDevice8_EndScene(device);
1032         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1033     }
1034
1035     color = getPixelColor(device, 320, 240);
1036     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x80, 0x80, 0x80), 4),
1037             "RCP test returned color 0x%08x, expected 0x00808080.\n", color);
1038
1039     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1040     ok(SUCCEEDED(hr), "Present failed (%#08x)\n", hr);
1041
1042     IDirect3DDevice8_SetVertexShader(device, 0);
1043     IDirect3DDevice8_DeleteVertexShader(device, shader);
1044
1045     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff996633, 0.0f, 0);
1046     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %#08x\n", hr);
1047
1048     hr = IDirect3DDevice8_CreateVertexShader(device, decl, rsq_test, &shader, 0);
1049     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned with %#08x\n", hr);
1050
1051     hr = IDirect3DDevice8_SetVertexShader(device, shader);
1052     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
1053     IDirect3DDevice8_SetVertexShaderConstant(device, 0, constant, 1);
1054
1055     hr = IDirect3DDevice8_BeginScene(device);
1056     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene returned %#08x\n", hr);
1057     if(SUCCEEDED(hr))
1058     {
1059         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], 3 * sizeof(float));
1060         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%#08x)\n", hr);
1061         hr = IDirect3DDevice8_EndScene(device);
1062         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
1063     }
1064
1065     color = getPixelColor(device, 320, 240);
1066     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xb4, 0xb4, 0xb4), 4),
1067             "RSQ test returned color 0x%08x, expected 0x00b4b4b4.\n", color);
1068
1069     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1070     ok(SUCCEEDED(hr), "Present failed (%#08x)\n", hr);
1071
1072     IDirect3DDevice8_SetVertexShader(device, 0);
1073     IDirect3DDevice8_DeleteVertexShader(device, shader);
1074 }
1075
1076 static void offscreen_test(IDirect3DDevice8 *device)
1077 {
1078     HRESULT hr;
1079     IDirect3DTexture8 *offscreenTexture = NULL;
1080     IDirect3DSurface8 *backbuffer = NULL, *offscreen = NULL, *depthstencil = NULL;
1081     DWORD color;
1082
1083     static const float quad[][5] = {
1084         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
1085         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
1086         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
1087         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
1088     };
1089
1090     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &depthstencil);
1091     ok(hr == D3D_OK, "IDirect3DDevice8_GetDepthStencilSurface failed, hr = %#08x\n", hr);
1092
1093     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
1094     ok(hr == D3D_OK, "Clear failed, hr = %#08x\n", hr);
1095
1096     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture);
1097     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr);
1098     if(!offscreenTexture) {
1099         trace("Failed to create an X8R8G8B8 offscreen texture, trying R5G6B5\n");
1100         hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &offscreenTexture);
1101         ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr);
1102         if(!offscreenTexture) {
1103             skip("Cannot create an offscreen render target\n");
1104             goto out;
1105         }
1106     }
1107
1108     hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1109     ok(hr == D3D_OK, "Can't get back buffer, hr = %#08x\n", hr);
1110     if(!backbuffer) {
1111         goto out;
1112     }
1113
1114     hr = IDirect3DTexture8_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
1115     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %#08x\n", hr);
1116     if(!offscreen) {
1117         goto out;
1118     }
1119
1120     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_TEX1);
1121     ok(hr == D3D_OK, "SetVertexShader failed, hr = %#08x\n", hr);
1122
1123     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
1124     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %#08x\n", hr);
1125     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
1126     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %#08x\n", hr);
1127     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DTEXF_NONE);
1128     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MINFILTER failed (%#08x)\n", hr);
1129     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DTEXF_NONE);
1130     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MAGFILTER failed (%#08x)\n", hr);
1131     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1132     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %08x\n", hr);
1133
1134     if(IDirect3DDevice8_BeginScene(device) == D3D_OK) {
1135         hr = IDirect3DDevice8_SetRenderTarget(device, offscreen, depthstencil);
1136         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %#08x\n", hr);
1137         hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
1138         ok(hr == D3D_OK, "Clear failed, hr = %#08x\n", hr);
1139
1140         /* Draw without textures - Should result in a white quad */
1141         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
1142         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
1143
1144         hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depthstencil);
1145         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %#08x\n", hr);
1146         hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *) offscreenTexture);
1147         ok(hr == D3D_OK, "SetTexture failed, %08x\n", hr);
1148
1149         /* This time with the texture */
1150         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
1151         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
1152
1153         IDirect3DDevice8_EndScene(device);
1154     }
1155
1156     /* Center quad - should be white */
1157     color = getPixelColor(device, 320, 240);
1158     ok(color == 0x00ffffff, "Offscreen failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
1159     /* Some quad in the cleared part of the texture */
1160     color = getPixelColor(device, 170, 240);
1161     ok(color == 0x00ff00ff, "Offscreen failed: Got color 0x%08x, expected 0x00ff00ff.\n", color);
1162     /* Part of the originally cleared back buffer */
1163     color = getPixelColor(device, 10, 10);
1164     ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1165     if(0) {
1166         /* Lower left corner of the screen, where back buffer offscreen rendering draws the offscreen texture.
1167         * It should be red, but the offscreen texture may leave some junk there. Not tested yet. Depending on
1168         * the offscreen rendering mode this test would succeed or fail
1169         */
1170         color = getPixelColor(device, 10, 470);
1171         ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
1172     }
1173
1174     IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1175
1176 out:
1177     hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
1178     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetTexture returned %#x.\n", hr);
1179
1180     /* restore things */
1181     if(backbuffer) {
1182         hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depthstencil);
1183         ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget returned %#x.\n", hr);
1184         IDirect3DSurface8_Release(backbuffer);
1185     }
1186     if(offscreenTexture) {
1187         IDirect3DTexture8_Release(offscreenTexture);
1188     }
1189     if(offscreen) {
1190         IDirect3DSurface8_Release(offscreen);
1191     }
1192     if(depthstencil) {
1193         IDirect3DSurface8_Release(depthstencil);
1194     }
1195 }
1196
1197 static void alpha_test(IDirect3DDevice8 *device)
1198 {
1199     HRESULT hr;
1200     IDirect3DTexture8 *offscreenTexture;
1201     IDirect3DSurface8 *backbuffer = NULL, *offscreen = NULL, *depthstencil = NULL;
1202     DWORD color;
1203
1204     struct vertex quad1[] =
1205     {
1206         {-1.0f, -1.0f,   0.1f,                          0x4000ff00},
1207         {-1.0f,  0.0f,   0.1f,                          0x4000ff00},
1208         { 1.0f, -1.0f,   0.1f,                          0x4000ff00},
1209         { 1.0f,  0.0f,   0.1f,                          0x4000ff00},
1210     };
1211     struct vertex quad2[] =
1212     {
1213         {-1.0f,  0.0f,   0.1f,                          0xc00000ff},
1214         {-1.0f,  1.0f,   0.1f,                          0xc00000ff},
1215         { 1.0f,  0.0f,   0.1f,                          0xc00000ff},
1216         { 1.0f,  1.0f,   0.1f,                          0xc00000ff},
1217     };
1218     static const float composite_quad[][5] = {
1219         { 0.0f, -1.0f, 0.1f, 0.0f, 1.0f},
1220         { 0.0f,  1.0f, 0.1f, 0.0f, 0.0f},
1221         { 1.0f, -1.0f, 0.1f, 1.0f, 1.0f},
1222         { 1.0f,  1.0f, 0.1f, 1.0f, 0.0f},
1223     };
1224
1225     /* Clear the render target with alpha = 0.5 */
1226     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
1227     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
1228
1229     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture);
1230     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr);
1231
1232     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &depthstencil);
1233     ok(hr == D3D_OK, "IDirect3DDevice8_GetDepthStencilSurface failed, hr = %#08x\n", hr);
1234
1235     hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
1236     ok(hr == D3D_OK, "Can't get back buffer, hr = %#08x\n", hr);
1237     if(!backbuffer) {
1238         goto out;
1239     }
1240     hr = IDirect3DTexture8_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
1241     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %#08x\n", hr);
1242     if(!offscreen) {
1243         goto out;
1244     }
1245
1246     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1247     ok(hr == D3D_OK, "SetVertexShader failed, hr = %#08x\n", hr);
1248
1249     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
1250     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %#08x\n", hr);
1251     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
1252     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %#08x\n", hr);
1253     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DTEXF_NONE);
1254     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MINFILTER failed (%#08x)\n", hr);
1255     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DTEXF_NONE);
1256     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MAGFILTER failed (%#08x)\n", hr);
1257     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1258     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %08x\n", hr);
1259
1260     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
1261     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1262     if(IDirect3DDevice8_BeginScene(device) == D3D_OK) {
1263
1264         /* Draw two quads, one with src alpha blending, one with dest alpha blending. */
1265         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
1266         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1267         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
1268         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1269         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
1270         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
1271
1272         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
1273         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1274         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
1275         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1276         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
1277         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
1278
1279         /* Switch to the offscreen buffer, and redo the testing. The offscreen render target
1280          * doesn't have an alpha channel. DESTALPHA and INVDESTALPHA "don't work" on render
1281          * targets without alpha channel, they give essentially ZERO and ONE blend factors. */
1282         hr = IDirect3DDevice8_SetRenderTarget(device, offscreen, 0);
1283         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
1284         hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
1285         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
1286
1287         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
1288         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1289         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
1290         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1291         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
1292         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
1293
1294         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
1295         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1296         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
1297         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1298         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
1299         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
1300
1301         hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depthstencil);
1302         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
1303
1304         /* Render the offscreen texture onto the frame buffer to be able to compare it regularly.
1305          * Disable alpha blending for the final composition
1306          */
1307         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
1308         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1309         hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_TEX1);
1310         ok(hr == D3D_OK, "SetVertexShader failed, hr = %#08x\n", hr);
1311
1312         hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *) offscreenTexture);
1313         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture failed, hr = %08x\n", hr);
1314         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, composite_quad, sizeof(float) * 5);
1315         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
1316         hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
1317         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture failed, hr = %08x\n", hr);
1318
1319         hr = IDirect3DDevice8_EndScene(device);
1320         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
1321     }
1322
1323     color = getPixelColor(device, 160, 360);
1324     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1),
1325        "SRCALPHA on frame buffer returned color %08x, expected 0x00bf4000\n", color);
1326
1327     color = getPixelColor(device, 160, 120);
1328     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x7f, 0x00, 0x80), 2),
1329        "DSTALPHA on frame buffer returned color %08x, expected 0x007f0080\n", color);
1330
1331     color = getPixelColor(device, 480, 360);
1332     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1),
1333        "SRCALPHA on texture returned color %08x, expected 0x00bf4000\n", color);
1334
1335     color = getPixelColor(device, 480, 120);
1336     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xff), 1),
1337        "DSTALPHA on texture returned color %08x, expected 0x000000ff\n", color);
1338
1339     IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1340
1341     out:
1342     /* restore things */
1343     if(backbuffer) {
1344         IDirect3DSurface8_Release(backbuffer);
1345     }
1346     if(offscreenTexture) {
1347         IDirect3DTexture8_Release(offscreenTexture);
1348     }
1349     if(offscreen) {
1350         IDirect3DSurface8_Release(offscreen);
1351     }
1352     if(depthstencil) {
1353         IDirect3DSurface8_Release(depthstencil);
1354     }
1355 }
1356
1357 static void p8_texture_test(IDirect3DDevice8 *device)
1358 {
1359     IDirect3D8 *d3d = NULL;
1360     HRESULT hr;
1361     IDirect3DTexture8 *texture = NULL, *texture2 = NULL;
1362     D3DLOCKED_RECT lr;
1363     unsigned char *data;
1364     DWORD color, red, green, blue;
1365     PALETTEENTRY table[256];
1366     D3DCAPS8 caps;
1367     UINT i;
1368     float quad[] = {
1369        -1.0f,      0.0f,    0.1f,    0.0f,   0.0f,
1370        -1.0f,      1.0f,    0.1f,    0.0f,   1.0f,
1371         1.0f,      0.0f,    0.1f,    1.0f,   0.0f,
1372         1.0f,      1.0f,    0.1f,    1.0f,   1.0f,
1373     };
1374     float quad2[] = {
1375        -1.0f,      -1.0f,   0.1f,    0.0f,   0.0f,
1376        -1.0f,      0.0f,    0.1f,    0.0f,   1.0f,
1377         1.0f,      -1.0f,   0.1f,    1.0f,   0.0f,
1378         1.0f,      0.0f,    0.1f,    1.0f,   1.0f,
1379     };
1380
1381     IDirect3DDevice8_GetDirect3D(device, &d3d);
1382
1383     if(IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
1384        D3DRTYPE_TEXTURE, D3DFMT_P8) != D3D_OK) {
1385            skip("D3DFMT_P8 textures not supported\n");
1386            goto out;
1387     }
1388
1389     hr = IDirect3DDevice8_CreateTexture(device, 1, 1, 1, 0, D3DFMT_P8,
1390                                         D3DPOOL_MANAGED, &texture2);
1391     ok(hr == D3D_OK, "IDirect3DDevice8_CreateTexture failed, hr = %08x\n", hr);
1392     if(!texture2) {
1393         skip("Failed to create D3DFMT_P8 texture\n");
1394         goto out;
1395     }
1396
1397     memset(&lr, 0, sizeof(lr));
1398     hr = IDirect3DTexture8_LockRect(texture2, 0, &lr, NULL, 0);
1399     ok(hr == D3D_OK, "IDirect3DTexture8_LockRect failed, hr = %08x\n", hr);
1400     data = lr.pBits;
1401     *data = 1;
1402
1403     hr = IDirect3DTexture8_UnlockRect(texture2, 0);
1404     ok(hr == D3D_OK, "IDirect3DTexture8_UnlockRect failed, hr = %08x\n", hr);
1405
1406     hr = IDirect3DDevice8_CreateTexture(device, 1, 1, 1, 0, D3DFMT_P8,
1407                                         D3DPOOL_MANAGED, &texture);
1408     ok(hr == D3D_OK, "IDirect3DDevice8_CreateTexture failed, hr = %08x\n", hr);
1409     if(!texture) {
1410         skip("Failed to create D3DFMT_P8 texture\n");
1411         goto out;
1412     }
1413
1414     memset(&lr, 0, sizeof(lr));
1415     hr = IDirect3DTexture8_LockRect(texture, 0, &lr, NULL, 0);
1416     ok(hr == D3D_OK, "IDirect3DTexture8_LockRect failed, hr = %08x\n", hr);
1417     data = lr.pBits;
1418     *data = 1;
1419
1420     hr = IDirect3DTexture8_UnlockRect(texture, 0);
1421     ok(hr == D3D_OK, "IDirect3DTexture8_UnlockRect failed, hr = %08x\n", hr);
1422
1423     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
1424     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed, hr = %08x\n", hr);
1425
1426     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
1427     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1428
1429     /* The first part of the test should work both with and without D3DPTEXTURECAPS_ALPHAPALETTE;
1430        alpha of every entry is set to 1.0, which MS says is required when there's no
1431        D3DPTEXTURECAPS_ALPHAPALETTE capability */
1432     for (i = 0; i < 256; i++) {
1433         table[i].peRed = table[i].peGreen = table[i].peBlue = 0;
1434         table[i].peFlags = 0xff;
1435     }
1436     table[1].peRed = 0xff;
1437     hr = IDirect3DDevice8_SetPaletteEntries(device, 0, table);
1438     ok(hr == D3D_OK, "IDirect3DDevice8_SetPaletteEntries failed, hr = %08x\n", hr);
1439
1440     table[1].peRed = 0;
1441     table[1].peBlue = 0xff;
1442     hr = IDirect3DDevice8_SetPaletteEntries(device, 1, table);
1443     ok(hr == D3D_OK, "IDirect3DDevice8_SetPaletteEntries failed, hr = %08x\n", hr);
1444
1445     hr = IDirect3DDevice8_BeginScene(device);
1446     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed, hr = %08x\n", hr);
1447     if(SUCCEEDED(hr)) {
1448         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
1449         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1450         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
1451         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1452
1453         hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_TEX1);
1454         ok(hr == D3D_OK, "SetVertexShader failed, hr = %#08x\n", hr);
1455
1456         hr = IDirect3DDevice8_SetCurrentTexturePalette(device, 0);
1457         ok(hr == D3D_OK, "IDirect3DDevice8_SetCurrentTexturePalette failed, hr = %08x\n", hr);
1458
1459         hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *) texture2);
1460         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture failed, hr = %08x\n", hr);
1461         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
1462         ok(hr == D3D_OK, "IDirect3DDevice8_DrawPrimitiveUP failed, hr = %08x\n", hr);
1463
1464         hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *) texture);
1465         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture failed, hr = %08x\n", hr);
1466         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
1467         ok(hr == D3D_OK, "IDirect3DDevice8_DrawPrimitiveUP failed, hr = %08x\n", hr);
1468
1469         hr = IDirect3DDevice8_SetCurrentTexturePalette(device, 1);
1470         ok(hr == D3D_OK, "IDirect3DDevice8_SetCurrentTexturePalette failed, hr = %08x\n", hr);
1471         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
1472         ok(hr == D3D_OK, "IDirect3DDevice8_DrawPrimitiveUP failed, hr = %08x\n", hr);
1473
1474         hr = IDirect3DDevice8_EndScene(device);
1475         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed, hr = %08x\n", hr);
1476     }
1477
1478     color = getPixelColor(device, 32, 32);
1479     red   = (color & 0x00ff0000) >> 16;
1480     green = (color & 0x0000ff00) >>  8;
1481     blue  = (color & 0x000000ff) >>  0;
1482     ok(red == 0xff && blue == 0 && green == 0,
1483        "got color %08x, expected 0x00ff0000\n", color);
1484
1485     color = getPixelColor(device, 32, 320);
1486     red   = (color & 0x00ff0000) >> 16;
1487     green = (color & 0x0000ff00) >>  8;
1488     blue  = (color & 0x000000ff) >>  0;
1489     ok(red == 0 && blue == 0xff && green == 0,
1490     "got color %08x, expected 0x000000ff\n", color);
1491
1492     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1493     ok(hr == D3D_OK, "IDirect3DDevice8_Present failed, hr = %08x\n", hr);
1494
1495     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
1496     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed, hr = %08x\n", hr);
1497
1498     hr = IDirect3DDevice8_BeginScene(device);
1499     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed, hr = %08x\n", hr);
1500     if(SUCCEEDED(hr)) {
1501         hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *) texture2);
1502         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture failed, hr = %08x\n", hr);
1503
1504         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
1505         ok(hr == D3D_OK, "IDirect3DDevice8_DrawPrimitiveUP failed, hr = %08x\n", hr);
1506
1507         hr = IDirect3DDevice8_EndScene(device);
1508         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed, hr = %08x\n", hr);
1509     }
1510
1511
1512     color = getPixelColor(device, 32, 32);
1513     red   = (color & 0x00ff0000) >> 16;
1514     green = (color & 0x0000ff00) >>  8;
1515     blue  = (color & 0x000000ff) >>  0;
1516     ok(red == 0 && blue == 0xff && green == 0,
1517     "got color %08x, expected 0x000000ff\n", color);
1518
1519     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1520     ok(hr == D3D_OK, "IDirect3DDevice8_Present failed, hr = %08x\n", hr);
1521
1522     /* Test palettes with alpha */
1523     IDirect3DDevice8_GetDeviceCaps(device, &caps);
1524     if (!(caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)) {
1525         skip("no D3DPTEXTURECAPS_ALPHAPALETTE capability, tests with alpha in palette will be skipped\n");
1526     } else {
1527         hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
1528         ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed, hr = %08x\n", hr);
1529
1530         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
1531         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1532
1533         for (i = 0; i < 256; i++) {
1534             table[i].peRed = table[i].peGreen = table[i].peBlue = 0;
1535             table[i].peFlags = 0xff;
1536         }
1537         table[1].peRed = 0xff;
1538         table[1].peFlags = 0x80;
1539         hr = IDirect3DDevice8_SetPaletteEntries(device, 0, table);
1540         ok(hr == D3D_OK, "IDirect3DDevice8_SetPaletteEntries failed, hr = %08x\n", hr);
1541
1542         table[1].peRed = 0;
1543         table[1].peBlue = 0xff;
1544         table[1].peFlags = 0x80;
1545         hr = IDirect3DDevice8_SetPaletteEntries(device, 1, table);
1546         ok(hr == D3D_OK, "IDirect3DDevice8_SetPaletteEntries failed, hr = %08x\n", hr);
1547
1548         hr = IDirect3DDevice8_BeginScene(device);
1549         ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed, hr = %08x\n", hr);
1550         if(SUCCEEDED(hr)) {
1551             hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
1552             ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1553             hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
1554             ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1555
1556             hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_TEX1);
1557             ok(hr == D3D_OK, "SetVertexShader failed, hr = %#08x\n", hr);
1558
1559             hr = IDirect3DDevice8_SetCurrentTexturePalette(device, 0);
1560             ok(hr == D3D_OK, "IDirect3DDevice8_SetCurrentTexturePalette failed, hr = %08x\n", hr);
1561
1562             hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
1563             ok(hr == D3D_OK, "IDirect3DDevice8_DrawPrimitiveUP failed, hr = %08x\n", hr);
1564
1565             hr = IDirect3DDevice8_SetCurrentTexturePalette(device, 1);
1566             ok(hr == D3D_OK, "IDirect3DDevice8_SetCurrentTexturePalette failed, hr = %08x\n", hr);
1567
1568             hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
1569             ok(hr == D3D_OK, "IDirect3DDevice8_DrawPrimitiveUP failed, hr = %08x\n", hr);
1570
1571             hr = IDirect3DDevice8_EndScene(device);
1572             ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed, hr = %08x\n", hr);
1573         }
1574
1575         color = getPixelColor(device, 32, 32);
1576         red   = (color & 0x00ff0000) >> 16;
1577         green = (color & 0x0000ff00) >>  8;
1578         blue  = (color & 0x000000ff) >>  0;
1579         ok(red >= 0x7e && red <= 0x81 && blue == 0 && green == 0,
1580         "got color %08x, expected 0x00800000 or near\n", color);
1581
1582         color = getPixelColor(device, 32, 320);
1583         red   = (color & 0x00ff0000) >> 16;
1584         green = (color & 0x0000ff00) >>  8;
1585         blue  = (color & 0x000000ff) >>  0;
1586         ok(red == 0 && blue >= 0x7e && blue <= 0x81 && green == 0,
1587         "got color %08x, expected 0x00000080 or near\n", color);
1588
1589         hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1590         ok(hr == D3D_OK, "IDirect3DDevice8_Present failed, hr = %08x\n", hr);
1591     }
1592
1593     hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
1594     ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture failed, hr = %08x\n", hr);
1595     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
1596     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1597
1598 out:
1599     if(texture) IDirect3DTexture8_Release(texture);
1600     if(texture2) IDirect3DTexture8_Release(texture2);
1601     IDirect3D8_Release(d3d);
1602 }
1603
1604 static void texop_test(IDirect3DDevice8 *device)
1605 {
1606     IDirect3DTexture8 *texture = NULL;
1607     D3DLOCKED_RECT locked_rect;
1608     D3DCOLOR color;
1609     D3DCAPS8 caps;
1610     HRESULT hr;
1611     unsigned int i;
1612
1613     static const struct {
1614         float x, y, z;
1615         D3DCOLOR diffuse;
1616         float s, t;
1617     } quad[] = {
1618         {-1.0f, -1.0f, 0.1f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00), -1.0f, -1.0f},
1619         {-1.0f,  1.0f, 0.1f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00), -1.0f,  1.0f},
1620         { 1.0f, -1.0f, 0.1f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00),  1.0f, -1.0f},
1621         { 1.0f,  1.0f, 0.1f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00),  1.0f,  1.0f}
1622     };
1623
1624     static const struct {
1625         D3DTEXTUREOP op;
1626         const char *name;
1627         DWORD caps_flag;
1628         D3DCOLOR result;
1629     } test_data[] = {
1630         {D3DTOP_SELECTARG1,                "SELECTARG1",                D3DTEXOPCAPS_SELECTARG1,                D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
1631         {D3DTOP_SELECTARG2,                "SELECTARG2",                D3DTEXOPCAPS_SELECTARG2,                D3DCOLOR_ARGB(0x00, 0x33, 0x33, 0x33)},
1632         {D3DTOP_MODULATE,                  "MODULATE",                  D3DTEXOPCAPS_MODULATE,                  D3DCOLOR_ARGB(0x00, 0x00, 0x33, 0x00)},
1633         {D3DTOP_MODULATE2X,                "MODULATE2X",                D3DTEXOPCAPS_MODULATE2X,                D3DCOLOR_ARGB(0x00, 0x00, 0x66, 0x00)},
1634         {D3DTOP_MODULATE4X,                "MODULATE4X",                D3DTEXOPCAPS_MODULATE4X,                D3DCOLOR_ARGB(0x00, 0x00, 0xcc, 0x00)},
1635         {D3DTOP_ADD,                       "ADD",                       D3DTEXOPCAPS_ADD,                       D3DCOLOR_ARGB(0x00, 0x33, 0xff, 0x33)},
1636
1637         {D3DTOP_ADDSIGNED,                 "ADDSIGNED",                 D3DTEXOPCAPS_ADDSIGNED,                 D3DCOLOR_ARGB(0x00, 0x00, 0xb2, 0x00)},
1638         {D3DTOP_ADDSIGNED2X,               "ADDSIGNED2X",               D3DTEXOPCAPS_ADDSIGNED2X,               D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
1639
1640         {D3DTOP_SUBTRACT,                  "SUBTRACT",                  D3DTEXOPCAPS_SUBTRACT,                  D3DCOLOR_ARGB(0x00, 0x00, 0xcc, 0x00)},
1641         {D3DTOP_ADDSMOOTH,                 "ADDSMOOTH",                 D3DTEXOPCAPS_ADDSMOOTH,                 D3DCOLOR_ARGB(0x00, 0x33, 0xff, 0x33)},
1642         {D3DTOP_BLENDDIFFUSEALPHA,         "BLENDDIFFUSEALPHA",         D3DTEXOPCAPS_BLENDDIFFUSEALPHA,         D3DCOLOR_ARGB(0x00, 0x22, 0x77, 0x22)},
1643         {D3DTOP_BLENDTEXTUREALPHA,         "BLENDTEXTUREALPHA",         D3DTEXOPCAPS_BLENDTEXTUREALPHA,         D3DCOLOR_ARGB(0x00, 0x14, 0xad, 0x14)},
1644         {D3DTOP_BLENDFACTORALPHA,          "BLENDFACTORALPHA",          D3DTEXOPCAPS_BLENDFACTORALPHA,          D3DCOLOR_ARGB(0x00, 0x07, 0xe4, 0x07)},
1645         {D3DTOP_BLENDTEXTUREALPHAPM,       "BLENDTEXTUREALPHAPM",       D3DTEXOPCAPS_BLENDTEXTUREALPHAPM,       D3DCOLOR_ARGB(0x00, 0x14, 0xff, 0x14)},
1646         {D3DTOP_BLENDCURRENTALPHA,         "BLENDCURRENTALPHA",         D3DTEXOPCAPS_BLENDCURRENTALPHA,         D3DCOLOR_ARGB(0x00, 0x22, 0x77, 0x22)},
1647         {D3DTOP_MODULATEALPHA_ADDCOLOR,    "MODULATEALPHA_ADDCOLOR",    D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR,    D3DCOLOR_ARGB(0x00, 0x1f, 0xff, 0x1f)},
1648         {D3DTOP_MODULATECOLOR_ADDALPHA,    "MODULATECOLOR_ADDALPHA",    D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA,    D3DCOLOR_ARGB(0x00, 0x99, 0xcc, 0x99)},
1649         {D3DTOP_MODULATEINVALPHA_ADDCOLOR, "MODULATEINVALPHA_ADDCOLOR", D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR, D3DCOLOR_ARGB(0x00, 0x14, 0xff, 0x14)},
1650         {D3DTOP_MODULATEINVCOLOR_ADDALPHA, "MODULATEINVCOLOR_ADDALPHA", D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA, D3DCOLOR_ARGB(0x00, 0xcc, 0x99, 0xcc)},
1651         /* BUMPENVMAP & BUMPENVMAPLUMINANCE have their own tests */
1652         {D3DTOP_DOTPRODUCT3,               "DOTPRODUCT2",               D3DTEXOPCAPS_DOTPRODUCT3,               D3DCOLOR_ARGB(0x00, 0x99, 0x99, 0x99)},
1653         {D3DTOP_MULTIPLYADD,               "MULTIPLYADD",               D3DTEXOPCAPS_MULTIPLYADD,               D3DCOLOR_ARGB(0x00, 0xff, 0x33, 0x00)},
1654         {D3DTOP_LERP,                      "LERP",                      D3DTEXOPCAPS_LERP,                      D3DCOLOR_ARGB(0x00, 0x00, 0x33, 0x33)},
1655     };
1656
1657     memset(&caps, 0, sizeof(caps));
1658     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
1659     ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x\n", hr);
1660
1661     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX0);
1662     ok(SUCCEEDED(hr), "SetVertexShader failed with 0x%08x\n", hr);
1663
1664     hr = IDirect3DDevice8_CreateTexture(device, 1, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture);
1665     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed with 0x%08x\n", hr);
1666     hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, NULL, 0);
1667     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
1668     *((DWORD *)locked_rect.pBits) = D3DCOLOR_ARGB(0x99, 0x00, 0xff, 0x00);
1669     hr = IDirect3DTexture8_UnlockRect(texture, 0);
1670     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
1671     hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *)texture);
1672     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
1673
1674     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLORARG0, D3DTA_DIFFUSE);
1675     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
1676     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
1677     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
1678     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
1679     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
1680
1681     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
1682     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
1683
1684     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1685     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
1686     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0xdd333333);
1687     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
1688     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA);
1689     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
1690
1691     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
1692     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
1693
1694     for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
1695     {
1696         if (!(caps.TextureOpCaps & test_data[i].caps_flag))
1697         {
1698             skip("tex operation %s not supported\n", test_data[i].name);
1699             continue;
1700         }
1701
1702         hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLOROP, test_data[i].op);
1703         ok(SUCCEEDED(hr), "SetTextureStageState (%s) failed with 0x%08x\n", test_data[i].name, hr);
1704
1705         hr = IDirect3DDevice8_BeginScene(device);
1706         ok(SUCCEEDED(hr), "BeginScene failed with 0x%08x\n", hr);
1707
1708         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
1709         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
1710
1711         hr = IDirect3DDevice8_EndScene(device);
1712         ok(SUCCEEDED(hr), "EndScene failed with 0x%08x\n", hr);
1713
1714         color = getPixelColor(device, 320, 240);
1715         ok(color_match(color, test_data[i].result, 3), "Operation %s returned color 0x%08x, expected 0x%08x\n",
1716                 test_data[i].name, color, test_data[i].result);
1717
1718         hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1719         ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
1720
1721         hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
1722         ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
1723     }
1724
1725     hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
1726     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
1727     if (texture) IDirect3DTexture8_Release(texture);
1728 }
1729
1730 /* This test tests depth clamping / clipping behaviour:
1731  *   - With software vertex processing, depth values are clamped to the
1732  *     minimum / maximum z value when D3DRS_CLIPPING is disabled, and clipped
1733  *     when D3DRS_CLIPPING is enabled. Pretransformed vertices behave the
1734  *     same as regular vertices here.
1735  *   - With hardware vertex processing, D3DRS_CLIPPING seems to be ignored.
1736  *     Normal vertices are always clipped. Pretransformed vertices are
1737  *     clipped when D3DPMISCCAPS_CLIPTLVERTS is set, clamped when it isn't.
1738  *   - The viewport's MinZ/MaxZ is irrelevant for this.
1739  */
1740 static void depth_clamp_test(IDirect3DDevice8 *device)
1741 {
1742     const struct tvertex quad1[] =
1743     {
1744         {  0.0f,   0.0f,  5.0f, 1.0f, 0xff002b7f},
1745         {640.0f,   0.0f,  5.0f, 1.0f, 0xff002b7f},
1746         {  0.0f, 480.0f,  5.0f, 1.0f, 0xff002b7f},
1747         {640.0f, 480.0f,  5.0f, 1.0f, 0xff002b7f},
1748     };
1749     const struct tvertex quad2[] =
1750     {
1751         {  0.0f, 300.0f, 10.0f, 1.0f, 0xfff9e814},
1752         {640.0f, 300.0f, 10.0f, 1.0f, 0xfff9e814},
1753         {  0.0f, 360.0f, 10.0f, 1.0f, 0xfff9e814},
1754         {640.0f, 360.0f, 10.0f, 1.0f, 0xfff9e814},
1755     };
1756     const struct tvertex quad3[] =
1757     {
1758         {112.0f, 108.0f,  5.0f, 1.0f, 0xffffffff},
1759         {208.0f, 108.0f,  5.0f, 1.0f, 0xffffffff},
1760         {112.0f, 204.0f,  5.0f, 1.0f, 0xffffffff},
1761         {208.0f, 204.0f,  5.0f, 1.0f, 0xffffffff},
1762     };
1763     const struct tvertex quad4[] =
1764     {
1765         { 42.0f,  41.0f, 10.0f, 1.0f, 0xffffffff},
1766         {112.0f,  41.0f, 10.0f, 1.0f, 0xffffffff},
1767         { 42.0f, 108.0f, 10.0f, 1.0f, 0xffffffff},
1768         {112.0f, 108.0f, 10.0f, 1.0f, 0xffffffff},
1769     };
1770     const struct vertex quad5[] =
1771     {
1772         { -0.5f,   0.5f, 10.0f,       0xff14f914},
1773         {  0.5f,   0.5f, 10.0f,       0xff14f914},
1774         { -0.5f,  -0.5f, 10.0f,       0xff14f914},
1775         {  0.5f,  -0.5f, 10.0f,       0xff14f914},
1776     };
1777     const struct vertex quad6[] =
1778     {
1779         { -1.0f,   0.5f, 10.0f,       0xfff91414},
1780         {  1.0f,   0.5f, 10.0f,       0xfff91414},
1781         { -1.0f,  0.25f, 10.0f,       0xfff91414},
1782         {  1.0f,  0.25f, 10.0f,       0xfff91414},
1783     };
1784
1785     D3DVIEWPORT8 vp;
1786     D3DCOLOR color;
1787     D3DCAPS8 caps;
1788     HRESULT hr;
1789
1790     vp.X = 0;
1791     vp.Y = 0;
1792     vp.Width = 640;
1793     vp.Height = 480;
1794     vp.MinZ = 0.0;
1795     vp.MaxZ = 7.5;
1796
1797     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
1798     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
1799
1800     hr = IDirect3DDevice8_SetViewport(device, &vp);
1801     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
1802
1803     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ff00, 1.0, 0);
1804     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
1805
1806     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPING, FALSE);
1807     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1808     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1809     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1810     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
1811     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1812     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
1813     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1814
1815     hr = IDirect3DDevice8_BeginScene(device);
1816     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
1817
1818     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
1819     ok(SUCCEEDED(hr), "SetVertexSahder failed, hr %#x.\n", hr);
1820
1821     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
1822     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1823     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
1824     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1825
1826     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPING, TRUE);
1827     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1828
1829     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(*quad3));
1830     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1831     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(*quad4));
1832     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1833
1834     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPING, FALSE);
1835     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1836     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1837     ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
1838
1839     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad5, sizeof(*quad5));
1840     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1841
1842     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPING, TRUE);
1843     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1844
1845     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad6, sizeof(*quad6));
1846     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1847
1848     hr = IDirect3DDevice8_EndScene(device);
1849     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
1850
1851     if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_CLIPTLVERTS)
1852     {
1853         color = getPixelColor(device, 75, 75);
1854         ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
1855         color = getPixelColor(device, 150, 150);
1856         ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
1857         color = getPixelColor(device, 320, 240);
1858         ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
1859         color = getPixelColor(device, 320, 330);
1860         ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
1861         color = getPixelColor(device, 320, 330);
1862         ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
1863     }
1864     else
1865     {
1866         color = getPixelColor(device, 75, 75);
1867         ok(color_match(color, 0x00ffffff, 1), "color 0x%08x.\n", color);
1868         color = getPixelColor(device, 150, 150);
1869         ok(color_match(color, 0x00ffffff, 1), "color 0x%08x.\n", color);
1870         color = getPixelColor(device, 320, 240);
1871         ok(color_match(color, 0x00002b7f, 1), "color 0x%08x.\n", color);
1872         color = getPixelColor(device, 320, 330);
1873         ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
1874         color = getPixelColor(device, 320, 330);
1875         ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
1876     }
1877
1878     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1879     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1880
1881     vp.MinZ = 0.0;
1882     vp.MaxZ = 1.0;
1883     hr = IDirect3DDevice8_SetViewport(device, &vp);
1884     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
1885 }
1886
1887 static void depth_buffer_test(IDirect3DDevice8 *device)
1888 {
1889     static const struct vertex quad1[] =
1890     {
1891         { -1.0,  1.0, 0.33f, 0xff00ff00},
1892         {  1.0,  1.0, 0.33f, 0xff00ff00},
1893         { -1.0, -1.0, 0.33f, 0xff00ff00},
1894         {  1.0, -1.0, 0.33f, 0xff00ff00},
1895     };
1896     static const struct vertex quad2[] =
1897     {
1898         { -1.0,  1.0, 0.50f, 0xffff00ff},
1899         {  1.0,  1.0, 0.50f, 0xffff00ff},
1900         { -1.0, -1.0, 0.50f, 0xffff00ff},
1901         {  1.0, -1.0, 0.50f, 0xffff00ff},
1902     };
1903     static const struct vertex quad3[] =
1904     {
1905         { -1.0,  1.0, 0.66f, 0xffff0000},
1906         {  1.0,  1.0, 0.66f, 0xffff0000},
1907         { -1.0, -1.0, 0.66f, 0xffff0000},
1908         {  1.0, -1.0, 0.66f, 0xffff0000},
1909     };
1910     static const DWORD expected_colors[4][4] =
1911     {
1912         {0x000000ff, 0x000000ff, 0x0000ff00, 0x00ff0000},
1913         {0x000000ff, 0x000000ff, 0x0000ff00, 0x00ff0000},
1914         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x00ff0000},
1915         {0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000},
1916     };
1917
1918     IDirect3DSurface8 *backbuffer, *rt1, *rt2, *rt3;
1919     IDirect3DSurface8 *depth_stencil;
1920     unsigned int i, j;
1921     D3DVIEWPORT8 vp;
1922     D3DCOLOR color;
1923     HRESULT hr;
1924
1925     vp.X = 0;
1926     vp.Y = 0;
1927     vp.Width = 640;
1928     vp.Height = 480;
1929     vp.MinZ = 0.0;
1930     vp.MaxZ = 1.0;
1931
1932     hr = IDirect3DDevice8_SetViewport(device, &vp);
1933     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
1934
1935     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1936     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1937     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
1938     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1939     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
1940     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1941     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
1942     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1943     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1944     ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
1945
1946     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &depth_stencil);
1947     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1948     hr = IDirect3DDevice8_GetRenderTarget(device, &backbuffer);
1949     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1950     hr = IDirect3DDevice8_CreateRenderTarget(device, 320, 240, D3DFMT_A8R8G8B8,
1951             D3DMULTISAMPLE_NONE, FALSE, &rt1);
1952     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
1953     hr = IDirect3DDevice8_CreateRenderTarget(device, 480, 360, D3DFMT_A8R8G8B8,
1954             D3DMULTISAMPLE_NONE, FALSE, &rt2);
1955     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
1956     hr = IDirect3DDevice8_CreateRenderTarget(device, 640, 480, D3DFMT_A8R8G8B8,
1957             D3DMULTISAMPLE_NONE, FALSE, &rt3);
1958     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
1959
1960     hr = IDirect3DDevice8_SetRenderTarget(device, rt3, depth_stencil);
1961     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1962     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 0.0f, 0);
1963     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
1964
1965     hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depth_stencil);
1966     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1967     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
1968     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
1969
1970     hr = IDirect3DDevice8_SetRenderTarget(device, rt1, depth_stencil);
1971     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1972     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0f, 0);
1973     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
1974
1975     hr = IDirect3DDevice8_SetRenderTarget(device, rt2, depth_stencil);
1976     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1977     hr = IDirect3DDevice8_BeginScene(device);
1978     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
1979     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
1980     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1981     hr = IDirect3DDevice8_EndScene(device);
1982     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
1983
1984     hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depth_stencil);
1985     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1986
1987     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
1988     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1989
1990     hr = IDirect3DDevice8_BeginScene(device);
1991     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
1992     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
1993     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1994     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(*quad3));
1995     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1996     hr = IDirect3DDevice8_EndScene(device);
1997     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
1998
1999     for (i = 0; i < 4; ++i)
2000     {
2001         for (j = 0; j < 4; ++j)
2002         {
2003             unsigned int x = 80 * ((2 * j) + 1);
2004             unsigned int y = 60 * ((2 * i) + 1);
2005             color = getPixelColor(device, x, y);
2006             ok(color_match(color, expected_colors[i][j], 0),
2007                     "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
2008         }
2009     }
2010
2011     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2012     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2013
2014     IDirect3DSurface8_Release(depth_stencil);
2015     IDirect3DSurface8_Release(backbuffer);
2016     IDirect3DSurface8_Release(rt3);
2017     IDirect3DSurface8_Release(rt2);
2018     IDirect3DSurface8_Release(rt1);
2019 }
2020
2021 /* Test that partial depth copies work the way they're supposed to. The clear
2022  * on rt2 only needs a partial copy of the onscreen depth/stencil buffer, and
2023  * the following draw should only copy back the part that was modified. */
2024 static void depth_buffer2_test(IDirect3DDevice8 *device)
2025 {
2026     static const struct vertex quad[] =
2027     {
2028         { -1.0,  1.0, 0.66f, 0xffff0000},
2029         {  1.0,  1.0, 0.66f, 0xffff0000},
2030         { -1.0, -1.0, 0.66f, 0xffff0000},
2031         {  1.0, -1.0, 0.66f, 0xffff0000},
2032     };
2033
2034     IDirect3DSurface8 *backbuffer, *rt1, *rt2;
2035     IDirect3DSurface8 *depth_stencil;
2036     unsigned int i, j;
2037     D3DVIEWPORT8 vp;
2038     D3DCOLOR color;
2039     HRESULT hr;
2040
2041     vp.X = 0;
2042     vp.Y = 0;
2043     vp.Width = 640;
2044     vp.Height = 480;
2045     vp.MinZ = 0.0;
2046     vp.MaxZ = 1.0;
2047
2048     hr = IDirect3DDevice8_SetViewport(device, &vp);
2049     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
2050
2051     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
2052     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2053     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
2054     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2055     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
2056     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2057     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
2058     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2059     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
2060     ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
2061
2062     hr = IDirect3DDevice8_CreateRenderTarget(device, 640, 480, D3DFMT_A8R8G8B8,
2063             D3DMULTISAMPLE_NONE, FALSE, &rt1);
2064     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
2065     hr = IDirect3DDevice8_CreateRenderTarget(device, 480, 360, D3DFMT_A8R8G8B8,
2066             D3DMULTISAMPLE_NONE, FALSE, &rt2);
2067     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
2068     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &depth_stencil);
2069     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
2070     hr = IDirect3DDevice8_GetRenderTarget(device, &backbuffer);
2071     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
2072
2073     hr = IDirect3DDevice8_SetRenderTarget(device, rt1, depth_stencil);
2074     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2075     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
2076     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
2077
2078     hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depth_stencil);
2079     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2080     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ff00, 0.5f, 0);
2081     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
2082
2083     hr = IDirect3DDevice8_SetRenderTarget(device, rt2, depth_stencil);
2084     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2085     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0f, 0);
2086     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
2087
2088     hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depth_stencil);
2089     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2090
2091     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
2092     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2093
2094     hr = IDirect3DDevice8_BeginScene(device);
2095     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2096     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
2097     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2098     hr = IDirect3DDevice8_EndScene(device);
2099     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2100
2101     for (i = 0; i < 4; ++i)
2102     {
2103         for (j = 0; j < 4; ++j)
2104         {
2105             unsigned int x = 80 * ((2 * j) + 1);
2106             unsigned int y = 60 * ((2 * i) + 1);
2107             color = getPixelColor(device, x, y);
2108             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 0),
2109                     "Expected color 0x0000ff00 %u,%u, got 0x%08x.\n", x, y, color);
2110         }
2111     }
2112
2113     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2114     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2115
2116     IDirect3DSurface8_Release(depth_stencil);
2117     IDirect3DSurface8_Release(backbuffer);
2118     IDirect3DSurface8_Release(rt2);
2119     IDirect3DSurface8_Release(rt1);
2120 }
2121
2122 static void intz_test(IDirect3DDevice8 *device)
2123 {
2124     static const DWORD ps_code[] =
2125     {
2126         0xffff0101,                                                             /* ps_1_1                       */
2127         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1.0, 0.0, 0.0, 0.0   */
2128         0x00000051, 0xa00f0001, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c1, 0.0, 1.0, 0.0, 0.0   */
2129         0x00000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, /* def c2, 0.0, 0.0, 1.0, 0.0   */
2130         0x00000042, 0xb00f0000,                                                 /* tex t0                       */
2131         0x00000042, 0xb00f0001,                                                 /* tex t1                       */
2132         0x00000008, 0xb0070001, 0xa0e40000, 0xb0e40001,                         /* dp3 t1.xyz, c0, t1           */
2133         0x00000005, 0x80070000, 0xa0e40001, 0xb0e40001,                         /* mul r0.xyz, c1, t1           */
2134         0x00000004, 0x80070000, 0xa0e40000, 0xb0e40000, 0x80e40000,             /* mad r0.xyz, c0, t0, r0       */
2135         0x40000001, 0x80080000, 0xa0aa0002,                                     /* +mov r0.w, c2.z              */
2136         0x0000ffff,                                                             /* end                          */
2137     };
2138     struct
2139     {
2140         float x, y, z;
2141         float s0, t0, p0;
2142         float s1, t1, p1, q1;
2143     }
2144     quad[] =
2145     {
2146         { -1.0f,  1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.5f},
2147         {  1.0f,  1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.5f},
2148         { -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f},
2149         {  1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f},
2150     },
2151     half_quad_1[] =
2152     {
2153         { -1.0f,  0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.5f},
2154         {  1.0f,  0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.5f},
2155         { -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f},
2156         {  1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f},
2157     },
2158     half_quad_2[] =
2159     {
2160         { -1.0f,  1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.5f},
2161         {  1.0f,  1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.5f},
2162         { -1.0f,  0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f},
2163         {  1.0f,  0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f},
2164     };
2165     struct
2166     {
2167         UINT x, y;
2168         D3DCOLOR color;
2169     }
2170     expected_colors[] =
2171     {
2172         { 80, 100, D3DCOLOR_ARGB(0x00, 0x20, 0x40, 0x00)},
2173         {240, 100, D3DCOLOR_ARGB(0x00, 0x60, 0xbf, 0x00)},
2174         {400, 100, D3DCOLOR_ARGB(0x00, 0x9f, 0x40, 0x00)},
2175         {560, 100, D3DCOLOR_ARGB(0x00, 0xdf, 0xbf, 0x00)},
2176         { 80, 450, D3DCOLOR_ARGB(0x00, 0x20, 0x40, 0x00)},
2177         {240, 450, D3DCOLOR_ARGB(0x00, 0x60, 0xbf, 0x00)},
2178         {400, 450, D3DCOLOR_ARGB(0x00, 0x9f, 0x40, 0x00)},
2179         {560, 450, D3DCOLOR_ARGB(0x00, 0xdf, 0xbf, 0x00)},
2180     };
2181
2182     IDirect3DSurface8 *original_ds, *original_rt, *rt;
2183     IDirect3DTexture8 *texture;
2184     IDirect3DSurface8 *ds;
2185     IDirect3D8 *d3d8;
2186     D3DCAPS8 caps;
2187     HRESULT hr;
2188     DWORD ps;
2189     UINT i;
2190
2191     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
2192     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
2193     if (caps.PixelShaderVersion < D3DPS_VERSION(1, 1))
2194     {
2195         skip("No pixel shader 1.1 support, skipping INTZ test.\n");
2196         return;
2197     }
2198     if (caps.TextureCaps & D3DPTEXTURECAPS_POW2)
2199     {
2200         skip("No unconditional NP2 texture support, skipping INTZ test.\n");
2201         return;
2202     }
2203
2204     hr = IDirect3DDevice8_GetDirect3D(device, &d3d8);
2205     ok(SUCCEEDED(hr), "GetDirect3D failed, hr %#x.\n", hr);
2206
2207     hr = IDirect3D8_CheckDeviceFormat(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
2208             D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, MAKEFOURCC('I','N','T','Z'));
2209     if (FAILED(hr))
2210     {
2211         skip("No INTZ support, skipping INTZ test.\n");
2212         return;
2213     }
2214
2215     IDirect3D8_Release(d3d8);
2216
2217     hr = IDirect3DDevice8_GetRenderTarget(device, &original_rt);
2218     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
2219     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &original_ds);
2220     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
2221
2222     hr = IDirect3DDevice8_CreateTexture(device, 640, 480, 1,
2223             D3DUSAGE_DEPTHSTENCIL, MAKEFOURCC('I','N','T','Z'), D3DPOOL_DEFAULT, &texture);
2224     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
2225     hr = IDirect3DDevice8_CreateRenderTarget(device, 640, 480, D3DFMT_A8R8G8B8,
2226             D3DMULTISAMPLE_NONE, FALSE, &rt);
2227     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
2228     hr = IDirect3DDevice8_CreatePixelShader(device, ps_code, &ps);
2229     ok(SUCCEEDED(hr), "CreatePixelShader failed, hr %#x.\n", hr);
2230
2231     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_TEX2
2232             | D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEXCOORDSIZE4(1));
2233     ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
2234     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
2235     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2236     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
2237     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2238     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
2239     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2240     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
2241     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2242
2243     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DTEXF_POINT);
2244     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2245     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
2246     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2247     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
2248     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2249     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
2250     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2251
2252     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
2253     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2254     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
2255     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2256     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_MAGFILTER, D3DTEXF_POINT);
2257     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2258     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_MINFILTER, D3DTEXF_POINT);
2259     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2260     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_MIPFILTER, D3DTEXF_POINT);
2261     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2262     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS,
2263             D3DTTFF_COUNT4 | D3DTTFF_PROJECTED);
2264     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2265
2266     hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &ds);
2267     ok(SUCCEEDED(hr), "GetSurfaceLevel failed, hr %#x.\n", hr);
2268
2269     /* Render offscreen, using the INTZ texture as depth buffer */
2270     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
2271     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2272     hr = IDirect3DDevice8_SetPixelShader(device, 0);
2273     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
2274
2275     /* Setup the depth/stencil surface. */
2276     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
2277     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
2278
2279     hr = IDirect3DDevice8_BeginScene(device);
2280     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2281     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
2282     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2283     hr = IDirect3DDevice8_EndScene(device);
2284     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2285
2286     hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, NULL);
2287     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2288     IDirect3DSurface8_Release(ds);
2289     hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *)texture);
2290     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2291     hr = IDirect3DDevice8_SetTexture(device, 1, (IDirect3DBaseTexture8 *)texture);
2292     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2293     hr = IDirect3DDevice8_SetPixelShader(device, ps);
2294     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
2295
2296     /* Read the depth values back. */
2297     hr = IDirect3DDevice8_BeginScene(device);
2298     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2299     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
2300     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2301     hr = IDirect3DDevice8_EndScene(device);
2302     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2303
2304     for (i = 0; i < sizeof(expected_colors) / sizeof(*expected_colors); ++i)
2305     {
2306         D3DCOLOR color = getPixelColor(device, expected_colors[i].x, expected_colors[i].y);
2307         ok(color_match(color, expected_colors[i].color, 1),
2308                 "Expected color 0x%08x at (%u, %u), got 0x%08x.\n",
2309                 expected_colors[i].color, expected_colors[i].x, expected_colors[i].y, color);
2310     }
2311
2312     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2313     ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
2314
2315     hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
2316     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2317     hr = IDirect3DDevice8_SetTexture(device, 1, NULL);
2318     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2319     IDirect3DTexture8_Release(texture);
2320
2321     /* Render onscreen while using the INTZ texture as depth buffer */
2322     hr = IDirect3DDevice8_CreateTexture(device, 640, 480, 1,
2323             D3DUSAGE_DEPTHSTENCIL, MAKEFOURCC('I','N','T','Z'), D3DPOOL_DEFAULT, &texture);
2324     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
2325     hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &ds);
2326     ok(SUCCEEDED(hr), "GetSurfaceLevel failed, hr %#x.\n", hr);
2327     hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, ds);
2328     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2329     hr = IDirect3DDevice8_SetPixelShader(device, 0);
2330     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
2331
2332     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
2333     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
2334
2335     hr = IDirect3DDevice8_BeginScene(device);
2336     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2337     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
2338     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2339     hr = IDirect3DDevice8_EndScene(device);
2340     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2341
2342     hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, NULL);
2343     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2344     IDirect3DSurface8_Release(ds);
2345     hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *)texture);
2346     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2347     hr = IDirect3DDevice8_SetTexture(device, 1, (IDirect3DBaseTexture8 *)texture);
2348     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2349     hr = IDirect3DDevice8_SetPixelShader(device, ps);
2350     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
2351
2352     /* Read the depth values back. */
2353     hr = IDirect3DDevice8_BeginScene(device);
2354     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2355     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
2356     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2357     hr = IDirect3DDevice8_EndScene(device);
2358     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2359
2360     for (i = 0; i < sizeof(expected_colors) / sizeof(*expected_colors); ++i)
2361     {
2362         D3DCOLOR color = getPixelColor(device, expected_colors[i].x, expected_colors[i].y);
2363         ok(color_match(color, expected_colors[i].color, 1),
2364                 "Expected color 0x%08x at (%u, %u), got 0x%08x.\n",
2365                 expected_colors[i].color, expected_colors[i].x, expected_colors[i].y, color);
2366     }
2367
2368     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2369     ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
2370
2371     hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
2372     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2373     hr = IDirect3DDevice8_SetTexture(device, 1, NULL);
2374     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2375     IDirect3DTexture8_Release(texture);
2376
2377     /* Render offscreen, then onscreen, and finally check the INTZ texture in both areas */
2378     hr = IDirect3DDevice8_CreateTexture(device, 640, 480, 1,
2379             D3DUSAGE_DEPTHSTENCIL, MAKEFOURCC('I','N','T','Z'), D3DPOOL_DEFAULT, &texture);
2380     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
2381     hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &ds);
2382     ok(SUCCEEDED(hr), "GetSurfaceLevel failed, hr %#x.\n", hr);
2383     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
2384     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2385     hr = IDirect3DDevice8_SetPixelShader(device, 0);
2386     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
2387
2388     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
2389     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
2390
2391     hr = IDirect3DDevice8_BeginScene(device);
2392     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2393     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, half_quad_1, sizeof(*half_quad_1));
2394     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2395     hr = IDirect3DDevice8_EndScene(device);
2396     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2397
2398     hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, ds);
2399     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2400
2401     hr = IDirect3DDevice8_BeginScene(device);
2402     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2403     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, half_quad_2, sizeof(*half_quad_2));
2404     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2405     hr = IDirect3DDevice8_EndScene(device);
2406     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2407
2408     hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, NULL);
2409     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2410     IDirect3DSurface8_Release(ds);
2411     hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *)texture);
2412     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2413     hr = IDirect3DDevice8_SetTexture(device, 1, (IDirect3DBaseTexture8 *)texture);
2414     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2415     hr = IDirect3DDevice8_SetPixelShader(device, ps);
2416     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
2417
2418     /* Read the depth values back. */
2419     hr = IDirect3DDevice8_BeginScene(device);
2420     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2421     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
2422     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2423     hr = IDirect3DDevice8_EndScene(device);
2424     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2425
2426     for (i = 0; i < sizeof(expected_colors) / sizeof(*expected_colors); ++i)
2427     {
2428         D3DCOLOR color = getPixelColor(device, expected_colors[i].x, expected_colors[i].y);
2429         ok(color_match(color, expected_colors[i].color, 1),
2430                 "Expected color 0x%08x at (%u, %u), got 0x%08x.\n",
2431                 expected_colors[i].color, expected_colors[i].x, expected_colors[i].y, color);
2432     }
2433
2434     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2435     ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
2436
2437     hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, original_ds);
2438     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2439     IDirect3DSurface8_Release(original_ds);
2440     hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
2441     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2442     hr = IDirect3DDevice8_SetTexture(device, 1, NULL);
2443     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2444     IDirect3DTexture8_Release(texture);
2445     hr = IDirect3DDevice8_SetPixelShader(device, 0);
2446     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
2447     hr = IDirect3DDevice8_DeletePixelShader(device, ps);
2448     ok(SUCCEEDED(hr), "DeletePixelShader failed, hr %#x.\n", hr);
2449
2450     IDirect3DSurface8_Release(original_rt);
2451     IDirect3DSurface8_Release(rt);
2452 }
2453
2454 static void shadow_test(IDirect3DDevice8 *device)
2455 {
2456     static const DWORD ps_code[] =
2457     {
2458         0xffff0101,                                                             /* ps_1_1                       */
2459         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1.0, 0.0, 0.0, 0.0   */
2460         0x00000051, 0xa00f0001, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c1, 0.0, 1.0, 0.0, 0.0   */
2461         0x00000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, /* def c2, 0.0, 0.0, 1.0, 0.0   */
2462         0x00000042, 0xb00f0000,                                                 /* tex t0                       */
2463         0x00000042, 0xb00f0001,                                                 /* tex t1                       */
2464         0x00000008, 0xb0070001, 0xa0e40000, 0xb0e40001,                         /* dp3 t1.xyz, c0, t1           */
2465         0x00000005, 0x80070000, 0xa0e40001, 0xb0e40001,                         /* mul r0.xyz, c1, t1           */
2466         0x00000004, 0x80070000, 0xa0e40000, 0xb0e40000, 0x80e40000,             /* mad r0.xyz, c0, t0, r0       */
2467         0x40000001, 0x80080000, 0xa0aa0002,                                     /* +mov r0.w, c2.z              */
2468         0x0000ffff,                                                             /* end                          */
2469     };
2470     struct
2471     {
2472         D3DFORMAT format;
2473         const char *name;
2474     }
2475     formats[] =
2476     {
2477         {D3DFMT_D16_LOCKABLE,   "D3DFMT_D16_LOCKABLE"},
2478         {D3DFMT_D32,            "D3DFMT_D32"},
2479         {D3DFMT_D15S1,          "D3DFMT_D15S1"},
2480         {D3DFMT_D24S8,          "D3DFMT_D24S8"},
2481         {D3DFMT_D24X8,          "D3DFMT_D24X8"},
2482         {D3DFMT_D24X4S4,        "D3DFMT_D24X4S4"},
2483         {D3DFMT_D16,            "D3DFMT_D16"},
2484     };
2485     struct
2486     {
2487         float x, y, z;
2488         float s0, t0, p0;
2489         float s1, t1, p1, q1;
2490     }
2491     quad[] =
2492     {
2493         { -1.0f,  1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f},
2494         {  1.0f,  1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f},
2495         { -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
2496         {  1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f},
2497     };
2498     struct
2499     {
2500         UINT x, y;
2501         D3DCOLOR color;
2502     }
2503     expected_colors[] =
2504     {
2505         {400,  60, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
2506         {560, 180, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00)},
2507         {560, 300, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00)},
2508         {400, 420, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00)},
2509         {240, 420, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00)},
2510         { 80, 300, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
2511         { 80, 180, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
2512         {240,  60, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
2513     };
2514
2515     IDirect3DSurface8 *original_ds, *original_rt, *rt;
2516     IDirect3D8 *d3d8;
2517     D3DCAPS8 caps;
2518     HRESULT hr;
2519     DWORD ps;
2520     UINT i;
2521
2522     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
2523     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
2524     if (caps.PixelShaderVersion < D3DPS_VERSION(1, 1))
2525     {
2526         skip("No pixel shader 1.1 support, skipping shadow test.\n");
2527         return;
2528     }
2529
2530     hr = IDirect3DDevice8_GetDirect3D(device, &d3d8);
2531     ok(SUCCEEDED(hr), "GetDirect3D failed, hr %#x.\n", hr);
2532     hr = IDirect3DDevice8_GetRenderTarget(device, &original_rt);
2533     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
2534     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &original_ds);
2535     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
2536
2537     hr = IDirect3DDevice8_CreateRenderTarget(device, 1024, 1024, D3DFMT_A8R8G8B8,
2538             D3DMULTISAMPLE_NONE, FALSE, &rt);
2539     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
2540     hr = IDirect3DDevice8_CreatePixelShader(device, ps_code, &ps);
2541     ok(SUCCEEDED(hr), "CreatePixelShader failed, hr %#x.\n", hr);
2542
2543     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_TEX2
2544             | D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEXCOORDSIZE4(1));
2545     ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
2546     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
2547     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2548     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
2549     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2550     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
2551     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2552     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
2553     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2554
2555     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DTEXF_POINT);
2556     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2557     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
2558     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2559     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
2560     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2561     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
2562     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2563
2564     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
2565     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2566     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
2567     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2568     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_MAGFILTER, D3DTEXF_POINT);
2569     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2570     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_MINFILTER, D3DTEXF_POINT);
2571     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2572     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_MIPFILTER, D3DTEXF_POINT);
2573     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2574     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS,
2575             D3DTTFF_COUNT4 | D3DTTFF_PROJECTED);
2576     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2577
2578     for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i)
2579     {
2580         D3DFORMAT format = formats[i].format;
2581         IDirect3DTexture8 *texture;
2582         IDirect3DSurface8 *ds;
2583         unsigned int j;
2584
2585         hr = IDirect3D8_CheckDeviceFormat(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
2586                 D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, format);
2587         if (FAILED(hr)) continue;
2588
2589         hr = IDirect3DDevice8_CreateTexture(device, 1024, 1024, 1,
2590                 D3DUSAGE_DEPTHSTENCIL, format, D3DPOOL_DEFAULT, &texture);
2591         ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
2592
2593         hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &ds);
2594         ok(SUCCEEDED(hr), "GetSurfaceLevel failed, hr %#x.\n", hr);
2595
2596         hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
2597         ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2598
2599         hr = IDirect3DDevice8_SetPixelShader(device, 0);
2600         ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
2601
2602         /* Setup the depth/stencil surface. */
2603         hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
2604         ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
2605
2606         hr = IDirect3DDevice8_BeginScene(device);
2607         ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2608         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
2609         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2610         hr = IDirect3DDevice8_EndScene(device);
2611         ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2612
2613         hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, NULL);
2614         ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2615         IDirect3DSurface8_Release(ds);
2616
2617         hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *)texture);
2618         ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2619         hr = IDirect3DDevice8_SetTexture(device, 1, (IDirect3DBaseTexture8 *)texture);
2620         ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2621
2622         hr = IDirect3DDevice8_SetPixelShader(device, ps);
2623         ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
2624
2625         /* Do the actual shadow mapping. */
2626         hr = IDirect3DDevice8_BeginScene(device);
2627         ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2628         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
2629         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2630         hr = IDirect3DDevice8_EndScene(device);
2631         ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2632
2633         hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
2634         ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2635         hr = IDirect3DDevice8_SetTexture(device, 1, NULL);
2636         ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2637         IDirect3DTexture8_Release(texture);
2638
2639         for (j = 0; j < sizeof(expected_colors) / sizeof(*expected_colors); ++j)
2640         {
2641             D3DCOLOR color = getPixelColor(device, expected_colors[j].x, expected_colors[j].y);
2642             ok(color_match(color, expected_colors[j].color, 0),
2643                     "Expected color 0x%08x at (%u, %u) for format %s, got 0x%08x.\n",
2644                     expected_colors[j].color, expected_colors[j].x, expected_colors[j].y,
2645                     formats[i].name, color);
2646         }
2647
2648         hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2649         ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
2650     }
2651
2652     hr = IDirect3DDevice8_SetPixelShader(device, 0);
2653     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
2654     hr = IDirect3DDevice8_DeletePixelShader(device, ps);
2655     ok(SUCCEEDED(hr), "DeletePixelShader failed, hr %#x.\n", hr);
2656
2657     hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, original_ds);
2658     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2659     IDirect3DSurface8_Release(original_ds);
2660
2661     IDirect3DSurface8_Release(original_rt);
2662     IDirect3DSurface8_Release(rt);
2663
2664     IDirect3D8_Release(d3d8);
2665 }
2666
2667 static void multisample_copy_rects_test(IDirect3DDevice8 *device)
2668 {
2669     IDirect3DSurface8 *original_ds, *original_rt, *ds, *ds_plain, *rt, *readback;
2670     RECT src_rect = {64, 64, 128, 128};
2671     POINT dst_point = {96, 96};
2672     D3DLOCKED_RECT locked_rect;
2673     IDirect3D8 *d3d8;
2674     D3DCOLOR color;
2675     HRESULT hr;
2676
2677     hr = IDirect3DDevice8_GetDirect3D(device, &d3d8);
2678     ok(SUCCEEDED(hr), "Failed to get d3d8 interface, hr %#x.\n", hr);
2679     hr = IDirect3D8_CheckDeviceMultiSampleType(d3d8, D3DADAPTER_DEFAULT,
2680             D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES);
2681     IDirect3D8_Release(d3d8);
2682     if (FAILED(hr))
2683     {
2684         skip("Multisampling not supported for D3DFMT_A8R8G8B8, skipping multisampled CopyRects test.\n");
2685         return;
2686     }
2687
2688     hr = IDirect3DDevice8_CreateRenderTarget(device, 256, 256, D3DFMT_A8R8G8B8,
2689             D3DMULTISAMPLE_2_SAMPLES, FALSE, &rt);
2690     ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2691     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 256, 256, D3DFMT_D24S8,
2692             D3DMULTISAMPLE_2_SAMPLES, &ds);
2693     ok(SUCCEEDED(hr), "Failed to create depth stencil surface, hr %#x.\n", hr);
2694     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 256, 256, D3DFMT_D24S8,
2695             D3DMULTISAMPLE_NONE, &ds_plain);
2696     ok(SUCCEEDED(hr), "Failed to create depth stencil surface, hr %#x.\n", hr);
2697     hr = IDirect3DDevice8_CreateImageSurface(device, 256, 256, D3DFMT_A8R8G8B8, &readback);
2698     ok(SUCCEEDED(hr), "Failed to create readback surface, hr %#x.\n", hr);
2699
2700     hr = IDirect3DDevice8_GetRenderTarget(device, &original_rt);
2701     ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
2702     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &original_ds);
2703     ok(SUCCEEDED(hr), "Failed to get depth/stencil, hr %#x.\n", hr);
2704
2705     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
2706     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
2707
2708     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ff00, 1.0f, 0);
2709     ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
2710
2711     hr = IDirect3DDevice8_CopyRects(device, rt, NULL, 0, readback, NULL);
2712     ok(SUCCEEDED(hr), "Failed to read render target back, hr %#x.\n", hr);
2713
2714     hr = IDirect3DDevice8_CopyRects(device, ds, NULL, 0, ds_plain, NULL);
2715     ok(hr == D3DERR_INVALIDCALL, "Depth buffer copy, hr %#x, expected %#x.\n", hr, D3DERR_INVALIDCALL);
2716
2717     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
2718     ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
2719
2720     hr = IDirect3DDevice8_CopyRects(device, rt, &src_rect, 1, readback, &dst_point);
2721     ok(SUCCEEDED(hr), "Failed to read render target back, hr %#x.\n", hr);
2722
2723     hr = IDirect3DSurface8_LockRect(readback, &locked_rect, NULL, D3DLOCK_READONLY);
2724     ok(SUCCEEDED(hr), "Failed to lock readback surface, hr %#x.\n", hr);
2725
2726     color = *(DWORD *)((BYTE *)locked_rect.pBits + 31 * locked_rect.Pitch + 31 * 4);
2727     ok(color == 0xff00ff00, "Got unexpected color 0x%08x.\n", color);
2728
2729     color = *(DWORD *)((BYTE *)locked_rect.pBits + 127 * locked_rect.Pitch + 127 * 4);
2730     ok(color == 0xffff0000, "Got unexpected color 0x%08x.\n", color);
2731
2732     hr = IDirect3DSurface8_UnlockRect(readback);
2733     ok(SUCCEEDED(hr), "Failed to unlock readback surface, hr %#x.\n", hr);
2734
2735     hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, original_ds);
2736     ok(SUCCEEDED(hr), "Failed to restore original render target, hr %#x.\n", hr);
2737
2738     IDirect3DSurface8_Release(original_ds);
2739     IDirect3DSurface8_Release(original_rt);
2740     IDirect3DSurface8_Release(readback);
2741     IDirect3DSurface8_Release(ds_plain);
2742     IDirect3DSurface8_Release(ds);
2743     IDirect3DSurface8_Release(rt);
2744 }
2745
2746 static void resz_test(IDirect3DDevice8 *device)
2747 {
2748     IDirect3DSurface8 *rt, *original_rt, *ds, *original_ds, *intz_ds;
2749     IDirect3D8 *d3d8;
2750     D3DCAPS8 caps;
2751     HRESULT hr;
2752     unsigned int i;
2753     static const DWORD ps_code[] =
2754     {
2755         0xffff0101,                                                             /* ps_1_1                       */
2756         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1.0, 0.0, 0.0, 0.0   */
2757         0x00000051, 0xa00f0001, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c1, 0.0, 1.0, 0.0, 0.0   */
2758         0x00000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, /* def c2, 0.0, 0.0, 1.0, 0.0   */
2759         0x00000042, 0xb00f0000,                                                 /* tex t0                       */
2760         0x00000042, 0xb00f0001,                                                 /* tex t1                       */
2761         0x00000008, 0xb0070001, 0xa0e40000, 0xb0e40001,                         /* dp3 t1.xyz, c0, t1           */
2762         0x00000005, 0x80070000, 0xa0e40001, 0xb0e40001,                         /* mul r0.xyz, c1, t1           */
2763         0x00000004, 0x80070000, 0xa0e40000, 0xb0e40000, 0x80e40000,             /* mad r0.xyz, c0, t0, r0       */
2764         0x40000001, 0x80080000, 0xa0aa0002,                                     /* +mov r0.w, c2.z              */
2765         0x0000ffff,                                                             /* end                          */
2766     };
2767     struct
2768     {
2769         float x, y, z;
2770         float s0, t0, p0;
2771         float s1, t1, p1, q1;
2772     }
2773     quad[] =
2774     {
2775         { -1.0f,  1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.5f},
2776         {  1.0f,  1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.5f},
2777         { -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f},
2778         {  1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.5f},
2779     };
2780     struct
2781     {
2782         UINT x, y;
2783         D3DCOLOR color;
2784     }
2785     expected_colors[] =
2786     {
2787         { 80, 100, D3DCOLOR_ARGB(0x00, 0x20, 0x40, 0x00)},
2788         {240, 100, D3DCOLOR_ARGB(0x00, 0x60, 0xbf, 0x00)},
2789         {400, 100, D3DCOLOR_ARGB(0x00, 0x9f, 0x40, 0x00)},
2790         {560, 100, D3DCOLOR_ARGB(0x00, 0xdf, 0xbf, 0x00)},
2791         { 80, 450, D3DCOLOR_ARGB(0x00, 0x20, 0x40, 0x00)},
2792         {240, 450, D3DCOLOR_ARGB(0x00, 0x60, 0xbf, 0x00)},
2793         {400, 450, D3DCOLOR_ARGB(0x00, 0x9f, 0x40, 0x00)},
2794         {560, 450, D3DCOLOR_ARGB(0x00, 0xdf, 0xbf, 0x00)},
2795     };
2796     IDirect3DTexture8 *texture;
2797     DWORD ps, value;
2798
2799     hr = IDirect3DDevice8_GetDirect3D(device, &d3d8);
2800     ok(SUCCEEDED(hr), "Failed to get d3d8 interface, hr %#x.\n", hr);
2801     hr = IDirect3D8_CheckDeviceMultiSampleType(d3d8, D3DADAPTER_DEFAULT,
2802             D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES);
2803     if (FAILED(hr))
2804     {
2805         skip("Multisampling not supported for D3DFMT_A8R8G8B8, skipping RESZ test.\n");
2806         return;
2807     }
2808     hr = IDirect3D8_CheckDeviceMultiSampleType(d3d8, D3DADAPTER_DEFAULT,
2809             D3DDEVTYPE_HAL, D3DFMT_D24S8, TRUE, D3DMULTISAMPLE_2_SAMPLES);
2810     if (FAILED(hr))
2811     {
2812         skip("Multisampling not supported for D3DFMT_D24S8, skipping RESZ test.\n");
2813         return;
2814     }
2815     hr = IDirect3D8_CheckDeviceFormat(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
2816             D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, MAKEFOURCC('I','N','T','Z'));
2817     if (FAILED(hr))
2818     {
2819         skip("No INTZ support, skipping RESZ test.\n");
2820         return;
2821     }
2822     hr = IDirect3D8_CheckDeviceFormat(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
2823             D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, MAKEFOURCC('R','E','S','Z'));
2824     if (FAILED(hr))
2825     {
2826         skip("No RESZ support, skipping RESZ test.\n");
2827         return;
2828     }
2829     IDirect3D8_Release(d3d8);
2830
2831     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
2832     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
2833     if (caps.TextureCaps & D3DPTEXTURECAPS_POW2)
2834     {
2835         skip("No unconditional NP2 texture support, skipping INTZ test.\n");
2836         return;
2837     }
2838
2839     hr = IDirect3DDevice8_GetRenderTarget(device, &original_rt);
2840     ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
2841     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &original_ds);
2842     ok(SUCCEEDED(hr), "Failed to get depth/stencil, hr %#x.\n", hr);
2843
2844     hr = IDirect3DDevice8_CreateRenderTarget(device, 640, 480, D3DFMT_A8R8G8B8,
2845             D3DMULTISAMPLE_2_SAMPLES, FALSE, &rt);
2846     ok(SUCCEEDED(hr), "Failed to create render target, hr %#x.\n", hr);
2847     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8,
2848             D3DMULTISAMPLE_2_SAMPLES, &ds);
2849
2850     hr = IDirect3DDevice8_CreateTexture(device, 640, 480, 1,
2851             D3DUSAGE_DEPTHSTENCIL, MAKEFOURCC('I','N','T','Z'), D3DPOOL_DEFAULT, &texture);
2852     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
2853     hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &intz_ds);
2854     ok(SUCCEEDED(hr), "GetSurfaceLevel failed, hr %#x.\n", hr);
2855
2856     hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, intz_ds);
2857     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
2858     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ffff, 1.0f, 0);
2859     ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
2860
2861     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
2862     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
2863     IDirect3DSurface8_Release(intz_ds);
2864     hr = IDirect3DDevice8_CreatePixelShader(device, ps_code, &ps);
2865     ok(SUCCEEDED(hr), "CreatePixelShader failed, hr %#x.\n", hr);
2866
2867     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_TEX2
2868             | D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEXCOORDSIZE4(1));
2869     ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
2870     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
2871     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2872     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
2873     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2874     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
2875     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2876     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
2877     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2878
2879     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DTEXF_POINT);
2880     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2881     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
2882     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2883     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
2884     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2885     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
2886     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2887
2888     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
2889     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2890     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
2891     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2892     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_MAGFILTER, D3DTEXF_POINT);
2893     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2894     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_MINFILTER, D3DTEXF_POINT);
2895     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2896     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_MIPFILTER, D3DTEXF_POINT);
2897     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2898     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS,
2899             D3DTTFF_COUNT4 | D3DTTFF_PROJECTED);
2900     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
2901
2902     /* Render offscreen (multisampled), blit the depth buffer into the INTZ texture and then check its contents. */
2903     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ff00, 1.0f, 0);
2904     ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
2905
2906     hr = IDirect3DDevice8_BeginScene(device);
2907     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2908     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
2909     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2910
2911     /* The destination depth texture has to be bound to sampler 0 */
2912     hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *)texture);
2913     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2914
2915     /* the ATI "spec" says you have to do a dummy draw to ensure correct commands ordering */
2916     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, FALSE);
2917     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2918     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
2919     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2920     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_COLORWRITEENABLE, 0);
2921     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2922     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
2923     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2924     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, TRUE);
2925     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2926     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
2927     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2928     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_COLORWRITEENABLE, 0xf);
2929     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2930
2931     /* The actual multisampled depth buffer resolve happens here */
2932     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE, 0x7fa05000);
2933     ok(SUCCEEDED(hr), "SetRenderState (multisampled depth buffer resolve) failed, hr %#x.\n", hr);
2934     hr = IDirect3DDevice8_GetRenderState(device, D3DRS_POINTSIZE, &value);
2935     ok(SUCCEEDED(hr) && value == 0x7fa05000, "GetRenderState failed, hr %#x, value %#x.\n", hr, value);
2936
2937     hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, NULL);
2938     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
2939     hr = IDirect3DDevice8_SetTexture(device, 1, (IDirect3DBaseTexture8 *)texture);
2940     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2941     hr = IDirect3DDevice8_SetPixelShader(device, ps);
2942     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
2943
2944     /* Read the depth values back. */
2945     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
2946     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2947     hr = IDirect3DDevice8_EndScene(device);
2948     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2949
2950     for (i = 0; i < sizeof(expected_colors) / sizeof(*expected_colors); ++i)
2951     {
2952         D3DCOLOR color = getPixelColor(device, expected_colors[i].x, expected_colors[i].y);
2953         ok(color_match(color, expected_colors[i].color, 1),
2954                 "Expected color 0x%08x at (%u, %u), got 0x%08x.\n",
2955                 expected_colors[i].color, expected_colors[i].x, expected_colors[i].y, color);
2956     }
2957
2958     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2959     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
2960
2961     /* Test edge cases - try with no texture at all */
2962     hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
2963     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2964     hr = IDirect3DDevice8_SetTexture(device, 1, NULL);
2965     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2966     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
2967     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
2968
2969     hr = IDirect3DDevice8_BeginScene(device);
2970     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2971     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
2972     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2973     hr = IDirect3DDevice8_EndScene(device);
2974     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2975
2976     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE, 0x7fa05000);
2977     ok(SUCCEEDED(hr), "SetRenderState (multisampled depth buffer resolve) failed, hr %#x.\n", hr);
2978
2979     /* With a non-multisampled depth buffer */
2980     IDirect3DSurface8_Release(ds);
2981     IDirect3DSurface8_Release(rt);
2982     hr = IDirect3DDevice8_CreateDepthStencilSurface(device, 640, 480, D3DFMT_D24S8,
2983             D3DMULTISAMPLE_NONE, &ds);
2984
2985     hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, ds);
2986     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
2987     hr = IDirect3DDevice8_SetPixelShader(device, 0);
2988     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
2989
2990     hr = IDirect3DDevice8_BeginScene(device);
2991     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2992     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
2993     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2994     hr = IDirect3DDevice8_EndScene(device);
2995     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2996
2997     hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *)texture);
2998     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2999
3000     hr = IDirect3DDevice8_BeginScene(device);
3001     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
3002     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, FALSE);
3003     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
3004     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
3005     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
3006     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_COLORWRITEENABLE, 0);
3007     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
3008     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
3009     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
3010     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, TRUE);
3011     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
3012     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
3013     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
3014     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_COLORWRITEENABLE, 0xf);
3015     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
3016     hr = IDirect3DDevice8_EndScene(device);
3017     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
3018
3019     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_POINTSIZE, 0x7fa05000);
3020     ok(SUCCEEDED(hr), "SetRenderState (multisampled depth buffer resolve) failed, hr %#x.\n", hr);
3021
3022     hr = IDirect3DDevice8_SetTexture(device, 1, (IDirect3DBaseTexture8 *)texture);
3023     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
3024     hr = IDirect3DDevice8_SetPixelShader(device, ps);
3025     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
3026
3027     /* Read the depth values back. */
3028     hr = IDirect3DDevice8_BeginScene(device);
3029     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
3030     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
3031     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
3032     hr = IDirect3DDevice8_EndScene(device);
3033     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
3034
3035     for (i = 0; i < sizeof(expected_colors) / sizeof(*expected_colors); ++i)
3036     {
3037         D3DCOLOR color = getPixelColor(device, expected_colors[i].x, expected_colors[i].y);
3038         ok(color_match(color, expected_colors[i].color, 1),
3039                 "Expected color 0x%08x at (%u, %u), got 0x%08x.\n",
3040                 expected_colors[i].color, expected_colors[i].x, expected_colors[i].y, color);
3041     }
3042
3043     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
3044     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
3045
3046     hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, original_ds);
3047     ok(SUCCEEDED(hr), "Failed to set render target, hr %#x.\n", hr);
3048     IDirect3DSurface8_Release(ds);
3049     hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
3050     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
3051     hr = IDirect3DDevice8_SetTexture(device, 1, NULL);
3052     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
3053     IDirect3DTexture8_Release(texture);
3054     hr = IDirect3DDevice8_SetPixelShader(device, 0);
3055     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
3056     hr = IDirect3DDevice8_DeletePixelShader(device, ps);
3057     ok(SUCCEEDED(hr), "DeletePixelShader failed, hr %#x.\n", hr);
3058     IDirect3DSurface8_Release(original_ds);
3059     IDirect3DSurface8_Release(original_rt);
3060 }
3061
3062 static void zenable_test(IDirect3DDevice8 *device)
3063 {
3064     static const struct
3065     {
3066         struct vec4 position;
3067         D3DCOLOR diffuse;
3068     }
3069     tquad[] =
3070     {
3071         {{  0.0f, 480.0f, -0.5f, 1.0f}, 0xff00ff00},
3072         {{  0.0f,   0.0f, -0.5f, 1.0f}, 0xff00ff00},
3073         {{640.0f, 480.0f,  1.5f, 1.0f}, 0xff00ff00},
3074         {{640.0f,   0.0f,  1.5f, 1.0f}, 0xff00ff00},
3075     };
3076     D3DCOLOR color;
3077     D3DCAPS8 caps;
3078     HRESULT hr;
3079     UINT x, y;
3080     UINT i, j;
3081
3082     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
3083     ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
3084     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
3085     ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
3086
3087     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
3088     ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3089     hr = IDirect3DDevice8_BeginScene(device);
3090     ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3091     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, tquad, sizeof(*tquad));
3092     ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3093     hr = IDirect3DDevice8_EndScene(device);
3094     ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3095
3096     for (i = 0; i < 4; ++i)
3097     {
3098         for (j = 0; j < 4; ++j)
3099         {
3100             x = 80 * ((2 * j) + 1);
3101             y = 60 * ((2 * i) + 1);
3102             color = getPixelColor(device, x, y);
3103             ok(color_match(color, 0x0000ff00, 1),
3104                     "Expected color 0x0000ff00 at %u, %u, got 0x%08x.\n", x, y, color);
3105         }
3106     }
3107
3108     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
3109     ok(SUCCEEDED(hr), "Failed to present backbuffer, hr %#x.\n", hr);
3110
3111     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
3112     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
3113
3114     if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 1)
3115             && caps.VertexShaderVersion >= D3DVS_VERSION(1, 1))
3116     {
3117         static const DWORD vs_code[] =
3118         {
3119             0xfffe0101,                                 /* vs_1_1           */
3120             0x00000001, 0xc00f0000, 0x90e40000,         /* mov oPos, v0     */
3121             0x00000001, 0xd00f0000, 0x90e40000,         /* mov oD0, v0      */
3122             0x0000ffff
3123         };
3124         static const DWORD ps_code[] =
3125         {
3126             0xffff0101,                                 /* ps_1_1           */
3127             0x00000001, 0x800f0000, 0x90e40000,         /* mov r0, v0       */
3128             0x0000ffff                                  /* end              */
3129         };
3130         static const struct vec3 quad[] =
3131         {
3132             {-1.0f, -1.0f, -0.5f},
3133             {-1.0f,  1.0f, -0.5f},
3134             { 1.0f, -1.0f,  1.5f},
3135             { 1.0f,  1.0f,  1.5f},
3136         };
3137         static const D3DCOLOR expected[] =
3138         {
3139             0x00ff0000, 0x0060df60, 0x009fdf9f, 0x00ff0000,
3140             0x00ff0000, 0x00609f60, 0x009f9f9f, 0x00ff0000,
3141             0x00ff0000, 0x00606060, 0x009f609f, 0x00ff0000,
3142             0x00ff0000, 0x00602060, 0x009f209f, 0x00ff0000,
3143         };
3144         static const DWORD decl[] =
3145         {
3146             D3DVSD_STREAM(0),
3147             D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),
3148             D3DVSD_END()
3149         };
3150         DWORD vs, ps;
3151
3152         hr = IDirect3DDevice8_CreateVertexShader(device, decl, vs_code, &vs, 0);
3153         ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr);
3154         hr = IDirect3DDevice8_CreatePixelShader(device, ps_code, &ps);
3155         ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr);
3156         hr = IDirect3DDevice8_SetVertexShader(device, vs);
3157         ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
3158         hr = IDirect3DDevice8_SetPixelShader(device, ps);
3159         ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
3160
3161         hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffff0000, 0.0f, 0);
3162         ok(SUCCEEDED(hr), "Failed to clear render target, hr %#x.\n", hr);
3163         hr = IDirect3DDevice8_BeginScene(device);
3164         ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
3165         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
3166         ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
3167         hr = IDirect3DDevice8_EndScene(device);
3168         ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
3169
3170         for (i = 0; i < 4; ++i)
3171         {
3172             for (j = 0; j < 4; ++j)
3173             {
3174                 x = 80 * ((2 * j) + 1);
3175                 y = 60 * ((2 * i) + 1);
3176                 color = getPixelColor(device, x, y);
3177                 ok(color_match(color, expected[i * 4 + j], 1),
3178                         "Expected color 0x%08x at %u, %u, got 0x%08x.\n", expected[i * 4 + j], x, y, color);
3179             }
3180         }
3181
3182         hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
3183         ok(SUCCEEDED(hr), "Failed to present backbuffer, hr %#x.\n", hr);
3184
3185         hr = IDirect3DDevice8_SetPixelShader(device, 0);
3186         ok(SUCCEEDED(hr), "Failed to set pixel shader, hr %#x.\n", hr);
3187         hr = IDirect3DDevice8_SetVertexShader(device, 0);
3188         ok(SUCCEEDED(hr), "Failed to set vertex shader, hr %#x.\n", hr);
3189         hr = IDirect3DDevice8_DeletePixelShader(device, ps);
3190         ok(SUCCEEDED(hr), "Failed to delete pixel shader, hr %#x.\n", hr);
3191         hr = IDirect3DDevice8_DeleteVertexShader(device, vs);
3192         ok(SUCCEEDED(hr), "Failed to delete vertex shader, hr %#x.\n", hr);
3193     }
3194 }
3195
3196 START_TEST(visual)
3197 {
3198     IDirect3DDevice8 *device_ptr;
3199     HRESULT hr;
3200     DWORD color;
3201     D3DCAPS8 caps;
3202
3203     d3d8_handle = LoadLibraryA("d3d8.dll");
3204     if (!d3d8_handle)
3205     {
3206         win_skip("Could not load d3d8.dll\n");
3207         return;
3208     }
3209
3210     device_ptr = init_d3d8();
3211     if (!device_ptr)
3212     {
3213         win_skip("Could not initialize direct3d\n");
3214         return;
3215     }
3216
3217     IDirect3DDevice8_GetDeviceCaps(device_ptr, &caps);
3218
3219     /* Check for the reliability of the returned data */
3220     hr = IDirect3DDevice8_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
3221     if(FAILED(hr))
3222     {
3223         skip("Clear failed, can't assure correctness of the test results\n");
3224         goto cleanup;
3225     }
3226
3227     color = getPixelColor(device_ptr, 1, 1);
3228     if(color !=0x00ff0000)
3229     {
3230         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests\n", color);
3231         goto cleanup;
3232     }
3233     IDirect3DDevice8_Present(device_ptr, NULL, NULL, NULL, NULL);
3234
3235     hr = IDirect3DDevice8_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xff00ddee, 0.0, 0);
3236     if(FAILED(hr))
3237     {
3238         skip("Clear failed, can't assure correctness of the test results\n");
3239         goto cleanup;
3240     }
3241
3242     color = getPixelColor(device_ptr, 639, 479);
3243     if(color != 0x0000ddee)
3244     {
3245         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests\n", color);
3246         goto cleanup;
3247     }
3248     IDirect3DDevice8_Present(device_ptr, NULL, NULL, NULL, NULL);
3249
3250     /* Now run the real test */
3251     depth_clamp_test(device_ptr);
3252     lighting_test(device_ptr);
3253     clear_test(device_ptr);
3254     fog_test(device_ptr);
3255     present_test(device_ptr);
3256     offscreen_test(device_ptr);
3257     alpha_test(device_ptr);
3258
3259     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1))
3260     {
3261         test_rcp_rsq(device_ptr);
3262         if (caps.PixelShaderVersion >= D3DPS_VERSION(1, 1))
3263             fog_with_shader_test(device_ptr);
3264     }
3265     else
3266     {
3267         skip("No vs.1.1 support\n");
3268     }
3269
3270     p8_texture_test(device_ptr);
3271     texop_test(device_ptr);
3272     depth_buffer_test(device_ptr);
3273     depth_buffer2_test(device_ptr);
3274     intz_test(device_ptr);
3275     shadow_test(device_ptr);
3276     multisample_copy_rects_test(device_ptr);
3277     zenable_test(device_ptr);
3278     resz_test(device_ptr);
3279
3280 cleanup:
3281     if(device_ptr) {
3282         D3DDEVICE_CREATION_PARAMETERS creation_parameters;
3283         ULONG refcount;
3284
3285         IDirect3DDevice8_GetCreationParameters(device_ptr, &creation_parameters);
3286         DestroyWindow(creation_parameters.hFocusWindow);
3287         refcount = IDirect3DDevice8_Release(device_ptr);
3288         ok(!refcount, "Device has %u references left\n", refcount);
3289     }
3290 }