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