d3d8/tests: Fix the depth clamping test.
[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 static HWND create_window(void)
29 {
30     WNDCLASS wc = {0};
31     HWND ret;
32     wc.lpfnWndProc = DefWindowProc;
33     wc.lpszClassName = "d3d8_test_wc";
34     RegisterClass(&wc);
35
36     ret = CreateWindow("d3d8_test_wc", "d3d8_test",
37                        WS_POPUP | WS_SYSMENU , 20, 20, 640, 480, 0, 0, 0, 0);
38     ShowWindow(ret, SW_SHOW);
39     return ret;
40 }
41
42 static BOOL color_match(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
43 {
44     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
45     c1 >>= 8; c2 >>= 8;
46     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
47     c1 >>= 8; c2 >>= 8;
48     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
49     c1 >>= 8; c2 >>= 8;
50     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
51     return TRUE;
52 }
53
54 static DWORD getPixelColor(IDirect3DDevice8 *device, UINT x, UINT y)
55 {
56     DWORD ret;
57     IDirect3DTexture8 *tex = NULL;
58     IDirect3DSurface8 *surf = NULL, *backbuf = NULL;
59     HRESULT hr;
60     D3DLOCKED_RECT lockedRect;
61     RECT rectToLock = {x, y, x+1, y+1};
62
63     hr = IDirect3DDevice8_CreateTexture(device, 640, 480, 1 /* Levels */, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &tex);
64     if(FAILED(hr) || !tex )  /* This is not a test */
65     {
66         trace("Can't create an offscreen plain surface to read the render target data, hr=%#08x\n", hr);
67         return 0xdeadbeef;
68     }
69     hr = IDirect3DTexture8_GetSurfaceLevel(tex, 0, &surf);
70     if(FAILED(hr) || !tex )  /* This is not a test */
71     {
72         trace("Can't get surface from texture, hr=%#08x\n", hr);
73         ret = 0xdeadbeee;
74         goto out;
75     }
76
77     hr = IDirect3DDevice8_GetRenderTarget(device, &backbuf);
78     if(FAILED(hr))
79     {
80         trace("Can't get the render target, hr=%#08x\n", hr);
81         ret = 0xdeadbeed;
82         goto out;
83     }
84     hr = IDirect3DDevice8_CopyRects(device, backbuf, NULL, 0, surf, NULL);
85     if(FAILED(hr))
86     {
87         trace("Can't read the render target, hr=%#08x\n", hr);
88         ret = 0xdeadbeec;
89         goto out;
90     }
91
92     hr = IDirect3DSurface8_LockRect(surf, &lockedRect, &rectToLock, D3DLOCK_READONLY);
93     if(FAILED(hr))
94     {
95         trace("Can't lock the offscreen surface, hr=%#08x\n", hr);
96         ret = 0xdeadbeeb;
97         goto out;
98     }
99     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
100      * really important for these tests
101      */
102     ret = ((DWORD *) lockedRect.pBits)[0] & 0x00ffffff;
103     hr = IDirect3DSurface8_UnlockRect(surf);
104     if(FAILED(hr))
105     {
106         trace("Can't unlock the offscreen surface, hr=%#08x\n", hr);
107     }
108
109 out:
110     if(backbuf) IDirect3DSurface8_Release(backbuf);
111     if(surf) IDirect3DSurface8_Release(surf);
112     if(tex) IDirect3DTexture8_Release(tex);
113     return ret;
114 }
115
116 static IDirect3DDevice8 *init_d3d8(void)
117 {
118     IDirect3D8 * (__stdcall * d3d8_create)(UINT SDKVersion) = 0;
119     IDirect3D8 *d3d8_ptr = 0;
120     IDirect3DDevice8 *device_ptr = 0;
121     D3DPRESENT_PARAMETERS present_parameters;
122     HRESULT hr;
123
124     d3d8_create = (void *)GetProcAddress(d3d8_handle, "Direct3DCreate8");
125     ok(d3d8_create != NULL, "Failed to get address of Direct3DCreate8\n");
126     if (!d3d8_create) return NULL;
127
128     d3d8_ptr = d3d8_create(D3D_SDK_VERSION);
129     if (!d3d8_ptr)
130     {
131         skip("could not create D3D8\n");
132         return NULL;
133     }
134
135     ZeroMemory(&present_parameters, sizeof(present_parameters));
136     present_parameters.Windowed = TRUE;
137     present_parameters.hDeviceWindow = create_window();
138     present_parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
139     present_parameters.BackBufferWidth = 640;
140     present_parameters.BackBufferHeight = 480;
141     present_parameters.BackBufferFormat = D3DFMT_A8R8G8B8;
142     present_parameters.EnableAutoDepthStencil = TRUE;
143     present_parameters.AutoDepthStencilFormat = D3DFMT_D24S8;
144
145     hr = IDirect3D8_CreateDevice(d3d8_ptr, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL,
146             present_parameters.hDeviceWindow, D3DCREATE_HARDWARE_VERTEXPROCESSING, &present_parameters, &device_ptr);
147     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL || broken(hr == D3DERR_NOTAVAILABLE), "IDirect3D_CreateDevice returned: %#08x\n", hr);
148
149     return device_ptr;
150 }
151
152 struct vertex
153 {
154     float x, y, z;
155     DWORD diffuse;
156 };
157
158 struct tvertex
159 {
160     float x, y, z, w;
161     DWORD diffuse;
162 };
163
164 struct nvertex
165 {
166     float x, y, z;
167     float nx, ny, nz;
168     DWORD diffuse;
169 };
170
171 static void lighting_test(IDirect3DDevice8 *device)
172 {
173     HRESULT hr;
174     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
175     DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
176     DWORD color;
177
178     float mat[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
179                       0.0f, 1.0f, 0.0f, 0.0f,
180                       0.0f, 0.0f, 1.0f, 0.0f,
181                       0.0f, 0.0f, 0.0f, 1.0f };
182
183     struct vertex unlitquad[] =
184     {
185         {-1.0f, -1.0f,   0.1f,                          0xffff0000},
186         {-1.0f,  0.0f,   0.1f,                          0xffff0000},
187         { 0.0f,  0.0f,   0.1f,                          0xffff0000},
188         { 0.0f, -1.0f,   0.1f,                          0xffff0000},
189     };
190     struct vertex litquad[] =
191     {
192         {-1.0f,  0.0f,   0.1f,                          0xff00ff00},
193         {-1.0f,  1.0f,   0.1f,                          0xff00ff00},
194         { 0.0f,  1.0f,   0.1f,                          0xff00ff00},
195         { 0.0f,  0.0f,   0.1f,                          0xff00ff00},
196     };
197     struct nvertex unlitnquad[] =
198     {
199         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
200         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
201         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
202         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
203     };
204     struct nvertex litnquad[] =
205     {
206         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
207         { 0.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
208         { 1.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
209         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
210     };
211     WORD Indices[] = {0, 1, 2, 2, 3, 0};
212
213     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
214     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %#08x\n", hr);
215
216     /* Setup some states that may cause issues */
217     hr = IDirect3DDevice8_SetTransform(device, D3DTS_WORLDMATRIX(0), (D3DMATRIX *) mat);
218     ok(hr == D3D_OK, "IDirect3DDevice8_SetTransform returned %#08x\n", hr);
219     hr = IDirect3DDevice8_SetTransform(device, D3DTS_VIEW, (D3DMATRIX *)mat);
220     ok(hr == D3D_OK, "IDirect3DDevice8_SetTransform returned %#08x\n", hr);
221     hr = IDirect3DDevice8_SetTransform(device, D3DTS_PROJECTION, (D3DMATRIX *) mat);
222     ok(hr == D3D_OK, "IDirect3DDevice8_SetTransform returned %#08x\n", hr);
223     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPING, FALSE);
224     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
225     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, FALSE);
226     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
227     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
228     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
229     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_STENCILENABLE, FALSE);
230     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
231     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHATESTENABLE, FALSE);
232     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
233     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
234     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
235     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CULLMODE, D3DCULL_NONE);
236     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed with %#08x\n", hr);
237     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE);
238     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed with %#08x\n", hr);
239
240     hr = IDirect3DDevice8_SetVertexShader(device, fvf);
241     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
242
243     hr = IDirect3DDevice8_BeginScene(device);
244     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %#08x\n", hr);
245     if(hr == D3D_OK)
246     {
247         /* No lights are defined... That means, lit vertices should be entirely black */
248         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
249         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
250         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
251                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitquad, sizeof(unlitquad[0]));
252         ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %#08x\n", hr);
253
254         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, TRUE);
255         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
256         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
257                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litquad, sizeof(litquad[0]));
258         ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %#08x\n", hr);
259
260         hr = IDirect3DDevice8_SetVertexShader(device, nfvf);
261         ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader failed with %#08x\n", hr);
262
263         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
264         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
265         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
266                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unlitnquad, sizeof(unlitnquad[0]));
267         ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %#08x\n", hr);
268
269         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, TRUE);
270         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
271         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
272                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, litnquad, sizeof(litnquad[0]));
273         ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %#08x\n", hr);
274
275         IDirect3DDevice8_EndScene(device);
276         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %#08x\n", hr);
277     }
278
279     color = getPixelColor(device, 160, 360); /* Lower left quad - unlit without normals */
280     ok(color == 0x00ff0000, "Unlit quad without normals has color 0x%08x, expected 0x00ff0000.\n", color);
281     color = getPixelColor(device, 160, 120); /* Upper left quad - lit without normals */
282     ok(color == 0x00000000, "Lit quad without normals has color 0x%08x, expected 0x00000000.\n", color);
283     color = getPixelColor(device, 480, 360); /* Lower right quad - unlit with normals */
284     ok(color == 0x000000ff, "Unlit quad with normals has color 0x%08x, expected 0x000000ff.\n", color);
285     color = getPixelColor(device, 480, 120); /* Upper right quad - lit with normals */
286     ok(color == 0x00000000, "Lit quad with normals has color 0x%08x, expected 0x00000000.\n", color);
287
288     IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
289
290     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
291     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %#08x\n", hr);
292 }
293
294 static void clear_test(IDirect3DDevice8 *device)
295 {
296     /* Tests the correctness of clearing parameters */
297     HRESULT hr;
298     D3DRECT rect[2];
299     D3DRECT rect_negneg;
300     DWORD color;
301
302     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
303     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %#08x\n", hr);
304
305     /* Positive x, negative y */
306     rect[0].x1 = 0;
307     rect[0].y1 = 480;
308     rect[0].x2 = 320;
309     rect[0].y2 = 240;
310
311     /* Positive x, positive y */
312     rect[1].x1 = 0;
313     rect[1].y1 = 0;
314     rect[1].x2 = 320;
315     rect[1].y2 = 240;
316     /* Clear 2 rectangles with one call. Shows that a positive value is returned, but the negative rectangle
317      * is ignored, the positive is still cleared afterwards
318      */
319     hr = IDirect3DDevice8_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
320     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %#08x\n", hr);
321
322     /* negative x, negative y */
323     rect_negneg.x1 = 640;
324     rect_negneg.y1 = 240;
325     rect_negneg.x2 = 320;
326     rect_negneg.y2 = 0;
327     hr = IDirect3DDevice8_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
328     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %#08x\n", hr);
329
330     color = getPixelColor(device, 160, 360); /* lower left quad */
331     ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
332     color = getPixelColor(device, 160, 120); /* upper left quad */
333     ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
334     color = getPixelColor(device, 480, 360); /* lower right quad  */
335     ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
336     color = getPixelColor(device, 480, 120); /* upper right quad */
337     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
338
339     IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
340 }
341
342 struct sVertex {
343     float x, y, z;
344     DWORD diffuse;
345     DWORD specular;
346 };
347
348 struct sVertexT {
349     float x, y, z, rhw;
350     DWORD diffuse;
351     DWORD specular;
352 };
353
354 static void fog_test(IDirect3DDevice8 *device)
355 {
356     HRESULT hr;
357     DWORD color;
358     float start = 0.0, end = 1.0;
359
360     /* Gets full z based fog with linear fog, no fog with specular color */
361     struct sVertex unstransformed_1[] = {
362         {-1,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
363         {-1,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
364         { 0,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
365         { 0,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
366     };
367     /* Ok, I am too lazy to deal with transform matrices */
368     struct sVertex unstransformed_2[] = {
369         {-1,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
370         {-1,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
371         { 0,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
372         { 0,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
373     };
374     /* Untransformed ones. Give them a different diffuse color to make the test look
375      * nicer. It also makes making sure that they are drawn correctly easier.
376      */
377     struct sVertexT transformed_1[] = {
378         {320,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
379         {640,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
380         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
381         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
382     };
383     struct sVertexT transformed_2[] = {
384         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
385         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
386         {640,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
387         {320,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
388     };
389     WORD Indices[] = {0, 1, 2, 2, 3, 0};
390
391     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
392     ok(hr == D3D_OK, "IDirect3DDevice8_Clear returned %#08x\n", hr);
393
394     /* Setup initial states: No lighting, fog on, fog color */
395     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
396     ok(hr == D3D_OK, "Turning off lighting returned %#08x\n", hr);
397     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
398     ok(hr == D3D_OK, "Turning on fog calculations returned %#08x\n", hr);
399     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
400     ok(hr == D3D_OK, "Turning on fog calculations returned %#08x\n", hr);
401
402     /* First test: Both table fog and vertex fog off */
403     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
404     ok(hr == D3D_OK, "Turning off table fog returned %#08x\n", hr);
405     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
406     ok(hr == D3D_OK, "Turning off table fog returned %#08x\n", hr);
407
408     /* Start = 0, end = 1. Should be default, but set them */
409     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
410     ok(hr == D3D_OK, "Setting fog start returned %#08x\n", hr);
411     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
412     ok(hr == D3D_OK, "Setting fog start returned %#08x\n", hr);
413
414     if(IDirect3DDevice8_BeginScene(device) == D3D_OK)
415     {
416         hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
417         ok( hr == D3D_OK, "SetVertexShader returned %#08x\n", hr);
418         /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
419         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
420                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_1,
421                                                      sizeof(unstransformed_1[0]));
422         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
423
424         /* That makes it use the Z value */
425         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
426         ok(hr == D3D_OK, "Turning off table fog returned %#08x\n", hr);
427         /* Untransformed, vertex fog != none (or table fog != none):
428          * Use the Z value as input into the equation
429          */
430         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
431                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_2,
432                                                      sizeof(unstransformed_1[0]));
433         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
434
435         /* transformed verts */
436         hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
437         ok( hr == D3D_OK, "SetVertexShader returned %#08x\n", hr);
438         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
439         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
440                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
441                                                      sizeof(transformed_1[0]));
442         ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %#08x\n", hr);
443
444         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
445         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %#08x\n", hr);
446         /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
447          * equation
448          */
449         hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
450                                                      2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_2,
451                                                      sizeof(transformed_2[0]));
452         ok(SUCCEEDED(hr), "IDirect3DDevice8_DrawIndexedPrimitiveUP returned %#x.\n", hr);
453
454         hr = IDirect3DDevice8_EndScene(device);
455         ok(hr == D3D_OK, "EndScene returned %#08x\n", hr);
456     }
457     else
458     {
459         ok(FALSE, "BeginScene failed\n");
460     }
461
462     color = getPixelColor(device, 160, 360);
463     ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color);
464     color = getPixelColor(device, 160, 120);
465     ok(color == 0x0000FF00, "Untransformed vertex with linear vertex fog has color %08x\n", color);
466     color = getPixelColor(device, 480, 120);
467     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
468     color = getPixelColor(device, 480, 360);
469     ok(color == 0x0000FF00, "Transformed vertex with linear table fog has color %08x\n", color);
470
471     IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
472
473     /* Turn off the fog master switch to avoid confusing other tests */
474     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
475     ok(hr == D3D_OK, "Turning off fog calculations returned %#08x\n", hr);
476 }
477
478 static void present_test(IDirect3DDevice8 *device)
479 {
480     struct vertex quad[] =
481     {
482         {-1.0f, -1.0f,   0.9f,                          0xffff0000},
483         {-1.0f,  1.0f,   0.9f,                          0xffff0000},
484         { 1.0f, -1.0f,   0.1f,                          0xffff0000},
485         { 1.0f,  1.0f,   0.1f,                          0xffff0000},
486     };
487     HRESULT hr;
488     DWORD color;
489
490     /* Does the Present clear the depth stencil? Clear the depth buffer with some value != 0,
491     * then call Present. Then clear the color buffer to make sure it has some defined content
492     * after the Present with D3DSWAPEFFECT_DISCARD. After that draw a plane that is somewhere cut
493     * by the depth value.
494     */
495     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.75, 0);
496     ok(hr == D3D_OK, "IDirect3DDevice8_Clear returned %08x\n", hr);
497     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
498     ok(SUCCEEDED(hr), "IDirect3DDevice8_Present returned %#x.\n", hr);
499     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.4f, 0);
500     ok(SUCCEEDED(hr), "IDirect3DDevice8_Clear returned %#x.\n", hr);
501
502     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
503     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %08x\n", hr);
504     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_GREATER);
505     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %08x\n", hr);
506     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
507     ok(hr == D3D_OK, "IDirect3DDevice8_SetFVF returned %08x\n", hr);
508
509     hr = IDirect3DDevice8_BeginScene(device);
510     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed with %08x\n", hr);
511     if(hr == D3D_OK)
512     {
513         /* No lights are defined... That means, lit vertices should be entirely black */
514         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2 /*PrimCount */, quad, sizeof(quad[0]));
515         ok(hr == D3D_OK, "IDirect3DDevice8_DrawIndexedPrimitiveUP failed with %08x\n", hr);
516
517         hr = IDirect3DDevice8_EndScene(device);
518         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed with %08x\n", hr);
519     }
520
521     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE);
522     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %08x\n", hr);
523
524     color = getPixelColor(device, 512, 240);
525     ok(color == 0x00ffffff, "Present failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
526     color = getPixelColor(device, 64, 240);
527     ok(color == 0x00ff0000, "Present failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
528
529     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
530     ok(SUCCEEDED(hr), "Present failed (%#08x)\n", hr);
531 }
532
533 static void test_rcp_rsq(IDirect3DDevice8 *device)
534 {
535     HRESULT hr;
536     DWORD shader;
537     DWORD color;
538     float constant[4] = {1.0, 1.0, 1.0, 2.0};
539
540     static const float quad[][3] = {
541         {-1.0f, -1.0f, 0.0f},
542         {-1.0f,  1.0f, 0.0f},
543         { 1.0f, -1.0f, 0.0f},
544         { 1.0f,  1.0f, 0.0f},
545     };
546
547     const DWORD rcp_test[] = {
548         0xfffe0101,                                         /* vs.1.1 */
549
550         0x0009fffe, 0x30303030, 0x30303030,                 /* Shaders have to have a minimal size. */
551         0x30303030, 0x30303030, 0x30303030,                 /* Add a filler comment. Usually D3DX8's*/
552         0x30303030, 0x30303030, 0x30303030,                 /* version comment makes the shader big */
553         0x00303030,                                         /* enough to make windows happy         */
554
555         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0 */
556         0x00000006, 0xd00f0000, 0xa0e40000,                 /* rcp oD0, c0 */
557         0x0000ffff                                          /* END */
558     };
559
560     const DWORD rsq_test[] = {
561         0xfffe0101,                                         /* vs.1.1 */
562
563         0x0009fffe, 0x30303030, 0x30303030,                 /* Shaders have to have a minimal size. */
564         0x30303030, 0x30303030, 0x30303030,                 /* Add a filler comment. Usually D3DX8's*/
565         0x30303030, 0x30303030, 0x30303030,                 /* version comment makes the shader big */
566         0x00303030,                                         /* enough to make windows happy         */
567
568         0x00000001, 0xc00f0000, 0x90e40000,                 /* mov oPos, v0 */
569         0x00000007, 0xd00f0000, 0xa0e40000,                 /* rsq oD0, c0 */
570         0x0000ffff                                          /* END */
571     };
572
573     DWORD decl[] =
574     {
575         D3DVSD_STREAM(0),
576         D3DVSD_REG(D3DVSDE_POSITION, D3DVSDT_FLOAT3),  /* D3DVSDE_POSITION, Register v0 */
577         D3DVSD_END()
578     };
579
580     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff336699, 0.0f, 0);
581     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %#08x\n", hr);
582
583     hr = IDirect3DDevice8_CreateVertexShader(device, decl, rcp_test, &shader, 0);
584     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned with %#08x\n", hr);
585
586     IDirect3DDevice8_SetVertexShader(device, shader);
587     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
588     IDirect3DDevice8_SetVertexShaderConstant(device, 0, constant, 1);
589
590     hr = IDirect3DDevice8_BeginScene(device);
591     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene returned %#08x\n", hr);
592     if(SUCCEEDED(hr))
593     {
594         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], 3 * sizeof(float));
595         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%#08x)\n", hr);
596         hr = IDirect3DDevice8_EndScene(device);
597         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
598     }
599
600     color = getPixelColor(device, 320, 240);
601     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x80, 0x80, 0x80), 4),
602             "RCP test returned color 0x%08x, expected 0x00808080.\n", color);
603
604     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
605     ok(SUCCEEDED(hr), "Present failed (%#08x)\n", hr);
606
607     IDirect3DDevice8_SetVertexShader(device, 0);
608     IDirect3DDevice8_DeleteVertexShader(device, shader);
609
610     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff996633, 0.0f, 0);
611     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed with %#08x\n", hr);
612
613     hr = IDirect3DDevice8_CreateVertexShader(device, decl, rsq_test, &shader, 0);
614     ok(hr == D3D_OK, "IDirect3DDevice8_CreateVertexShader returned with %#08x\n", hr);
615
616     IDirect3DDevice8_SetVertexShader(device, shader);
617     ok(hr == D3D_OK, "IDirect3DDevice8_SetVertexShader returned %#08x\n", hr);
618     IDirect3DDevice8_SetVertexShaderConstant(device, 0, constant, 1);
619
620     hr = IDirect3DDevice8_BeginScene(device);
621     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene returned %#08x\n", hr);
622     if(SUCCEEDED(hr))
623     {
624         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, &quad[0], 3 * sizeof(float));
625         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed (%#08x)\n", hr);
626         hr = IDirect3DDevice8_EndScene(device);
627         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene returned %#08x\n", hr);
628     }
629
630     color = getPixelColor(device, 320, 240);
631     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xb4, 0xb4, 0xb4), 4),
632             "RSQ test returned color 0x%08x, expected 0x00b4b4b4.\n", color);
633
634     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
635     ok(SUCCEEDED(hr), "Present failed (%#08x)\n", hr);
636
637     IDirect3DDevice8_SetVertexShader(device, 0);
638     IDirect3DDevice8_DeleteVertexShader(device, shader);
639 }
640
641 static void offscreen_test(IDirect3DDevice8 *device)
642 {
643     HRESULT hr;
644     IDirect3DTexture8 *offscreenTexture = NULL;
645     IDirect3DSurface8 *backbuffer = NULL, *offscreen = NULL, *depthstencil = NULL;
646     DWORD color;
647
648     static const float quad[][5] = {
649         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
650         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
651         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
652         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
653     };
654
655     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &depthstencil);
656     ok(hr == D3D_OK, "IDirect3DDevice8_GetDepthStencilSurface failed, hr = %#08x\n", hr);
657
658     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
659     ok(hr == D3D_OK, "Clear failed, hr = %#08x\n", hr);
660
661     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture);
662     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr);
663     if(!offscreenTexture) {
664         trace("Failed to create an X8R8G8B8 offscreen texture, trying R5G6B5\n");
665         hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &offscreenTexture);
666         ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr);
667         if(!offscreenTexture) {
668             skip("Cannot create an offscreen render target\n");
669             goto out;
670         }
671     }
672
673     hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
674     ok(hr == D3D_OK, "Can't get back buffer, hr = %#08x\n", hr);
675     if(!backbuffer) {
676         goto out;
677     }
678
679     hr = IDirect3DTexture8_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
680     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %#08x\n", hr);
681     if(!offscreen) {
682         goto out;
683     }
684
685     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_TEX1);
686     ok(hr == D3D_OK, "SetVertexShader failed, hr = %#08x\n", hr);
687
688     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
689     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %#08x\n", hr);
690     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
691     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %#08x\n", hr);
692     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DTEXF_NONE);
693     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MINFILTER failed (%#08x)\n", hr);
694     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DTEXF_NONE);
695     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MAGFILTER failed (%#08x)\n", hr);
696     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
697     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %08x\n", hr);
698
699     if(IDirect3DDevice8_BeginScene(device) == D3D_OK) {
700         hr = IDirect3DDevice8_SetRenderTarget(device, offscreen, depthstencil);
701         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %#08x\n", hr);
702         hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
703         ok(hr == D3D_OK, "Clear failed, hr = %#08x\n", hr);
704
705         /* Draw without textures - Should result in a white quad */
706         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
707         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
708
709         hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depthstencil);
710         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %#08x\n", hr);
711         hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *) offscreenTexture);
712         ok(hr == D3D_OK, "SetTexture failed, %08x\n", hr);
713
714         /* This time with the texture */
715         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(quad[0]));
716         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
717
718         IDirect3DDevice8_EndScene(device);
719     }
720
721     /* Center quad - should be white */
722     color = getPixelColor(device, 320, 240);
723     ok(color == 0x00ffffff, "Offscreen failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
724     /* Some quad in the cleared part of the texture */
725     color = getPixelColor(device, 170, 240);
726     ok(color == 0x00ff00ff, "Offscreen failed: Got color 0x%08x, expected 0x00ff00ff.\n", color);
727     /* Part of the originally cleared back buffer */
728     color = getPixelColor(device, 10, 10);
729     ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
730     if(0) {
731         /* Lower left corner of the screen, where back buffer offscreen rendering draws the offscreen texture.
732         * It should be red, but the offscreen texture may leave some junk there. Not tested yet. Depending on
733         * the offscreen rendering mode this test would succeed or fail
734         */
735         color = getPixelColor(device, 10, 470);
736         ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
737     }
738
739     IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
740
741 out:
742     hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
743     ok(SUCCEEDED(hr), "IDirect3DDevice8_SetTexture returned %#x.\n", hr);
744
745     /* restore things */
746     if(backbuffer) {
747         hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depthstencil);
748         ok(SUCCEEDED(hr), "IDirect3DDevice8_SetRenderTarget returned %#x.\n", hr);
749         IDirect3DSurface8_Release(backbuffer);
750     }
751     if(offscreenTexture) {
752         IDirect3DTexture8_Release(offscreenTexture);
753     }
754     if(offscreen) {
755         IDirect3DSurface8_Release(offscreen);
756     }
757     if(depthstencil) {
758         IDirect3DSurface8_Release(depthstencil);
759     }
760 }
761
762 static void alpha_test(IDirect3DDevice8 *device)
763 {
764     HRESULT hr;
765     IDirect3DTexture8 *offscreenTexture;
766     IDirect3DSurface8 *backbuffer = NULL, *offscreen = NULL, *depthstencil = NULL;
767     DWORD color;
768
769     struct vertex quad1[] =
770     {
771         {-1.0f, -1.0f,   0.1f,                          0x4000ff00},
772         {-1.0f,  0.0f,   0.1f,                          0x4000ff00},
773         { 1.0f, -1.0f,   0.1f,                          0x4000ff00},
774         { 1.0f,  0.0f,   0.1f,                          0x4000ff00},
775     };
776     struct vertex quad2[] =
777     {
778         {-1.0f,  0.0f,   0.1f,                          0xc00000ff},
779         {-1.0f,  1.0f,   0.1f,                          0xc00000ff},
780         { 1.0f,  0.0f,   0.1f,                          0xc00000ff},
781         { 1.0f,  1.0f,   0.1f,                          0xc00000ff},
782     };
783     static const float composite_quad[][5] = {
784         { 0.0f, -1.0f, 0.1f, 0.0f, 1.0f},
785         { 0.0f,  1.0f, 0.1f, 0.0f, 0.0f},
786         { 1.0f, -1.0f, 0.1f, 1.0f, 1.0f},
787         { 1.0f,  1.0f, 0.1f, 1.0f, 0.0f},
788     };
789
790     /* Clear the render target with alpha = 0.5 */
791     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
792     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
793
794     hr = IDirect3DDevice8_CreateTexture(device, 128, 128, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &offscreenTexture);
795     ok(hr == D3D_OK || hr == D3DERR_INVALIDCALL, "Creating the offscreen render target failed, hr = %#08x\n", hr);
796
797     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &depthstencil);
798     ok(hr == D3D_OK, "IDirect3DDevice8_GetDepthStencilSurface failed, hr = %#08x\n", hr);
799
800     hr = IDirect3DDevice8_GetBackBuffer(device, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
801     ok(hr == D3D_OK, "Can't get back buffer, hr = %#08x\n", hr);
802     if(!backbuffer) {
803         goto out;
804     }
805     hr = IDirect3DTexture8_GetSurfaceLevel(offscreenTexture, 0, &offscreen);
806     ok(hr == D3D_OK, "Can't get offscreen surface, hr = %#08x\n", hr);
807     if(!offscreen) {
808         goto out;
809     }
810
811     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
812     ok(hr == D3D_OK, "SetVertexShader failed, hr = %#08x\n", hr);
813
814     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
815     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %#08x\n", hr);
816     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
817     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %#08x\n", hr);
818     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DTEXF_NONE);
819     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MINFILTER failed (%#08x)\n", hr);
820     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DTEXF_NONE);
821     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MAGFILTER failed (%#08x)\n", hr);
822     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
823     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState returned %08x\n", hr);
824
825     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
826     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
827     if(IDirect3DDevice8_BeginScene(device) == D3D_OK) {
828
829         /* Draw two quads, one with src alpha blending, one with dest alpha blending. */
830         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
831         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
832         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
833         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
834         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
835         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
836
837         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
838         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
839         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
840         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
841         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
842         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
843
844         /* Switch to the offscreen buffer, and redo the testing. The offscreen render target
845          * doesn't have an alpha channel. DESTALPHA and INVDESTALPHA "don't work" on render
846          * targets without alpha channel, they give essentially ZERO and ONE blend factors. */
847         hr = IDirect3DDevice8_SetRenderTarget(device, offscreen, 0);
848         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
849         hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
850         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
851
852         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
853         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
854         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
855         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
856         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(quad1[0]));
857         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
858
859         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_DESTALPHA);
860         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
861         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVDESTALPHA);
862         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
863         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(quad2[0]));
864         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
865
866         hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depthstencil);
867         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
868
869         /* Render the offscreen texture onto the frame buffer to be able to compare it regularly.
870          * Disable alpha blending for the final composition
871          */
872         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
873         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
874         hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_TEX1);
875         ok(hr == D3D_OK, "SetVertexShader failed, hr = %#08x\n", hr);
876
877         hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *) offscreenTexture);
878         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture failed, hr = %08x\n", hr);
879         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, composite_quad, sizeof(float) * 5);
880         ok(hr == D3D_OK, "DrawPrimitiveUP failed, hr = %#08x\n", hr);
881         hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
882         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture failed, hr = %08x\n", hr);
883
884         hr = IDirect3DDevice8_EndScene(device);
885         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
886     }
887
888     color = getPixelColor(device, 160, 360);
889     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1),
890        "SRCALPHA on frame buffer returned color %08x, expected 0x00bf4000\n", color);
891
892     color = getPixelColor(device, 160, 120);
893     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x7f, 0x00, 0x80), 2),
894        "DSTALPHA on frame buffer returned color %08x, expected 0x007f0080\n", color);
895
896     color = getPixelColor(device, 480, 360);
897     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0xbf, 0x40, 0x00), 1),
898        "SRCALPHA on texture returned color %08x, expected 0x00bf4000\n", color);
899
900     color = getPixelColor(device, 480, 120);
901     ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0xff), 1),
902        "DSTALPHA on texture returned color %08x, expected 0x000000ff\n", color);
903
904     IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
905
906     out:
907     /* restore things */
908     if(backbuffer) {
909         IDirect3DSurface8_Release(backbuffer);
910     }
911     if(offscreenTexture) {
912         IDirect3DTexture8_Release(offscreenTexture);
913     }
914     if(offscreen) {
915         IDirect3DSurface8_Release(offscreen);
916     }
917     if(depthstencil) {
918         IDirect3DSurface8_Release(depthstencil);
919     }
920 }
921
922 static void p8_texture_test(IDirect3DDevice8 *device)
923 {
924     IDirect3D8 *d3d = NULL;
925     HRESULT hr;
926     IDirect3DTexture8 *texture = NULL, *texture2 = NULL;
927     D3DLOCKED_RECT lr;
928     unsigned char *data;
929     DWORD color, red, green, blue;
930     PALETTEENTRY table[256];
931     D3DCAPS8 caps;
932     UINT i;
933     float quad[] = {
934        -1.0f,      0.0f,    0.1f,    0.0f,   0.0f,
935        -1.0f,      1.0f,    0.1f,    0.0f,   1.0f,
936         1.0f,      0.0f,    0.1f,    1.0f,   0.0f,
937         1.0f,      1.0f,    0.1f,    1.0f,   1.0f,
938     };
939     float quad2[] = {
940        -1.0f,      -1.0f,   0.1f,    0.0f,   0.0f,
941        -1.0f,      0.0f,    0.1f,    0.0f,   1.0f,
942         1.0f,      -1.0f,   0.1f,    1.0f,   0.0f,
943         1.0f,      0.0f,    0.1f,    1.0f,   1.0f,
944     };
945
946     IDirect3DDevice8_GetDirect3D(device, &d3d);
947
948     if(IDirect3D8_CheckDeviceFormat(d3d, 0, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, 0,
949        D3DRTYPE_TEXTURE, D3DFMT_P8) != D3D_OK) {
950            skip("D3DFMT_P8 textures not supported\n");
951            goto out;
952     }
953
954     hr = IDirect3DDevice8_CreateTexture(device, 1, 1, 1, 0, D3DFMT_P8,
955                                         D3DPOOL_MANAGED, &texture2);
956     ok(hr == D3D_OK, "IDirect3DDevice8_CreateTexture failed, hr = %08x\n", hr);
957     if(!texture2) {
958         skip("Failed to create D3DFMT_P8 texture\n");
959         goto out;
960     }
961
962     memset(&lr, 0, sizeof(lr));
963     hr = IDirect3DTexture8_LockRect(texture2, 0, &lr, NULL, 0);
964     ok(hr == D3D_OK, "IDirect3DTexture8_LockRect failed, hr = %08x\n", hr);
965     data = lr.pBits;
966     *data = 1;
967
968     hr = IDirect3DTexture8_UnlockRect(texture2, 0);
969     ok(hr == D3D_OK, "IDirect3DTexture8_UnlockRect failed, hr = %08x\n", hr);
970
971     hr = IDirect3DDevice8_CreateTexture(device, 1, 1, 1, 0, D3DFMT_P8,
972                                         D3DPOOL_MANAGED, &texture);
973     ok(hr == D3D_OK, "IDirect3DDevice8_CreateTexture failed, hr = %08x\n", hr);
974     if(!texture) {
975         skip("Failed to create D3DFMT_P8 texture\n");
976         goto out;
977     }
978
979     memset(&lr, 0, sizeof(lr));
980     hr = IDirect3DTexture8_LockRect(texture, 0, &lr, NULL, 0);
981     ok(hr == D3D_OK, "IDirect3DTexture8_LockRect failed, hr = %08x\n", hr);
982     data = lr.pBits;
983     *data = 1;
984
985     hr = IDirect3DTexture8_UnlockRect(texture, 0);
986     ok(hr == D3D_OK, "IDirect3DTexture8_UnlockRect failed, hr = %08x\n", hr);
987
988     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
989     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed, hr = %08x\n", hr);
990
991     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
992     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
993
994     /* The first part of the test should work both with and without D3DPTEXTURECAPS_ALPHAPALETTE;
995        alpha of every entry is set to 1.0, which MS says is required when there's no
996        D3DPTEXTURECAPS_ALPHAPALETTE capability */
997     for (i = 0; i < 256; i++) {
998         table[i].peRed = table[i].peGreen = table[i].peBlue = 0;
999         table[i].peFlags = 0xff;
1000     }
1001     table[1].peRed = 0xff;
1002     hr = IDirect3DDevice8_SetPaletteEntries(device, 0, table);
1003     ok(hr == D3D_OK, "IDirect3DDevice8_SetPaletteEntries failed, hr = %08x\n", hr);
1004
1005     table[1].peRed = 0;
1006     table[1].peBlue = 0xff;
1007     hr = IDirect3DDevice8_SetPaletteEntries(device, 1, table);
1008     ok(hr == D3D_OK, "IDirect3DDevice8_SetPaletteEntries failed, hr = %08x\n", hr);
1009
1010     hr = IDirect3DDevice8_BeginScene(device);
1011     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed, hr = %08x\n", hr);
1012     if(SUCCEEDED(hr)) {
1013         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
1014         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1015         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
1016         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1017
1018         hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_TEX1);
1019         ok(hr == D3D_OK, "SetVertexShader failed, hr = %#08x\n", hr);
1020
1021         hr = IDirect3DDevice8_SetCurrentTexturePalette(device, 0);
1022         ok(hr == D3D_OK, "IDirect3DDevice8_SetCurrentTexturePalette failed, hr = %08x\n", hr);
1023
1024         hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *) texture2);
1025         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture failed, hr = %08x\n", hr);
1026         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
1027         ok(hr == D3D_OK, "IDirect3DDevice8_DrawPrimitiveUP failed, hr = %08x\n", hr);
1028
1029         hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *) texture);
1030         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture failed, hr = %08x\n", hr);
1031         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
1032         ok(hr == D3D_OK, "IDirect3DDevice8_DrawPrimitiveUP failed, hr = %08x\n", hr);
1033
1034         hr = IDirect3DDevice8_SetCurrentTexturePalette(device, 1);
1035         ok(hr == D3D_OK, "IDirect3DDevice8_SetCurrentTexturePalette failed, hr = %08x\n", hr);
1036         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
1037         ok(hr == D3D_OK, "IDirect3DDevice8_DrawPrimitiveUP failed, hr = %08x\n", hr);
1038
1039         hr = IDirect3DDevice8_EndScene(device);
1040         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed, hr = %08x\n", hr);
1041     }
1042
1043     color = getPixelColor(device, 32, 32);
1044     red   = (color & 0x00ff0000) >> 16;
1045     green = (color & 0x0000ff00) >>  8;
1046     blue  = (color & 0x000000ff) >>  0;
1047     ok(red == 0xff && blue == 0 && green == 0,
1048        "got color %08x, expected 0x00ff0000\n", color);
1049
1050     color = getPixelColor(device, 32, 320);
1051     red   = (color & 0x00ff0000) >> 16;
1052     green = (color & 0x0000ff00) >>  8;
1053     blue  = (color & 0x000000ff) >>  0;
1054     ok(red == 0 && blue == 0xff && green == 0,
1055     "got color %08x, expected 0x000000ff\n", color);
1056
1057     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1058     ok(hr == D3D_OK, "IDirect3DDevice8_Present failed, hr = %08x\n", hr);
1059
1060     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
1061     ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed, hr = %08x\n", hr);
1062
1063     hr = IDirect3DDevice8_BeginScene(device);
1064     ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed, hr = %08x\n", hr);
1065     if(SUCCEEDED(hr)) {
1066         hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *) texture2);
1067         ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture failed, hr = %08x\n", hr);
1068
1069         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
1070         ok(hr == D3D_OK, "IDirect3DDevice8_DrawPrimitiveUP failed, hr = %08x\n", hr);
1071
1072         hr = IDirect3DDevice8_EndScene(device);
1073         ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed, hr = %08x\n", hr);
1074     }
1075
1076
1077     color = getPixelColor(device, 32, 32);
1078     red   = (color & 0x00ff0000) >> 16;
1079     green = (color & 0x0000ff00) >>  8;
1080     blue  = (color & 0x000000ff) >>  0;
1081     ok(red == 0 && blue == 0xff && green == 0,
1082     "got color %08x, expected 0x000000ff\n", color);
1083
1084     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1085     ok(hr == D3D_OK, "IDirect3DDevice8_Present failed, hr = %08x\n", hr);
1086
1087     /* Test palettes with alpha */
1088     IDirect3DDevice8_GetDeviceCaps(device, &caps);
1089     if (!(caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE)) {
1090         skip("no D3DPTEXTURECAPS_ALPHAPALETTE capability, tests with alpha in palette will be skipped\n");
1091     } else {
1092         hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
1093         ok(hr == D3D_OK, "IDirect3DDevice8_Clear failed, hr = %08x\n", hr);
1094
1095         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHABLENDENABLE, TRUE);
1096         ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1097
1098         for (i = 0; i < 256; i++) {
1099             table[i].peRed = table[i].peGreen = table[i].peBlue = 0;
1100             table[i].peFlags = 0xff;
1101         }
1102         table[1].peRed = 0xff;
1103         table[1].peFlags = 0x80;
1104         hr = IDirect3DDevice8_SetPaletteEntries(device, 0, table);
1105         ok(hr == D3D_OK, "IDirect3DDevice8_SetPaletteEntries failed, hr = %08x\n", hr);
1106
1107         table[1].peRed = 0;
1108         table[1].peBlue = 0xff;
1109         table[1].peFlags = 0x80;
1110         hr = IDirect3DDevice8_SetPaletteEntries(device, 1, table);
1111         ok(hr == D3D_OK, "IDirect3DDevice8_SetPaletteEntries failed, hr = %08x\n", hr);
1112
1113         hr = IDirect3DDevice8_BeginScene(device);
1114         ok(hr == D3D_OK, "IDirect3DDevice8_BeginScene failed, hr = %08x\n", hr);
1115         if(SUCCEEDED(hr)) {
1116             hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
1117             ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1118             hr = IDirect3DDevice8_SetRenderState(device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
1119             ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1120
1121             hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_TEX1);
1122             ok(hr == D3D_OK, "SetVertexShader failed, hr = %#08x\n", hr);
1123
1124             hr = IDirect3DDevice8_SetCurrentTexturePalette(device, 0);
1125             ok(hr == D3D_OK, "IDirect3DDevice8_SetCurrentTexturePalette failed, hr = %08x\n", hr);
1126
1127             hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, 5 * sizeof(float));
1128             ok(hr == D3D_OK, "IDirect3DDevice8_DrawPrimitiveUP failed, hr = %08x\n", hr);
1129
1130             hr = IDirect3DDevice8_SetCurrentTexturePalette(device, 1);
1131             ok(hr == D3D_OK, "IDirect3DDevice8_SetCurrentTexturePalette failed, hr = %08x\n", hr);
1132
1133             hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, 5 * sizeof(float));
1134             ok(hr == D3D_OK, "IDirect3DDevice8_DrawPrimitiveUP failed, hr = %08x\n", hr);
1135
1136             hr = IDirect3DDevice8_EndScene(device);
1137             ok(hr == D3D_OK, "IDirect3DDevice8_EndScene failed, hr = %08x\n", hr);
1138         }
1139
1140         color = getPixelColor(device, 32, 32);
1141         red   = (color & 0x00ff0000) >> 16;
1142         green = (color & 0x0000ff00) >>  8;
1143         blue  = (color & 0x000000ff) >>  0;
1144         ok(red >= 0x7e && red <= 0x81 && blue == 0 && green == 0,
1145         "got color %08x, expected 0x00800000 or near\n", color);
1146
1147         color = getPixelColor(device, 32, 320);
1148         red   = (color & 0x00ff0000) >> 16;
1149         green = (color & 0x0000ff00) >>  8;
1150         blue  = (color & 0x000000ff) >>  0;
1151         ok(red == 0 && blue >= 0x7e && blue <= 0x81 && green == 0,
1152         "got color %08x, expected 0x00000080 or near\n", color);
1153
1154         hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1155         ok(hr == D3D_OK, "IDirect3DDevice8_Present failed, hr = %08x\n", hr);
1156     }
1157
1158     hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
1159     ok(hr == D3D_OK, "IDirect3DDevice8_SetTexture failed, hr = %08x\n", hr);
1160     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ALPHABLENDENABLE, FALSE);
1161     ok(hr == D3D_OK, "IDirect3DDevice8_SetRenderState failed, hr = %08x\n", hr);
1162
1163 out:
1164     if(texture) IDirect3DTexture8_Release(texture);
1165     if(texture2) IDirect3DTexture8_Release(texture2);
1166     IDirect3D8_Release(d3d);
1167 }
1168
1169 static void texop_test(IDirect3DDevice8 *device)
1170 {
1171     IDirect3DTexture8 *texture = NULL;
1172     D3DLOCKED_RECT locked_rect;
1173     D3DCOLOR color;
1174     D3DCAPS8 caps;
1175     HRESULT hr;
1176     unsigned int i;
1177
1178     static const struct {
1179         float x, y, z;
1180         D3DCOLOR diffuse;
1181         float s, t;
1182     } quad[] = {
1183         {-1.0f, -1.0f, 0.1f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00), -1.0f, -1.0f},
1184         {-1.0f,  1.0f, 0.1f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00), -1.0f,  1.0f},
1185         { 1.0f, -1.0f, 0.1f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00),  1.0f, -1.0f},
1186         { 1.0f,  1.0f, 0.1f, D3DCOLOR_ARGB(0x55, 0xff, 0x00, 0x00),  1.0f,  1.0f}
1187     };
1188
1189     static const struct {
1190         D3DTEXTUREOP op;
1191         const char *name;
1192         DWORD caps_flag;
1193         D3DCOLOR result;
1194     } test_data[] = {
1195         {D3DTOP_SELECTARG1,                "SELECTARG1",                D3DTEXOPCAPS_SELECTARG1,                D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
1196         {D3DTOP_SELECTARG2,                "SELECTARG2",                D3DTEXOPCAPS_SELECTARG2,                D3DCOLOR_ARGB(0x00, 0x33, 0x33, 0x33)},
1197         {D3DTOP_MODULATE,                  "MODULATE",                  D3DTEXOPCAPS_MODULATE,                  D3DCOLOR_ARGB(0x00, 0x00, 0x33, 0x00)},
1198         {D3DTOP_MODULATE2X,                "MODULATE2X",                D3DTEXOPCAPS_MODULATE2X,                D3DCOLOR_ARGB(0x00, 0x00, 0x66, 0x00)},
1199         {D3DTOP_MODULATE4X,                "MODULATE4X",                D3DTEXOPCAPS_MODULATE4X,                D3DCOLOR_ARGB(0x00, 0x00, 0xcc, 0x00)},
1200         {D3DTOP_ADD,                       "ADD",                       D3DTEXOPCAPS_ADD,                       D3DCOLOR_ARGB(0x00, 0x33, 0xff, 0x33)},
1201
1202         {D3DTOP_ADDSIGNED,                 "ADDSIGNED",                 D3DTEXOPCAPS_ADDSIGNED,                 D3DCOLOR_ARGB(0x00, 0x00, 0xb2, 0x00)},
1203         {D3DTOP_ADDSIGNED2X,               "ADDSIGNED2X",               D3DTEXOPCAPS_ADDSIGNED2X,               D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00)},
1204
1205         {D3DTOP_SUBTRACT,                  "SUBTRACT",                  D3DTEXOPCAPS_SUBTRACT,                  D3DCOLOR_ARGB(0x00, 0x00, 0xcc, 0x00)},
1206         {D3DTOP_ADDSMOOTH,                 "ADDSMOOTH",                 D3DTEXOPCAPS_ADDSMOOTH,                 D3DCOLOR_ARGB(0x00, 0x33, 0xff, 0x33)},
1207         {D3DTOP_BLENDDIFFUSEALPHA,         "BLENDDIFFUSEALPHA",         D3DTEXOPCAPS_BLENDDIFFUSEALPHA,         D3DCOLOR_ARGB(0x00, 0x22, 0x77, 0x22)},
1208         {D3DTOP_BLENDTEXTUREALPHA,         "BLENDTEXTUREALPHA",         D3DTEXOPCAPS_BLENDTEXTUREALPHA,         D3DCOLOR_ARGB(0x00, 0x14, 0xad, 0x14)},
1209         {D3DTOP_BLENDFACTORALPHA,          "BLENDFACTORALPHA",          D3DTEXOPCAPS_BLENDFACTORALPHA,          D3DCOLOR_ARGB(0x00, 0x07, 0xe4, 0x07)},
1210         {D3DTOP_BLENDTEXTUREALPHAPM,       "BLENDTEXTUREALPHAPM",       D3DTEXOPCAPS_BLENDTEXTUREALPHAPM,       D3DCOLOR_ARGB(0x00, 0x14, 0xff, 0x14)},
1211         {D3DTOP_BLENDCURRENTALPHA,         "BLENDCURRENTALPHA",         D3DTEXOPCAPS_BLENDCURRENTALPHA,         D3DCOLOR_ARGB(0x00, 0x22, 0x77, 0x22)},
1212         {D3DTOP_MODULATEALPHA_ADDCOLOR,    "MODULATEALPHA_ADDCOLOR",    D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR,    D3DCOLOR_ARGB(0x00, 0x1f, 0xff, 0x1f)},
1213         {D3DTOP_MODULATECOLOR_ADDALPHA,    "MODULATECOLOR_ADDALPHA",    D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA,    D3DCOLOR_ARGB(0x00, 0x99, 0xcc, 0x99)},
1214         {D3DTOP_MODULATEINVALPHA_ADDCOLOR, "MODULATEINVALPHA_ADDCOLOR", D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR, D3DCOLOR_ARGB(0x00, 0x14, 0xff, 0x14)},
1215         {D3DTOP_MODULATEINVCOLOR_ADDALPHA, "MODULATEINVCOLOR_ADDALPHA", D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA, D3DCOLOR_ARGB(0x00, 0xcc, 0x99, 0xcc)},
1216         /* BUMPENVMAP & BUMPENVMAPLUMINANCE have their own tests */
1217         {D3DTOP_DOTPRODUCT3,               "DOTPRODUCT2",               D3DTEXOPCAPS_DOTPRODUCT3,               D3DCOLOR_ARGB(0x00, 0x99, 0x99, 0x99)},
1218         {D3DTOP_MULTIPLYADD,               "MULTIPLYADD",               D3DTEXOPCAPS_MULTIPLYADD,               D3DCOLOR_ARGB(0x00, 0xff, 0x33, 0x00)},
1219         {D3DTOP_LERP,                      "LERP",                      D3DTEXOPCAPS_LERP,                      D3DCOLOR_ARGB(0x00, 0x00, 0x33, 0x33)},
1220     };
1221
1222     memset(&caps, 0, sizeof(caps));
1223     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
1224     ok(SUCCEEDED(hr), "GetDeviceCaps failed with 0x%08x\n", hr);
1225
1226     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX0);
1227     ok(SUCCEEDED(hr), "SetVertexShader failed with 0x%08x\n", hr);
1228
1229     hr = IDirect3DDevice8_CreateTexture(device, 1, 1, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture);
1230     ok(SUCCEEDED(hr), "IDirect3DDevice9_CreateTexture failed with 0x%08x\n", hr);
1231     hr = IDirect3DTexture8_LockRect(texture, 0, &locked_rect, NULL, 0);
1232     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
1233     *((DWORD *)locked_rect.pBits) = D3DCOLOR_ARGB(0x99, 0x00, 0xff, 0x00);
1234     hr = IDirect3DTexture8_UnlockRect(texture, 0);
1235     ok(SUCCEEDED(hr), "LockRect failed with 0x%08x\n", hr);
1236     hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *)texture);
1237     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
1238
1239     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLORARG0, D3DTA_DIFFUSE);
1240     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
1241     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
1242     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
1243     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLORARG2, D3DTA_TFACTOR);
1244     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
1245
1246     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_COLOROP, D3DTOP_DISABLE);
1247     ok(SUCCEEDED(hr), "SetTextureStageState failed with 0x%08x\n", hr);
1248
1249     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1250     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
1251     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_TEXTUREFACTOR, 0xdd333333);
1252     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
1253     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA);
1254     ok(SUCCEEDED(hr), "SetRenderState failed with 0x%08x\n", hr);
1255
1256     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
1257     ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
1258
1259     for (i = 0; i < sizeof(test_data) / sizeof(*test_data); ++i)
1260     {
1261         if (!(caps.TextureOpCaps & test_data[i].caps_flag))
1262         {
1263             skip("tex operation %s not supported\n", test_data[i].name);
1264             continue;
1265         }
1266
1267         hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_COLOROP, test_data[i].op);
1268         ok(SUCCEEDED(hr), "SetTextureStageState (%s) failed with 0x%08x\n", test_data[i].name, hr);
1269
1270         hr = IDirect3DDevice8_BeginScene(device);
1271         ok(SUCCEEDED(hr), "BeginScene failed with 0x%08x\n", hr);
1272
1273         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
1274         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed with 0x%08x\n", hr);
1275
1276         hr = IDirect3DDevice8_EndScene(device);
1277         ok(SUCCEEDED(hr), "EndScene failed with 0x%08x\n", hr);
1278
1279         color = getPixelColor(device, 320, 240);
1280         ok(color_match(color, test_data[i].result, 3), "Operation %s returned color 0x%08x, expected 0x%08x\n",
1281                 test_data[i].name, color, test_data[i].result);
1282
1283         hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1284         ok(SUCCEEDED(hr), "Present failed with 0x%08x\n", hr);
1285
1286         hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
1287         ok(SUCCEEDED(hr), "IDirect3DDevice9_Clear failed with 0x%08x\n", hr);
1288     }
1289
1290     hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
1291     ok(SUCCEEDED(hr), "SetTexture failed with 0x%08x\n", hr);
1292     if (texture) IDirect3DTexture8_Release(texture);
1293 }
1294
1295 /* This test tests depth clamping / clipping behaviour:
1296  *   - With software vertex processing, depth values are clamped to the
1297  *     minimum / maximum z value when D3DRS_CLIPPING is disabled, and clipped
1298  *     when D3DRS_CLIPPING is enabled. Pretransformed vertices behave the
1299  *     same as regular vertices here.
1300  *   - With hardware vertex processing, D3DRS_CLIPPING seems to be ignored.
1301  *     Normal vertices are always clipped. Pretransformed vertices are
1302  *     clipped when D3DPMISCCAPS_CLIPTLVERTS is set, clamped when it isn't.
1303  *   - The viewport's MinZ/MaxZ is irrelevant for this.
1304  */
1305 static void depth_clamp_test(IDirect3DDevice8 *device)
1306 {
1307     const struct tvertex quad1[] =
1308     {
1309         {  0.0f,   0.0f,  5.0f, 1.0f, 0xff002b7f},
1310         {640.0f,   0.0f,  5.0f, 1.0f, 0xff002b7f},
1311         {  0.0f, 480.0f,  5.0f, 1.0f, 0xff002b7f},
1312         {640.0f, 480.0f,  5.0f, 1.0f, 0xff002b7f},
1313     };
1314     const struct tvertex quad2[] =
1315     {
1316         {  0.0f, 300.0f, 10.0f, 1.0f, 0xfff9e814},
1317         {640.0f, 300.0f, 10.0f, 1.0f, 0xfff9e814},
1318         {  0.0f, 360.0f, 10.0f, 1.0f, 0xfff9e814},
1319         {640.0f, 360.0f, 10.0f, 1.0f, 0xfff9e814},
1320     };
1321     const struct tvertex quad3[] =
1322     {
1323         {112.0f, 108.0f,  5.0f, 1.0f, 0xffffffff},
1324         {208.0f, 108.0f,  5.0f, 1.0f, 0xffffffff},
1325         {112.0f, 204.0f,  5.0f, 1.0f, 0xffffffff},
1326         {208.0f, 204.0f,  5.0f, 1.0f, 0xffffffff},
1327     };
1328     const struct tvertex quad4[] =
1329     {
1330         { 42.0f,  41.0f, 10.0f, 1.0f, 0xffffffff},
1331         {112.0f,  41.0f, 10.0f, 1.0f, 0xffffffff},
1332         { 42.0f, 108.0f, 10.0f, 1.0f, 0xffffffff},
1333         {112.0f, 108.0f, 10.0f, 1.0f, 0xffffffff},
1334     };
1335     const struct vertex quad5[] =
1336     {
1337         { -0.5f,   0.5f, 10.0f,       0xff14f914},
1338         {  0.5f,   0.5f, 10.0f,       0xff14f914},
1339         { -0.5f,  -0.5f, 10.0f,       0xff14f914},
1340         {  0.5f,  -0.5f, 10.0f,       0xff14f914},
1341     };
1342     const struct vertex quad6[] =
1343     {
1344         { -1.0f,   0.5f, 10.0f,       0xfff91414},
1345         {  1.0f,   0.5f, 10.0f,       0xfff91414},
1346         { -1.0f,  0.25f, 10.0f,       0xfff91414},
1347         {  1.0f,  0.25f, 10.0f,       0xfff91414},
1348     };
1349
1350     D3DVIEWPORT8 vp;
1351     D3DCOLOR color;
1352     D3DCAPS8 caps;
1353     HRESULT hr;
1354
1355     vp.X = 0;
1356     vp.Y = 0;
1357     vp.Width = 640;
1358     vp.Height = 480;
1359     vp.MinZ = 0.0;
1360     vp.MaxZ = 7.5;
1361
1362     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
1363     ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
1364
1365     hr = IDirect3DDevice8_SetViewport(device, &vp);
1366     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
1367
1368     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ff00, 1.0, 0);
1369     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
1370
1371     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPING, FALSE);
1372     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1373     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1374     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1375     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
1376     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1377     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
1378     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1379
1380     hr = IDirect3DDevice8_BeginScene(device);
1381     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
1382
1383     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
1384     ok(SUCCEEDED(hr), "SetVertexSahder failed, hr %#x.\n", hr);
1385
1386     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
1387     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1388     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
1389     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1390
1391     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPING, TRUE);
1392     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1393
1394     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(*quad3));
1395     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1396     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad4, sizeof(*quad4));
1397     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1398
1399     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPING, FALSE);
1400     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1401     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1402     ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
1403
1404     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad5, sizeof(*quad5));
1405     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1406
1407     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_CLIPPING, TRUE);
1408     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1409
1410     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad6, sizeof(*quad6));
1411     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1412
1413     hr = IDirect3DDevice8_EndScene(device);
1414     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
1415
1416     if (caps.PrimitiveMiscCaps & D3DPMISCCAPS_CLIPTLVERTS)
1417     {
1418         color = getPixelColor(device, 75, 75);
1419         todo_wine ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
1420         color = getPixelColor(device, 150, 150);
1421         todo_wine ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
1422         color = getPixelColor(device, 320, 240);
1423         todo_wine ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
1424         color = getPixelColor(device, 320, 330);
1425         todo_wine ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
1426         color = getPixelColor(device, 320, 330);
1427         todo_wine ok(color_match(color, 0x0000ff00, 1), "color 0x%08x.\n", color);
1428     }
1429     else
1430     {
1431         color = getPixelColor(device, 75, 75);
1432         ok(color_match(color, 0x00ffffff, 1), "color 0x%08x.\n", color);
1433         color = getPixelColor(device, 150, 150);
1434         ok(color_match(color, 0x00ffffff, 1), "color 0x%08x.\n", color);
1435         color = getPixelColor(device, 320, 240);
1436         ok(color_match(color, 0x00002b7f, 1), "color 0x%08x.\n", color);
1437         color = getPixelColor(device, 320, 330);
1438         ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
1439         color = getPixelColor(device, 320, 330);
1440         ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
1441     }
1442
1443     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1444     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1445
1446     vp.MinZ = 0.0;
1447     vp.MaxZ = 1.0;
1448     hr = IDirect3DDevice8_SetViewport(device, &vp);
1449     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
1450 }
1451
1452 static void depth_buffer_test(IDirect3DDevice8 *device)
1453 {
1454     static const struct vertex quad1[] =
1455     {
1456         { -1.0,  1.0, 0.33f, 0xff00ff00},
1457         {  1.0,  1.0, 0.33f, 0xff00ff00},
1458         { -1.0, -1.0, 0.33f, 0xff00ff00},
1459         {  1.0, -1.0, 0.33f, 0xff00ff00},
1460     };
1461     static const struct vertex quad2[] =
1462     {
1463         { -1.0,  1.0, 0.50f, 0xffff00ff},
1464         {  1.0,  1.0, 0.50f, 0xffff00ff},
1465         { -1.0, -1.0, 0.50f, 0xffff00ff},
1466         {  1.0, -1.0, 0.50f, 0xffff00ff},
1467     };
1468     static const struct vertex quad3[] =
1469     {
1470         { -1.0,  1.0, 0.66f, 0xffff0000},
1471         {  1.0,  1.0, 0.66f, 0xffff0000},
1472         { -1.0, -1.0, 0.66f, 0xffff0000},
1473         {  1.0, -1.0, 0.66f, 0xffff0000},
1474     };
1475     static const DWORD expected_colors[4][4] =
1476     {
1477         {0x000000ff, 0x000000ff, 0x0000ff00, 0x00ff0000},
1478         {0x000000ff, 0x000000ff, 0x0000ff00, 0x00ff0000},
1479         {0x0000ff00, 0x0000ff00, 0x0000ff00, 0x00ff0000},
1480         {0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000},
1481     };
1482
1483     IDirect3DSurface8 *backbuffer, *rt1, *rt2, *rt3;
1484     IDirect3DSurface8 *depth_stencil;
1485     unsigned int i, j;
1486     D3DVIEWPORT8 vp;
1487     D3DCOLOR color;
1488     HRESULT hr;
1489
1490     vp.X = 0;
1491     vp.Y = 0;
1492     vp.Width = 640;
1493     vp.Height = 480;
1494     vp.MinZ = 0.0;
1495     vp.MaxZ = 1.0;
1496
1497     hr = IDirect3DDevice8_SetViewport(device, &vp);
1498     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
1499
1500     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1501     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1502     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
1503     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1504     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
1505     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1506     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
1507     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1508     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1509     ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
1510
1511     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &depth_stencil);
1512     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1513     hr = IDirect3DDevice8_GetRenderTarget(device, &backbuffer);
1514     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1515     hr = IDirect3DDevice8_CreateRenderTarget(device, 320, 240, D3DFMT_A8R8G8B8,
1516             D3DMULTISAMPLE_NONE, FALSE, &rt1);
1517     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
1518     hr = IDirect3DDevice8_CreateRenderTarget(device, 480, 360, D3DFMT_A8R8G8B8,
1519             D3DMULTISAMPLE_NONE, FALSE, &rt2);
1520     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
1521     hr = IDirect3DDevice8_CreateRenderTarget(device, 640, 480, D3DFMT_A8R8G8B8,
1522             D3DMULTISAMPLE_NONE, FALSE, &rt3);
1523     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
1524
1525     hr = IDirect3DDevice8_SetRenderTarget(device, rt3, depth_stencil);
1526     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1527     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 0.0f, 0);
1528     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
1529
1530     hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depth_stencil);
1531     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1532     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
1533     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
1534
1535     hr = IDirect3DDevice8_SetRenderTarget(device, rt1, depth_stencil);
1536     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1537     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0f, 0);
1538     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
1539
1540     hr = IDirect3DDevice8_SetRenderTarget(device, rt2, depth_stencil);
1541     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1542     hr = IDirect3DDevice8_BeginScene(device);
1543     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
1544     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad2, sizeof(*quad2));
1545     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1546     hr = IDirect3DDevice8_EndScene(device);
1547     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
1548
1549     hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depth_stencil);
1550     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1551     IDirect3DSurface8_Release(depth_stencil);
1552     IDirect3DSurface8_Release(backbuffer);
1553     IDirect3DSurface8_Release(rt3);
1554     IDirect3DSurface8_Release(rt2);
1555     IDirect3DSurface8_Release(rt1);
1556
1557     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
1558     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1559
1560     hr = IDirect3DDevice8_BeginScene(device);
1561     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
1562     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad1, sizeof(*quad1));
1563     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1564     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad3, sizeof(*quad3));
1565     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1566     hr = IDirect3DDevice8_EndScene(device);
1567     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
1568
1569     for (i = 0; i < 4; ++i)
1570     {
1571         for (j = 0; j < 4; ++j)
1572         {
1573             unsigned int x = 80 * ((2 * j) + 1);
1574             unsigned int y = 60 * ((2 * i) + 1);
1575             color = getPixelColor(device, x, y);
1576             ok(color_match(color, expected_colors[i][j], 0),
1577                     "Expected color 0x%08x at %u,%u, got 0x%08x.\n", expected_colors[i][j], x, y, color);
1578         }
1579     }
1580
1581     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1582     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1583 }
1584
1585 /* Test that partial depth copies work the way they're supposed to. The clear
1586  * on rt2 only needs a partial copy of the onscreen depth/stencil buffer, and
1587  * the following draw should only copy back the part that was modified. */
1588 static void depth_buffer2_test(IDirect3DDevice8 *device)
1589 {
1590     static const struct vertex quad[] =
1591     {
1592         { -1.0,  1.0, 0.66f, 0xffff0000},
1593         {  1.0,  1.0, 0.66f, 0xffff0000},
1594         { -1.0, -1.0, 0.66f, 0xffff0000},
1595         {  1.0, -1.0, 0.66f, 0xffff0000},
1596     };
1597
1598     IDirect3DSurface8 *backbuffer, *rt1, *rt2;
1599     IDirect3DSurface8 *depth_stencil;
1600     unsigned int i, j;
1601     D3DVIEWPORT8 vp;
1602     D3DCOLOR color;
1603     HRESULT hr;
1604
1605     vp.X = 0;
1606     vp.Y = 0;
1607     vp.Width = 640;
1608     vp.Height = 480;
1609     vp.MinZ = 0.0;
1610     vp.MaxZ = 1.0;
1611
1612     hr = IDirect3DDevice8_SetViewport(device, &vp);
1613     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
1614
1615     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1616     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1617     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
1618     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1619     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
1620     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1621     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
1622     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1623     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
1624     ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
1625
1626     hr = IDirect3DDevice8_CreateRenderTarget(device, 640, 480, D3DFMT_A8R8G8B8,
1627             D3DMULTISAMPLE_NONE, FALSE, &rt1);
1628     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
1629     hr = IDirect3DDevice8_CreateRenderTarget(device, 480, 360, D3DFMT_A8R8G8B8,
1630             D3DMULTISAMPLE_NONE, FALSE, &rt2);
1631     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
1632     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &depth_stencil);
1633     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1634     hr = IDirect3DDevice8_GetRenderTarget(device, &backbuffer);
1635     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1636
1637     hr = IDirect3DDevice8_SetRenderTarget(device, rt1, depth_stencil);
1638     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1639     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0);
1640     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
1641
1642     hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depth_stencil);
1643     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1644     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff00ff00, 0.5f, 0);
1645     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
1646
1647     hr = IDirect3DDevice8_SetRenderTarget(device, rt2, depth_stencil);
1648     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1649     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 0.0f, 0);
1650     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
1651
1652     hr = IDirect3DDevice8_SetRenderTarget(device, backbuffer, depth_stencil);
1653     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1654     IDirect3DSurface8_Release(depth_stencil);
1655     IDirect3DSurface8_Release(backbuffer);
1656     IDirect3DSurface8_Release(rt2);
1657     IDirect3DSurface8_Release(rt1);
1658
1659     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, FALSE);
1660     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1661
1662     hr = IDirect3DDevice8_BeginScene(device);
1663     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
1664     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
1665     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1666     hr = IDirect3DDevice8_EndScene(device);
1667     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
1668
1669     for (i = 0; i < 4; ++i)
1670     {
1671         for (j = 0; j < 4; ++j)
1672         {
1673             unsigned int x = 80 * ((2 * j) + 1);
1674             unsigned int y = 60 * ((2 * i) + 1);
1675             color = getPixelColor(device, x, y);
1676             ok(color_match(color, D3DCOLOR_ARGB(0x00, 0x00, 0xff, 0x00), 0),
1677                     "Expected color 0x0000ff00 %u,%u, got 0x%08x.\n", x, y, color);
1678         }
1679     }
1680
1681     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1682     ok(SUCCEEDED(hr), "Present failed (0x%08x)\n", hr);
1683 }
1684
1685 static void intz_test(IDirect3DDevice8 *device)
1686 {
1687     static const DWORD ps_code[] =
1688     {
1689         0xffff0101,                                                             /* ps_1_1                       */
1690         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1.0, 0.0, 0.0, 0.0   */
1691         0x00000051, 0xa00f0001, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c1, 0.0, 1.0, 0.0, 0.0   */
1692         0x00000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, /* def c2, 0.0, 0.0, 1.0, 0.0   */
1693         0x00000042, 0xb00f0000,                                                 /* tex t0                       */
1694         0x00000042, 0xb00f0001,                                                 /* tex t1                       */
1695         0x00000008, 0xb0070001, 0xa0e40000, 0xb0e40001,                         /* dp3 t1.xyz, c0, t1           */
1696         0x00000005, 0x80070000, 0xa0e40001, 0xb0e40001,                         /* mul r0.xyz, c1, t1           */
1697         0x00000004, 0x80070000, 0xa0e40000, 0xb0e40000, 0x80e40000,             /* mad r0.xyz, c0, t0, r0       */
1698         0x40000001, 0x80080000, 0xa0aa0002,                                     /* +mov r0.w, c2.z              */
1699         0x0000ffff,                                                             /* end                          */
1700     };
1701     struct
1702     {
1703         float x, y, z;
1704         float s0, t0, p0;
1705         float s1, t1, p1, q1;
1706     }
1707     quad[] =
1708     {
1709         { -1.0f,  1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f},
1710         {  1.0f,  1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f},
1711         { -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
1712         {  1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f},
1713     };
1714     struct
1715     {
1716         UINT x, y;
1717         D3DCOLOR color;
1718     }
1719     expected_colors[] =
1720     {
1721         {400,  60, D3DCOLOR_ARGB(0x00, 0x9f, 0xff, 0x00)},
1722         {560, 180, D3DCOLOR_ARGB(0x00, 0xdf, 0x55, 0x00)},
1723         {560, 300, D3DCOLOR_ARGB(0x00, 0xdf, 0x66, 0x00)},
1724         {400, 420, D3DCOLOR_ARGB(0x00, 0x9f, 0xb6, 0x00)},
1725         {240, 420, D3DCOLOR_ARGB(0x00, 0x60, 0x6d, 0x00)},
1726         { 80, 300, D3DCOLOR_ARGB(0x00, 0x20, 0x33, 0x00)},
1727         { 80, 180, D3DCOLOR_ARGB(0x00, 0x20, 0x55, 0x00)},
1728         {240,  60, D3DCOLOR_ARGB(0x00, 0x60, 0xff, 0x00)},
1729     };
1730
1731     IDirect3DSurface8 *original_ds, *original_rt, *rt;
1732     IDirect3DTexture8 *texture;
1733     IDirect3DSurface8 *ds;
1734     IDirect3D8 *d3d8;
1735     D3DCAPS8 caps;
1736     HRESULT hr;
1737     DWORD ps;
1738     UINT i;
1739
1740     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
1741     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1742     if (caps.PixelShaderVersion < D3DPS_VERSION(1, 1))
1743     {
1744         skip("No pixel shader 1.1 support, skipping INTZ test.\n");
1745         return;
1746     }
1747
1748     hr = IDirect3DDevice8_GetDirect3D(device, &d3d8);
1749     ok(SUCCEEDED(hr), "GetDirect3D failed, hr %#x.\n", hr);
1750
1751     hr = IDirect3D8_CheckDeviceFormat(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
1752             D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, MAKEFOURCC('I','N','T','Z'));
1753     if (FAILED(hr))
1754     {
1755         skip("No INTZ support, skipping INTZ test.\n");
1756         return;
1757     }
1758
1759     IDirect3D8_Release(d3d8);
1760
1761     hr = IDirect3DDevice8_GetRenderTarget(device, &original_rt);
1762     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1763     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &original_ds);
1764     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1765
1766     hr = IDirect3DDevice8_CreateTexture(device, 1024, 1024, 1,
1767             D3DUSAGE_DEPTHSTENCIL, MAKEFOURCC('I','N','T','Z'), D3DPOOL_DEFAULT, &texture);
1768     ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
1769     hr = IDirect3DDevice8_CreateRenderTarget(device, 1024, 1024, D3DFMT_A8R8G8B8,
1770             D3DMULTISAMPLE_NONE, FALSE, &rt);
1771     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
1772     hr = IDirect3DDevice8_CreatePixelShader(device, ps_code, &ps);
1773     ok(SUCCEEDED(hr), "CreatePixelShader failed, hr %#x.\n", hr);
1774
1775     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_TEX2
1776             | D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEXCOORDSIZE4(1));
1777     ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
1778     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
1779     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1780     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
1781     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1782     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
1783     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1784     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1785     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1786
1787     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DTEXF_POINT);
1788     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1789     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
1790     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1791     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
1792     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1793     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
1794     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1795
1796     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
1797     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1798     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
1799     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1800     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_MAGFILTER, D3DTEXF_POINT);
1801     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1802     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_MINFILTER, D3DTEXF_POINT);
1803     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1804     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_MIPFILTER, D3DTEXF_POINT);
1805     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1806     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS,
1807             D3DTTFF_COUNT4 | D3DTTFF_PROJECTED);
1808     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1809
1810     hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &ds);
1811     ok(SUCCEEDED(hr), "GetSurfaceLevel failed, hr %#x.\n", hr);
1812     hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
1813     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1814     IDirect3DDevice8_SetPixelShader(device, 0);
1815     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
1816
1817     /* Setup the depth/stencil surface. */
1818     hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
1819     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
1820
1821     hr = IDirect3DDevice8_BeginScene(device);
1822     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
1823     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
1824     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1825     hr = IDirect3DDevice8_EndScene(device);
1826     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
1827
1828     hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, NULL);
1829     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1830     IDirect3DSurface8_Release(ds);
1831     hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *)texture);
1832     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
1833     hr = IDirect3DDevice8_SetTexture(device, 1, (IDirect3DBaseTexture8 *)texture);
1834     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
1835     hr = IDirect3DDevice8_SetPixelShader(device, ps);
1836     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
1837
1838     /* Read the depth values back. */
1839     hr = IDirect3DDevice8_BeginScene(device);
1840     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
1841     hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
1842     ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
1843     hr = IDirect3DDevice8_EndScene(device);
1844     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
1845
1846     for (i = 0; i < sizeof(expected_colors) / sizeof(*expected_colors); ++i)
1847     {
1848         D3DCOLOR color = getPixelColor(device, expected_colors[i].x, expected_colors[i].y);
1849         ok(color_match(color, expected_colors[i].color, 1),
1850                 "Expected color 0x%08x at (%u, %u), got 0x%08x.\n",
1851                 expected_colors[i].color, expected_colors[i].x, expected_colors[i].y, color);
1852     }
1853
1854     hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
1855     ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
1856
1857     hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, original_ds);
1858     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
1859     IDirect3DSurface8_Release(original_ds);
1860     hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
1861     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
1862     hr = IDirect3DDevice8_SetTexture(device, 1, NULL);
1863     ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
1864     IDirect3DTexture8_Release(texture);
1865     hr = IDirect3DDevice8_SetPixelShader(device, 0);
1866     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
1867     hr = IDirect3DDevice8_DeletePixelShader(device, ps);
1868     ok(SUCCEEDED(hr), "DeletePixelShader failed, hr %#x.\n", hr);
1869
1870     IDirect3DSurface8_Release(original_rt);
1871     IDirect3DSurface8_Release(rt);
1872 }
1873
1874 static void shadow_test(IDirect3DDevice8 *device)
1875 {
1876     static const DWORD ps_code[] =
1877     {
1878         0xffff0101,                                                             /* ps_1_1                       */
1879         0x00000051, 0xa00f0000, 0x3f800000, 0x00000000, 0x00000000, 0x00000000, /* def c0, 1.0, 0.0, 0.0, 0.0   */
1880         0x00000051, 0xa00f0001, 0x00000000, 0x3f800000, 0x00000000, 0x00000000, /* def c1, 0.0, 1.0, 0.0, 0.0   */
1881         0x00000051, 0xa00f0002, 0x00000000, 0x00000000, 0x3f800000, 0x00000000, /* def c2, 0.0, 0.0, 1.0, 0.0   */
1882         0x00000042, 0xb00f0000,                                                 /* tex t0                       */
1883         0x00000042, 0xb00f0001,                                                 /* tex t1                       */
1884         0x00000008, 0xb0070001, 0xa0e40000, 0xb0e40001,                         /* dp3 t1.xyz, c0, t1           */
1885         0x00000005, 0x80070000, 0xa0e40001, 0xb0e40001,                         /* mul r0.xyz, c1, t1           */
1886         0x00000004, 0x80070000, 0xa0e40000, 0xb0e40000, 0x80e40000,             /* mad r0.xyz, c0, t0, r0       */
1887         0x40000001, 0x80080000, 0xa0aa0002,                                     /* +mov r0.w, c2.z              */
1888         0x0000ffff,                                                             /* end                          */
1889     };
1890     struct
1891     {
1892         D3DFORMAT format;
1893         const char *name;
1894     }
1895     formats[] =
1896     {
1897         {D3DFMT_D16_LOCKABLE,   "D3DFMT_D16_LOCKABLE"},
1898         {D3DFMT_D32,            "D3DFMT_D32"},
1899         {D3DFMT_D15S1,          "D3DFMT_D15S1"},
1900         {D3DFMT_D24S8,          "D3DFMT_D24S8"},
1901         {D3DFMT_D24X8,          "D3DFMT_D24X8"},
1902         {D3DFMT_D24X4S4,        "D3DFMT_D24X4S4"},
1903         {D3DFMT_D16,            "D3DFMT_D16"},
1904     };
1905     struct
1906     {
1907         float x, y, z;
1908         float s0, t0, p0;
1909         float s1, t1, p1, q1;
1910     }
1911     quad[] =
1912     {
1913         { -1.0f,  1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f},
1914         {  1.0f,  1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f},
1915         { -1.0f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
1916         {  1.0f, -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f},
1917     };
1918     struct
1919     {
1920         UINT x, y;
1921         D3DCOLOR color;
1922     }
1923     expected_colors[] =
1924     {
1925         {400,  60, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
1926         {560, 180, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00)},
1927         {560, 300, D3DCOLOR_ARGB(0x00, 0xff, 0x00, 0x00)},
1928         {400, 420, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00)},
1929         {240, 420, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00)},
1930         { 80, 300, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
1931         { 80, 180, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
1932         {240,  60, D3DCOLOR_ARGB(0x00, 0x00, 0x00, 0x00)},
1933     };
1934
1935     IDirect3DSurface8 *original_ds, *original_rt, *rt;
1936     IDirect3D8 *d3d8;
1937     D3DCAPS8 caps;
1938     HRESULT hr;
1939     DWORD ps;
1940     UINT i;
1941
1942     hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
1943     ok(SUCCEEDED(hr), "GetDeviceCaps failed, hr %#x.\n", hr);
1944     if (caps.PixelShaderVersion < D3DPS_VERSION(1, 1))
1945     {
1946         skip("No pixel shader 1.1 support, skipping shadow test.\n");
1947         return;
1948     }
1949
1950     hr = IDirect3DDevice8_GetDirect3D(device, &d3d8);
1951     ok(SUCCEEDED(hr), "GetDirect3D failed, hr %#x.\n", hr);
1952     hr = IDirect3DDevice8_GetRenderTarget(device, &original_rt);
1953     ok(SUCCEEDED(hr), "GetRenderTarget failed, hr %#x.\n", hr);
1954     hr = IDirect3DDevice8_GetDepthStencilSurface(device, &original_ds);
1955     ok(SUCCEEDED(hr), "GetDepthStencilSurface failed, hr %#x.\n", hr);
1956
1957     hr = IDirect3DDevice8_CreateRenderTarget(device, 1024, 1024, D3DFMT_A8R8G8B8,
1958             D3DMULTISAMPLE_NONE, FALSE, &rt);
1959     ok(SUCCEEDED(hr), "CreateRenderTarget failed, hr %#x.\n", hr);
1960     hr = IDirect3DDevice8_CreatePixelShader(device, ps_code, &ps);
1961     ok(SUCCEEDED(hr), "CreatePixelShader failed, hr %#x.\n", hr);
1962
1963     hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_TEX2
1964             | D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEXCOORDSIZE4(1));
1965     ok(SUCCEEDED(hr), "SetVertexShader failed, hr %#x.\n", hr);
1966     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_TRUE);
1967     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1968     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZFUNC, D3DCMP_ALWAYS);
1969     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1970     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZWRITEENABLE, TRUE);
1971     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1972     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
1973     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
1974
1975     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DTEXF_POINT);
1976     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1977     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MIPFILTER, D3DTEXF_POINT);
1978     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1979     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DTEXF_POINT);
1980     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1981     hr = IDirect3DDevice8_SetTextureStageState(device, 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT3);
1982     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1983
1984     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
1985     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1986     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
1987     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1988     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_MAGFILTER, D3DTEXF_POINT);
1989     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1990     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_MINFILTER, D3DTEXF_POINT);
1991     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1992     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_MIPFILTER, D3DTEXF_POINT);
1993     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1994     hr = IDirect3DDevice8_SetTextureStageState(device, 1, D3DTSS_TEXTURETRANSFORMFLAGS,
1995             D3DTTFF_COUNT4 | D3DTTFF_PROJECTED);
1996     ok(SUCCEEDED(hr), "SetTextureStageState failed, hr %#x.\n", hr);
1997
1998     for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i)
1999     {
2000         D3DFORMAT format = formats[i].format;
2001         IDirect3DTexture8 *texture;
2002         IDirect3DSurface8 *ds;
2003         unsigned int j;
2004
2005         hr = IDirect3D8_CheckDeviceFormat(d3d8, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8,
2006                 D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, format);
2007         if (FAILED(hr)) continue;
2008
2009         hr = IDirect3DDevice8_CreateTexture(device, 1024, 1024, 1,
2010                 D3DUSAGE_DEPTHSTENCIL, format, D3DPOOL_DEFAULT, &texture);
2011         ok(SUCCEEDED(hr), "CreateTexture failed, hr %#x.\n", hr);
2012
2013         hr = IDirect3DTexture8_GetSurfaceLevel(texture, 0, &ds);
2014         ok(SUCCEEDED(hr), "GetSurfaceLevel failed, hr %#x.\n", hr);
2015
2016         hr = IDirect3DDevice8_SetRenderTarget(device, rt, ds);
2017         ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2018
2019         IDirect3DDevice8_SetPixelShader(device, 0);
2020         ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
2021
2022         /* Setup the depth/stencil surface. */
2023         hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
2024         ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
2025
2026         hr = IDirect3DDevice8_BeginScene(device);
2027         ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2028         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
2029         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2030         hr = IDirect3DDevice8_EndScene(device);
2031         ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2032
2033         hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, NULL);
2034         ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2035         IDirect3DSurface8_Release(ds);
2036
2037         hr = IDirect3DDevice8_SetTexture(device, 0, (IDirect3DBaseTexture8 *)texture);
2038         ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2039         hr = IDirect3DDevice8_SetTexture(device, 1, (IDirect3DBaseTexture8 *)texture);
2040         ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2041
2042         hr = IDirect3DDevice8_SetPixelShader(device, ps);
2043         ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
2044
2045         /* Do the actual shadow mapping. */
2046         hr = IDirect3DDevice8_BeginScene(device);
2047         ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2048         hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad));
2049         ok(SUCCEEDED(hr), "DrawPrimitiveUP failed, hr %#x.\n", hr);
2050         hr = IDirect3DDevice8_EndScene(device);
2051         ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2052
2053         hr = IDirect3DDevice8_SetTexture(device, 0, NULL);
2054         ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2055         hr = IDirect3DDevice8_SetTexture(device, 1, NULL);
2056         ok(SUCCEEDED(hr), "SetTexture failed, hr %#x.\n", hr);
2057         IDirect3DTexture8_Release(texture);
2058
2059         for (j = 0; j < sizeof(expected_colors) / sizeof(*expected_colors); ++j)
2060         {
2061             D3DCOLOR color = getPixelColor(device, expected_colors[j].x, expected_colors[j].y);
2062             ok(color_match(color, expected_colors[j].color, 0),
2063                     "Expected color 0x%08x at (%u, %u) for format %s, got 0x%08x.\n",
2064                     expected_colors[j].color, expected_colors[j].x, expected_colors[j].y,
2065                     formats[i].name, color);
2066         }
2067
2068         hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
2069         ok(SUCCEEDED(hr), "Present failed, hr %#x.\n", hr);
2070     }
2071
2072     hr = IDirect3DDevice8_SetPixelShader(device, 0);
2073     ok(SUCCEEDED(hr), "SetPixelShader failed, hr %#x.\n", hr);
2074     hr = IDirect3DDevice8_DeletePixelShader(device, ps);
2075     ok(SUCCEEDED(hr), "DeletePixelShader failed, hr %#x.\n", hr);
2076
2077     hr = IDirect3DDevice8_SetRenderTarget(device, original_rt, original_ds);
2078     ok(SUCCEEDED(hr), "SetRenderTarget failed, hr %#x.\n", hr);
2079     IDirect3DSurface8_Release(original_ds);
2080
2081     IDirect3DSurface8_Release(original_rt);
2082     IDirect3DSurface8_Release(rt);
2083
2084     IDirect3D8_Release(d3d8);
2085 }
2086
2087 START_TEST(visual)
2088 {
2089     IDirect3DDevice8 *device_ptr;
2090     HRESULT hr;
2091     DWORD color;
2092     D3DCAPS8 caps;
2093
2094     d3d8_handle = LoadLibraryA("d3d8.dll");
2095     if (!d3d8_handle)
2096     {
2097         win_skip("Could not load d3d8.dll\n");
2098         return;
2099     }
2100
2101     device_ptr = init_d3d8();
2102     if (!device_ptr)
2103     {
2104         win_skip("Could not initialize direct3d\n");
2105         return;
2106     }
2107
2108     IDirect3DDevice8_GetDeviceCaps(device_ptr, &caps);
2109
2110     /* Check for the reliability of the returned data */
2111     hr = IDirect3DDevice8_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
2112     if(FAILED(hr))
2113     {
2114         skip("Clear failed, can't assure correctness of the test results\n");
2115         goto cleanup;
2116     }
2117
2118     color = getPixelColor(device_ptr, 1, 1);
2119     if(color !=0x00ff0000)
2120     {
2121         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests\n", color);
2122         goto cleanup;
2123     }
2124     IDirect3DDevice8_Present(device_ptr, NULL, NULL, NULL, NULL);
2125
2126     hr = IDirect3DDevice8_Clear(device_ptr, 0, NULL, D3DCLEAR_TARGET, 0xff00ddee, 0.0, 0);
2127     if(FAILED(hr))
2128     {
2129         skip("Clear failed, can't assure correctness of the test results\n");
2130         goto cleanup;
2131     }
2132
2133     color = getPixelColor(device_ptr, 639, 479);
2134     if(color != 0x0000ddee)
2135     {
2136         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests\n", color);
2137         goto cleanup;
2138     }
2139     IDirect3DDevice8_Present(device_ptr, NULL, NULL, NULL, NULL);
2140
2141     /* Now run the real test */
2142     depth_clamp_test(device_ptr);
2143     lighting_test(device_ptr);
2144     clear_test(device_ptr);
2145     fog_test(device_ptr);
2146     present_test(device_ptr);
2147     offscreen_test(device_ptr);
2148     alpha_test(device_ptr);
2149
2150     if (caps.VertexShaderVersion >= D3DVS_VERSION(1, 1))
2151     {
2152         test_rcp_rsq(device_ptr);
2153     }
2154     else
2155     {
2156         skip("No vs.1.1 support\n");
2157     }
2158
2159     p8_texture_test(device_ptr);
2160     texop_test(device_ptr);
2161     depth_buffer_test(device_ptr);
2162     depth_buffer2_test(device_ptr);
2163     intz_test(device_ptr);
2164     shadow_test(device_ptr);
2165
2166 cleanup:
2167     if(device_ptr) {
2168         D3DDEVICE_CREATION_PARAMETERS creation_parameters;
2169         ULONG refcount;
2170
2171         IDirect3DDevice8_GetCreationParameters(device_ptr, &creation_parameters);
2172         DestroyWindow(creation_parameters.hFocusWindow);
2173         refcount = IDirect3DDevice8_Release(device_ptr);
2174         ok(!refcount, "Device has %u references left\n", refcount);
2175     }
2176 }