ddraw: Use a D24X8 depth buffer.
[wine] / dlls / ddraw / tests / visual.c
1 /*
2  * Copyright (C) 2007 Stefan Dösinger(for CodeWeavers)
3  * Copyright (C) 2008 Alexander Dorofeyev
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 #include <assert.h>
23 #include "wine/test.h"
24 #include "ddraw.h"
25 #include "d3d.h"
26
27 HWND window;
28 IDirectDraw7        *DirectDraw = NULL;
29 IDirectDrawSurface7 *Surface;
30 IDirectDrawSurface7 *depth_buffer;
31 IDirect3D7          *Direct3D = NULL;
32 IDirect3DDevice7    *Direct3DDevice = NULL;
33
34 IDirectDraw *DirectDraw1 = NULL;
35 IDirectDrawSurface *Surface1 = NULL;
36 IDirect3D *Direct3D1 = NULL;
37 IDirect3DDevice *Direct3DDevice1 = NULL;
38 IDirect3DExecuteBuffer *ExecuteBuffer = NULL;
39 IDirect3DViewport *Viewport = NULL;
40
41 static BOOL refdevice = FALSE;
42
43 static HRESULT (WINAPI *pDirectDrawCreateEx)(LPGUID,LPVOID*,REFIID,LPUNKNOWN);
44
45 static BOOL color_match(D3DCOLOR c1, D3DCOLOR c2, BYTE max_diff)
46 {
47     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
48     c1 >>= 8; c2 >>= 8;
49     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
50     c1 >>= 8; c2 >>= 8;
51     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
52     c1 >>= 8; c2 >>= 8;
53     if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
54     return TRUE;
55 }
56
57 static BOOL createObjects(void)
58 {
59     HRESULT hr;
60     HMODULE hmod = GetModuleHandleA("ddraw.dll");
61     WNDCLASS wc = {0};
62     DDSURFACEDESC2 ddsd;
63
64
65     if(!hmod) return FALSE;
66     pDirectDrawCreateEx = (void*)GetProcAddress(hmod, "DirectDrawCreateEx");
67     if(!pDirectDrawCreateEx) return FALSE;
68
69     hr = pDirectDrawCreateEx(NULL, (void **) &DirectDraw, &IID_IDirectDraw7, NULL);
70     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreateEx returned: %x\n", hr);
71     if(!DirectDraw) goto err;
72
73     wc.lpfnWndProc = DefWindowProc;
74     wc.lpszClassName = "d3d7_test_wc";
75     RegisterClass(&wc);
76     window = CreateWindow("d3d7_test_wc", "d3d7_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
77
78     hr = IDirectDraw7_SetCooperativeLevel(DirectDraw, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
79     ok(hr == DD_OK, "IDirectDraw7_SetCooperativeLevel failed with %08x\n", hr);
80     if(FAILED(hr)) goto err;
81     hr = IDirectDraw7_SetDisplayMode(DirectDraw, 640, 480, 32, 0, 0);
82     if(FAILED(hr)) {
83         /* 24 bit is fine too */
84         hr = IDirectDraw7_SetDisplayMode(DirectDraw, 640, 480, 24, 0, 0);
85
86     }
87     ok(hr == DD_OK || hr == DDERR_UNSUPPORTED, "IDirectDraw7_SetDisplayMode failed with %08x\n", hr);
88     if(FAILED(hr)) {
89         /* use trace, the caller calls skip() */
90         trace("SetDisplayMode failed\n");
91         goto err;
92     }
93
94     hr = IDirectDraw7_QueryInterface(DirectDraw, &IID_IDirect3D7, (void**) &Direct3D);
95     if (hr == E_NOINTERFACE) goto err;
96     ok(hr==DD_OK, "QueryInterface returned: %08x\n", hr);
97
98     /* DirectDraw Flipping behavior doesn't seem that well-defined. The reference rasterizer behaves differently
99      * than hardware implementations. Request single buffering, that seems to work everywhere
100      */
101     memset(&ddsd, 0, sizeof(ddsd));
102     ddsd.dwSize = sizeof(ddsd);
103     ddsd.dwFlags = DDSD_CAPS;
104     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
105     ddsd.dwBackBufferCount = 1;
106     hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &Surface, NULL);
107     if(FAILED(hr)) goto err;
108
109     memset(&ddsd, 0, sizeof(ddsd));
110     ddsd.dwSize = sizeof(ddsd);
111     ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
112     ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;
113     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
114     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_ZBUFFER;
115     U1(U4(ddsd).ddpfPixelFormat).dwZBufferBitDepth = 32;
116     U3(U4(ddsd).ddpfPixelFormat).dwZBitMask = 0x00ffffff;
117     ddsd.dwWidth = 640;
118     ddsd.dwHeight = 480;
119     hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &depth_buffer, NULL);
120     ok(SUCCEEDED(hr), "CreateSurface failed, hr %#x.\n", hr);
121     if (FAILED(hr)) goto err;
122
123     hr = IDirectDrawSurface_AddAttachedSurface(Surface, depth_buffer);
124     ok(SUCCEEDED(hr), "AddAttachedSurface failed, hr %#x.\n", hr);
125     if (FAILED(hr)) goto err;
126
127     hr = IDirect3D7_CreateDevice(Direct3D, &IID_IDirect3DTnLHalDevice, Surface, &Direct3DDevice);
128     if(FAILED(hr))
129     {
130         trace("Creating a TnLHal Device failed, trying HAL\n");
131         hr = IDirect3D7_CreateDevice(Direct3D, &IID_IDirect3DHALDevice, Surface, &Direct3DDevice);
132         if(FAILED(hr))
133         {
134             trace("Creating a HAL device failed, trying Ref\n");
135             hr = IDirect3D7_CreateDevice(Direct3D, &IID_IDirect3DRefDevice, Surface, &Direct3DDevice);
136             if (SUCCEEDED(hr))
137                 refdevice = TRUE;
138         }
139     }
140     if(!Direct3DDevice) goto err;
141     return TRUE;
142
143     err:
144     if(DirectDraw) IDirectDraw7_Release(DirectDraw);
145     if (depth_buffer) IDirectDrawSurface7_Release(depth_buffer);
146     if(Surface) IDirectDrawSurface7_Release(Surface);
147     if(Direct3D) IDirect3D7_Release(Direct3D);
148     if(Direct3DDevice) IDirect3DDevice7_Release(Direct3DDevice);
149     if(window) DestroyWindow(window);
150     return FALSE;
151 }
152
153 static void releaseObjects(void)
154 {
155     IDirect3DDevice7_Release(Direct3DDevice);
156     IDirect3D7_Release(Direct3D);
157     IDirectDrawSurface7_Release(depth_buffer);
158     IDirectDrawSurface7_Release(Surface);
159     IDirectDraw7_Release(DirectDraw);
160     DestroyWindow(window);
161 }
162
163 static DWORD getPixelColor(IDirect3DDevice7 *device, UINT x, UINT y)
164 {
165     DWORD ret;
166     HRESULT hr;
167     DDSURFACEDESC2 ddsd;
168     RECT rectToLock = {x, y, x+1, y+1};
169     IDirectDrawSurface7 *surf = NULL;
170
171     /* Some implementations seem to dislike direct locking on the front buffer. Thus copy the front buffer
172      * to an offscreen surface and lock it instead of the front buffer
173      */
174     memset(&ddsd, 0, sizeof(ddsd));
175     ddsd.dwSize = sizeof(ddsd);
176     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
177     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
178     ddsd.dwWidth = 640;
179     ddsd.dwHeight = 480;
180     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
181     hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &surf, NULL);
182     ok(hr == DD_OK, "IDirectDraw7_CreateSurface failed with %08x\n", hr);
183     if(!surf)
184     {
185         trace("cannot create helper surface\n");
186         return 0xdeadbeef;
187     }
188
189     memset(&ddsd, 0, sizeof(ddsd));
190     ddsd.dwSize = sizeof(ddsd);
191     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
192
193     hr = IDirectDrawSurface_BltFast(surf, 0, 0, Surface, NULL, 0);
194     ok(hr == DD_OK, "IDirectDrawSurface7_BltFast returned %08x\n", hr);
195     if(FAILED(hr))
196     {
197         trace("Cannot blit\n");
198         ret = 0xdeadbee;
199         goto out;
200     }
201
202     hr = IDirectDrawSurface7_Lock(surf, &rectToLock, &ddsd, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
203     if(FAILED(hr))
204     {
205         trace("Can't lock the offscreen surface, hr=%08x\n", hr);
206         ret = 0xdeadbeec;
207         goto out;
208     }
209
210     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
211      * really important for these tests
212      */
213     ret = ((DWORD *) ddsd.lpSurface)[0] & 0x00ffffff;
214     hr = IDirectDrawSurface7_Unlock(surf, NULL);
215     if(FAILED(hr))
216     {
217         trace("Can't unlock the offscreen surface, hr=%08x\n", hr);
218     }
219
220 out:
221     IDirectDrawSurface7_Release(surf);
222     return ret;
223 }
224
225 /*
226  * Helper function to get and set the viewport - needed on geforce 8800 on XP - driver bug?
227  * This is needed after IDirect3DDevice7_SetRenderTarget in combination with offscreen to backbuffer rendering.
228  */
229 static void set_the_same_viewport_again(IDirect3DDevice7 *device)
230 {
231     D3DVIEWPORT7 vp = {0};
232     HRESULT hr;
233     hr = IDirect3DDevice7_GetViewport(device,&vp);
234     ok(hr == D3D_OK && vp.dwWidth == 640 && vp.dwHeight == 480, "IDirect3DDevice7_SetViewport returned %08x\n", hr);
235     hr = IDirect3DDevice7_SetViewport(device, &vp);
236     ok(hr == D3D_OK, "IDirect3DDevice7_SetViewport returned %08x\n", hr);
237     return;
238 }
239
240 struct vertex
241 {
242     float x, y, z;
243     DWORD diffuse;
244 };
245
246 struct tvertex
247 {
248     float x, y, z, w;
249     DWORD diffuse;
250 };
251
252 struct nvertex
253 {
254     float x, y, z;
255     float nx, ny, nz;
256     DWORD diffuse;
257 };
258
259 static void lighting_test(IDirect3DDevice7 *device)
260 {
261     HRESULT hr;
262     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
263     DWORD nfvf = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_NORMAL;
264     DWORD color;
265
266     float mat[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
267                       0.0f, 1.0f, 0.0f, 0.0f,
268                       0.0f, 0.0f, 1.0f, 0.0f,
269                       0.0f, 0.0f, 0.0f, 1.0f };
270
271     struct vertex unlitquad[] =
272     {
273         {-1.0f, -1.0f,   0.1f,                          0xffff0000},
274         {-1.0f,  0.0f,   0.1f,                          0xffff0000},
275         { 0.0f,  0.0f,   0.1f,                          0xffff0000},
276         { 0.0f, -1.0f,   0.1f,                          0xffff0000},
277     };
278     struct vertex litquad[] =
279     {
280         {-1.0f,  0.0f,   0.1f,                          0xff00ff00},
281         {-1.0f,  1.0f,   0.1f,                          0xff00ff00},
282         { 0.0f,  1.0f,   0.1f,                          0xff00ff00},
283         { 0.0f,  0.0f,   0.1f,                          0xff00ff00},
284     };
285     struct nvertex unlitnquad[] =
286     {
287         { 0.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
288         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
289         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
290         { 1.0f, -1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xff0000ff},
291     };
292     struct nvertex litnquad[] =
293     {
294         { 0.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
295         { 0.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
296         { 1.0f,  1.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
297         { 1.0f,  0.0f,   0.1f,  1.0f,   1.0f,   1.0f,   0xffffff00},
298     };
299     WORD Indices[] = {0, 1, 2, 2, 3, 0};
300
301     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
302     ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
303
304     /* Setup some states that may cause issues */
305     hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_WORLD, (D3DMATRIX *) mat);
306     ok(hr == D3D_OK, "IDirect3DDevice7_SetTransform returned %08x\n", hr);
307     hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, (D3DMATRIX *)mat);
308     ok(hr == D3D_OK, "IDirect3DDevice7_SetTransform returned %08x\n", hr);
309     hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, (D3DMATRIX *) mat);
310     ok(hr == D3D_OK, "IDirect3DDevice7_SetTransform returned %08x\n", hr);
311     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
312     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
313     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
314     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
315     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
316     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
317     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_STENCILENABLE, FALSE);
318     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
319     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
320     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
321     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
322     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
323     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
324     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed with %08x\n", hr);
325
326     hr = IDirect3DDevice7_BeginScene(device);
327     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
328     if(hr == D3D_OK)
329     {
330         /* No lights are defined... That means, lit vertices should be entirely black */
331         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
332         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
333         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, unlitquad, 4 /* NumVerts */,
334                                                     Indices, 6 /* Indexcount */, 0 /* flags */);
335         ok(hr == D3D_OK, "IDirect3DDevice7_DrawIndexedPrimitiveUP failed with %08x\n", hr);
336
337         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
338         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
339         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, litquad, 4 /* NumVerts */,
340                                                     Indices, 6 /* Indexcount */, 0 /* flags */);
341         ok(hr == D3D_OK, "IDirect3DDevice7_DrawIndexedPrimitiveUP failed with %08x\n", hr);
342
343         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
344         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
345         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, unlitnquad, 4 /* NumVerts */,
346                                                     Indices, 6 /* Indexcount */, 0 /* flags */);
347         ok(hr == D3D_OK, "IDirect3DDevice7_DrawIndexedPrimitiveUP failed with %08x\n", hr);
348
349         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, TRUE);
350         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
351         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, nfvf, litnquad, 4 /* NumVerts */,
352                                                     Indices, 6 /* Indexcount */, 0 /* flags */);
353         ok(hr == D3D_OK, "IDirect3DDevice7_DrawIndexedPrimitiveUP failed with %08x\n", hr);
354
355         IDirect3DDevice7_EndScene(device);
356         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed with %08x\n", hr);
357     }
358
359     color = getPixelColor(device, 160, 360); /* lower left quad - unlit without normals */
360     ok(color == 0x00ff0000, "Unlit quad without normals has color %08x\n", color);
361     color = getPixelColor(device, 160, 120); /* upper left quad - lit without normals */
362     ok(color == 0x00000000, "Lit quad without normals has color %08x\n", color);
363     color = getPixelColor(device, 480, 360); /* lower left quad - unlit width normals */
364     ok(color == 0x000000ff, "Unlit quad width normals has color %08x\n", color);
365     color = getPixelColor(device, 480, 120); /* upper left quad - lit width normals */
366     ok(color == 0x00000000, "Lit quad width normals has color %08x\n", color);
367
368     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
369     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned %08x\n", hr);
370 }
371
372 static void clear_test(IDirect3DDevice7 *device)
373 {
374     /* Tests the correctness of clearing parameters */
375     HRESULT hr;
376     D3DRECT rect[2];
377     D3DRECT rect_negneg;
378     DWORD color;
379
380     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
381     ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
382
383     /* Positive x, negative y */
384     U1(rect[0]).x1 = 0;
385     U2(rect[0]).y1 = 480;
386     U3(rect[0]).x2 = 320;
387     U4(rect[0]).y2 = 240;
388
389     /* Positive x, positive y */
390     U1(rect[1]).x1 = 0;
391     U2(rect[1]).y1 = 0;
392     U3(rect[1]).x2 = 320;
393     U4(rect[1]).y2 = 240;
394     /* Clear 2 rectangles with one call. Shows that a positive value is returned, but the negative rectangle
395      * is ignored, the positive is still cleared afterwards
396      */
397     hr = IDirect3DDevice7_Clear(device, 2, rect, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
398     ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
399
400     /* negative x, negative y */
401     U1(rect_negneg).x1 = 640;
402     U2(rect_negneg).y1 = 240;
403     U3(rect_negneg).x2 = 320;
404     U4(rect_negneg).y2 = 0;
405     hr = IDirect3DDevice7_Clear(device, 1, &rect_negneg, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
406     ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
407
408     color = getPixelColor(device, 160, 360); /* lower left quad */
409     ok(color == 0x00ffffff, "Clear rectangle 3(pos, neg) has color %08x\n", color);
410     color = getPixelColor(device, 160, 120); /* upper left quad */
411     ok(color == 0x00ff0000, "Clear rectangle 1(pos, pos) has color %08x\n", color);
412     color = getPixelColor(device, 480, 360); /* lower right quad  */
413     ok(color == 0x00ffffff, "Clear rectangle 4(NULL) has color %08x\n", color);
414     color = getPixelColor(device, 480, 120); /* upper right quad */
415     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
416 }
417
418 struct sVertex {
419     float x, y, z;
420     DWORD diffuse;
421     DWORD specular;
422 };
423
424 struct sVertexT {
425     float x, y, z, rhw;
426     DWORD diffuse;
427     DWORD specular;
428 };
429
430 static void fog_test(IDirect3DDevice7 *device)
431 {
432     HRESULT hr;
433     DWORD color;
434     float start = 0.0, end = 1.0;
435     D3DDEVICEDESC7 caps;
436
437     /* Gets full z based fog with linear fog, no fog with specular color */
438     struct sVertex unstransformed_1[] = {
439         {-1,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
440         {-1,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
441         { 0,     0,   0.1f,         0xFFFF0000,     0xFF000000  },
442         { 0,    -1,   0.1f,         0xFFFF0000,     0xFF000000  },
443     };
444     /* Ok, I am too lazy to deal with transform matrices */
445     struct sVertex unstransformed_2[] = {
446         {-1,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
447         {-1,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
448         { 0,     1,   1.0f,         0xFFFF0000,     0xFF000000  },
449         { 0,     0,   1.0f,         0xFFFF0000,     0xFF000000  },
450     };
451     /* Untransformed ones. Give them a different diffuse color to make the test look
452      * nicer. It also makes making sure that they are drawn correctly easier.
453      */
454     struct sVertexT transformed_1[] = {
455         {320,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
456         {640,    0,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
457         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
458         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
459     };
460     struct sVertexT transformed_2[] = {
461         {320,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
462         {640,  240,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
463         {640,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
464         {320,  480,   1.0f, 1.0f,   0xFFFFFF00,     0xFF000000  },
465     };
466     WORD Indices[] = {0, 1, 2, 2, 3, 0};
467
468     memset(&caps, 0, sizeof(caps));
469     hr = IDirect3DDevice7_GetCaps(device, &caps);
470     ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
471     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
472     ok(hr == D3D_OK, "IDirect3DDevice7_Clear returned %08x\n", hr);
473
474     /* Setup initial states: No lighting, fog on, fog color */
475     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
476     ok(hr == D3D_OK, "Turning off lighting returned %08x\n", hr);
477     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
478     ok(hr == D3D_OK, "Turning on fog calculations returned %08x\n", hr);
479     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0xFF00FF00 /* A nice green */);
480     ok(hr == D3D_OK, "Turning on fog calculations returned %08x\n", hr);
481
482     /* First test: Both table fog and vertex fog off */
483     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE);
484     ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
485     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_NONE);
486     ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
487
488     /* Start = 0, end = 1. Should be default, but set them */
489     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, *((DWORD *) &start));
490     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
491     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, *((DWORD *) &end));
492     ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
493
494     if(IDirect3DDevice7_BeginScene(device) == D3D_OK)
495     {
496         /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
497         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
498                                                    unstransformed_1, 4, Indices, 6, 0);
499         ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
500
501         /* That makes it use the Z value */
502         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_LINEAR);
503         ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
504         /* Untransformed, vertex fog != none (or table fog != none):
505          * Use the Z value as input into the equation
506          */
507         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
508                                                    unstransformed_2, 4, Indices, 6, 0);
509         ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
510
511         /* transformed verts */
512         ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
513         /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
514         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
515                                                    transformed_1, 4, Indices, 6, 0);
516         ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
517
518         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_LINEAR);
519         ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
520         /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
521          * equation
522          */
523         hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
524                                                    transformed_2, 4, Indices, 6, 0);
525         ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
526
527         hr = IDirect3DDevice7_EndScene(device);
528         ok(hr == D3D_OK, "EndScene returned %08x\n", hr);
529     }
530     else
531     {
532         ok(FALSE, "BeginScene failed\n");
533     }
534
535     color = getPixelColor(device, 160, 360);
536     ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color);
537     color = getPixelColor(device, 160, 120);
538     ok(color == 0x0000FF00, "Untransformed vertex with linear vertex fog has color %08x\n", color);
539     color = getPixelColor(device, 480, 120);
540     ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
541     if(caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_FOGTABLE)
542     {
543         color = getPixelColor(device, 480, 360);
544         ok(color == 0x0000FF00, "Transformed vertex with linear table fog has color %08x\n", color);
545     }
546     else
547     {
548         /* Without fog table support the vertex fog is still applied, even though table fog is turned on.
549          * The settings above result in no fogging with vertex fog
550          */
551         color = getPixelColor(device, 480, 120);
552         ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
553         trace("Info: Table fog not supported by this device\n");
554     }
555
556     /* Turn off the fog master switch to avoid confusing other tests */
557     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
558     ok(hr == D3D_OK, "Turning off fog calculations returned %08x\n", hr);
559 }
560
561 static void offscreen_test(IDirect3DDevice7 *device)
562 {
563     HRESULT hr;
564     IDirectDrawSurface7 *backbuffer = NULL, *offscreen = NULL;
565     DWORD color;
566     DDSURFACEDESC2 ddsd;
567
568     static const float quad[][5] = {
569         {-0.5f, -0.5f, 0.1f, 0.0f, 0.0f},
570         {-0.5f,  0.5f, 0.1f, 0.0f, 1.0f},
571         { 0.5f, -0.5f, 0.1f, 1.0f, 0.0f},
572         { 0.5f,  0.5f, 0.1f, 1.0f, 1.0f},
573     };
574
575     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
576     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
577
578     memset(&ddsd, 0, sizeof(ddsd));
579     ddsd.dwSize = sizeof(ddsd);
580     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
581     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
582     ddsd.dwWidth = 128;
583     ddsd.dwHeight = 128;
584     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
585     hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &offscreen, NULL);
586     ok(hr == D3D_OK, "Creating the offscreen render target failed, hr = %08x\n", hr);
587     if(!offscreen) {
588         goto out;
589     }
590
591     hr = IDirect3DDevice7_GetRenderTarget(device, &backbuffer);
592     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
593     if(!backbuffer) {
594         goto out;
595     }
596
597     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
598     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
599     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
600     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
601     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DFILTER_NEAREST);
602     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
603     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DFILTER_NEAREST);
604     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
605     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
606     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState returned hr = %08x\n", hr);
607
608     if (refdevice) {
609         win_skip("Tests would crash on W2K with a refdevice\n");
610         goto out;
611     }
612
613     if(IDirect3DDevice7_BeginScene(device) == D3D_OK) {
614         hr = IDirect3DDevice7_SetRenderTarget(device, offscreen, 0);
615         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
616         hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
617         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
618
619         /* Draw without textures - Should result in a white quad */
620         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
621         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
622
623         hr = IDirect3DDevice7_SetRenderTarget(device, backbuffer, 0);
624         ok(hr == D3D_OK, "SetRenderTarget failed, hr = %08x\n", hr);
625         set_the_same_viewport_again(device);
626
627         hr = IDirect3DDevice7_SetTexture(device, 0, offscreen);
628         ok(hr == D3D_OK, "SetTexture failed, %08x\n", hr);
629
630         /* This time with the texture */
631         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, quad, 4, 0);
632         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
633
634         IDirect3DDevice7_EndScene(device);
635     }
636
637     /* Center quad - should be white */
638     color = getPixelColor(device, 320, 240);
639     ok(color == 0x00ffffff, "Offscreen failed: Got color 0x%08x, expected 0x00ffffff.\n", color);
640     /* Some quad in the cleared part of the texture */
641     color = getPixelColor(device, 170, 240);
642     ok(color == 0x00ff00ff, "Offscreen failed: Got color 0x%08x, expected 0x00ff00ff.\n", color);
643     /* Part of the originally cleared back buffer */
644     color = getPixelColor(device, 10, 10);
645     ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
646     if(0) {
647         /* Lower left corner of the screen, where back buffer offscreen rendering draws the offscreen texture.
648          * It should be red, but the offscreen texture may leave some junk there. Not tested yet. Depending on
649          * the offscreen rendering mode this test would succeed or fail
650          */
651         color = getPixelColor(device, 10, 470);
652         ok(color == 0x00ff0000, "Offscreen failed: Got color 0x%08x, expected 0x00ff0000.\n", color);
653     }
654
655 out:
656     hr = IDirect3DDevice7_SetTexture(device, 0, NULL);
657     ok(SUCCEEDED(hr), "IDirect3DDevice7_SetTexture returned %#x.\n", hr);
658
659     /* restore things */
660     if(backbuffer) {
661         hr = IDirect3DDevice7_SetRenderTarget(device, backbuffer, 0);
662         ok(SUCCEEDED(hr), "IDirect3DDevice7_SetRenderTarget returned %#x.\n", hr);
663         IDirectDrawSurface7_Release(backbuffer);
664     }
665     if(offscreen) {
666         IDirectDrawSurface7_Release(offscreen);
667     }
668 }
669
670 static void alpha_test(IDirect3DDevice7 *device)
671 {
672     HRESULT hr;
673     IDirectDrawSurface7 *backbuffer = NULL, *offscreen = NULL;
674     DWORD color, red, green, blue;
675     DDSURFACEDESC2 ddsd;
676
677     struct vertex quad1[] =
678     {
679         {-1.0f, -1.0f,   0.1f,                          0x4000ff00},
680         {-1.0f,  0.0f,   0.1f,                          0x4000ff00},
681         { 1.0f, -1.0f,   0.1f,                          0x4000ff00},
682         { 1.0f,  0.0f,   0.1f,                          0x4000ff00},
683     };
684     struct vertex quad2[] =
685     {
686         {-1.0f,  0.0f,   0.1f,                          0xc00000ff},
687         {-1.0f,  1.0f,   0.1f,                          0xc00000ff},
688         { 1.0f,  0.0f,   0.1f,                          0xc00000ff},
689         { 1.0f,  1.0f,   0.1f,                          0xc00000ff},
690     };
691     static const float composite_quad[][5] = {
692         { 0.0f, -1.0f, 0.1f, 0.0f, 1.0f},
693         { 0.0f,  1.0f, 0.1f, 0.0f, 0.0f},
694         { 1.0f, -1.0f, 0.1f, 1.0f, 1.0f},
695         { 1.0f,  1.0f, 0.1f, 1.0f, 0.0f},
696     };
697
698     /* Clear the render target with alpha = 0.5 */
699     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
700     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
701
702     memset(&ddsd, 0, sizeof(ddsd));
703     ddsd.dwSize = sizeof(ddsd);
704     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
705     ddsd.dwWidth = 128;
706     ddsd.dwHeight = 128;
707     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
708     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
709     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount      = 32;
710     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask         = 0x00ff0000;
711     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask         = 0x0000ff00;
712     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask         = 0x000000ff;
713     U5(U4(ddsd).ddpfPixelFormat).dwRGBAlphaBitMask  = 0xff000000;
714     hr = IDirectDraw7_CreateSurface(DirectDraw, &ddsd, &offscreen, NULL);
715     ok(hr == D3D_OK, "Creating the offscreen render target failed, hr = %08x\n", hr);
716     if(!offscreen) {
717         goto out;
718     }
719     hr = IDirect3DDevice7_GetRenderTarget(device, &backbuffer);
720     ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
721     if(!backbuffer) {
722         goto out;
723     }
724
725     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
726     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
727     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
728     ok(hr == D3D_OK, "SetTextureStageState failed, hr = %08x\n", hr);
729     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_MINFILTER, D3DFILTER_NEAREST);
730     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MINFILTER failed (0x%08x)\n", hr);
731     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_MAGFILTER, D3DFILTER_NEAREST);
732     ok(SUCCEEDED(hr), "SetTextureStageState D3DSAMP_MAGFILTER failed (0x%08x)\n", hr);
733
734     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, TRUE);
735     ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
736
737     if (refdevice) {
738         win_skip("Tests would crash on W2K with a refdevice\n");
739         goto out;
740     }
741
742     if(IDirect3DDevice7_BeginScene(device) == D3D_OK) {
743
744         /* Draw two quads, one with src alpha blending, one with dest alpha blending. The
745          * SRCALPHA / INVSRCALPHA blend doesn't give any surprises. Colors are blended based on
746          * the input alpha
747          *
748          * The DESTALPHA / INVDESTALPHA do not "work" on the regular buffer because there is no alpha.
749          * They give essentially ZERO and ONE blend factors
750          */
751         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
752         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
753         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
754         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
755         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad1, 4, 0);
756         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
757
758         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_DESTALPHA);
759         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
760         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVDESTALPHA);
761         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
762         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad2, 4, 0);
763         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
764
765         /* Switch to the offscreen buffer, and redo the testing. SRCALPHA and DESTALPHA. The offscreen buffer
766          * has a alpha channel on its own. Clear the offscreen buffer with alpha = 0.5 again, then draw the
767          * quads again. The SRCALPHA/INVSRCALPHA doesn't give any surprises, but the DESTALPHA/INVDESTALPHA
768          * blending works as supposed now - blend factor is 0.5 in both cases, not 0.75 as from the input
769          * vertices
770          */
771         hr = IDirect3DDevice7_SetRenderTarget(device, offscreen, 0);
772         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
773         hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x80ff0000, 0.0, 0);
774         ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
775
776         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA);
777         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
778         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA);
779         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
780         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad1, 4, 0);
781         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
782
783         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SRCBLEND, D3DBLEND_DESTALPHA);
784         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
785         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVDESTALPHA);
786         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
787         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad2, 4, 0);
788         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
789
790         hr = IDirect3DDevice7_SetRenderTarget(device, backbuffer, 0);
791         ok(hr == D3D_OK, "Can't get back buffer, hr = %08x\n", hr);
792         set_the_same_viewport_again(device);
793
794         /* Render the offscreen texture onto the frame buffer to be able to compare it regularly.
795          * Disable alpha blending for the final composition
796          */
797         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
798         ok(hr == D3D_OK, "IDirect3DDevice7_SetRenderState failed, hr = %08x\n", hr);
799
800         hr = IDirect3DDevice7_SetTexture(device, 0, offscreen);
801         ok(hr == D3D_OK, "IDirect3DDevice7_SetTexture failed, hr = %08x\n", hr);
802         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEX1, composite_quad, 4, 0);
803         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
804         hr = IDirect3DDevice7_SetTexture(device, 0, NULL);
805         ok(hr == D3D_OK, "IDirect3DDevice7_SetTexture failed, hr = %08x\n", hr);
806
807         hr = IDirect3DDevice7_EndScene(device);
808         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
809     }
810
811     color = getPixelColor(device, 160, 360);
812     red =   (color & 0x00ff0000) >> 16;
813     green = (color & 0x0000ff00) >>  8;
814     blue =  (color & 0x000000ff);
815     ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
816        "SRCALPHA on frame buffer returned color 0x%08x, expected 0x00bf4000\n", color);
817
818     color = getPixelColor(device, 160, 120);
819     red =   (color & 0x00ff0000) >> 16;
820     green = (color & 0x0000ff00) >>  8;
821     blue =  (color & 0x000000ff);
822     ok(red == 0x00 && green == 0x00 && blue >= 0xfe && blue <= 0xff ,
823        "DSTALPHA on frame buffer returned color 0x%08x, expected 0x000000ff\n", color);
824
825     color = getPixelColor(device, 480, 360);
826     red =   (color & 0x00ff0000) >> 16;
827     green = (color & 0x0000ff00) >>  8;
828     blue =  (color & 0x000000ff);
829     ok(red >= 0xbe && red <= 0xc0 && green >= 0x39 && green <= 0x41 && blue == 0x00,
830        "SRCALPHA on texture returned color 0x%08x, expected 0x00bf4000\n", color);
831
832     color = getPixelColor(device, 480, 120);
833     red =   (color & 0x00ff0000) >> 16;
834     green = (color & 0x0000ff00) >>  8;
835     blue =  (color & 0x000000ff);
836     ok(red >= 0x7e && red <= 0x81 && green == 0x00 && blue >= 0x7e && blue <= 0x81,
837        "DSTALPHA on texture returned color 0x%08x, expected 0x00800080\n", color);
838
839     out:
840     if(offscreen) IDirectDrawSurface7_Release(offscreen);
841     if(backbuffer) IDirectDrawSurface7_Release(backbuffer);
842 }
843
844 static void rhw_zero_test(IDirect3DDevice7 *device)
845 {
846 /* Test if it will render a quad correctly when vertex rhw = 0 */
847     HRESULT hr;
848     DWORD color;
849
850     struct {
851         float x, y, z;
852         float rhw;
853         DWORD diffuse;
854         } quad1[] =
855     {
856         {0, 100, 0, 0, 0xffffffff},
857         {0, 0, 0, 0, 0xffffffff},
858         {100, 100, 0, 0, 0xffffffff},
859         {100, 0, 0, 0, 0xffffffff},
860     };
861
862     /* Clear to black */
863     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0, 0.0, 0);
864     ok(hr == D3D_OK, "Clear failed, hr = %08x\n", hr);
865
866     hr = IDirect3DDevice7_BeginScene(device);
867     ok(hr == D3D_OK, "IDirect3DDevice7_BeginScene failed with %08x\n", hr);
868
869     if (SUCCEEDED(hr)) {
870         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad1, 4, 0);
871         ok(hr == D3D_OK, "DrawPrimitive failed, hr = %08x\n", hr);
872
873         hr = IDirect3DDevice7_EndScene(device);
874         ok(hr == D3D_OK, "IDirect3DDevice7_EndScene failed, hr = %08x\n", hr);
875     }
876
877     color = getPixelColor(device, 5, 5);
878     ok(color == 0xffffff ||
879        broken(color == 0), /* VMware */
880        "Got color %08x, expected 00ffffff\n", color);
881
882     color = getPixelColor(device, 105, 105);
883     ok(color == 0, "Got color %08x, expected 00000000\n", color);
884 }
885
886 static BOOL D3D1_createObjects(void)
887 {
888     WNDCLASS wc = {0};
889     HRESULT hr;
890     DDSURFACEDESC ddsd;
891     D3DEXECUTEBUFFERDESC exdesc;
892     D3DVIEWPORT vp_data;
893
894     /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
895     hr = DirectDrawCreate(NULL, &DirectDraw1, NULL);
896
897     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
898     if (FAILED(hr)) {
899         return FALSE;
900     }
901
902     wc.lpfnWndProc = DefWindowProc;
903     wc.lpszClassName = "texturemapblend_test_wc";
904     RegisterClass(&wc);
905     window = CreateWindow("texturemapblend_test_wc", "texturemapblend_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
906
907     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
908     ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
909     if(FAILED(hr)) {
910         return FALSE;
911     }
912
913     hr = IDirectDraw_SetDisplayMode(DirectDraw1, 640, 480, 32);
914     if(FAILED(hr)) {
915         /* 24 bit is fine too */
916         hr = IDirectDraw_SetDisplayMode(DirectDraw1, 640, 480, 24);
917     }
918     ok(hr==DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode returned: %x\n", hr);
919     if (FAILED(hr)) {
920         return FALSE;
921     }
922
923     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirect3D, (void**) &Direct3D1);
924     ok(hr==DD_OK, "QueryInterface returned: %x\n", hr);
925     if (FAILED(hr)) {
926         return FALSE;
927     }
928
929     memset(&ddsd, 0, sizeof(ddsd));
930     ddsd.dwSize = sizeof(ddsd);
931     ddsd.dwFlags = DDSD_CAPS;
932     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
933     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
934     ok(hr==DD_OK, "CreateSurface returned: %x\n", hr);
935     if (FAILED(hr)) {
936         return FALSE;
937     }
938
939     hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DHALDevice, (void **) &Direct3DDevice1);
940     if(FAILED(hr)) {
941         trace("Creating a HAL device failed, trying Ref\n");
942         hr = IDirectDrawSurface_QueryInterface(Surface1, &IID_IDirect3DRefDevice, (void **) &Direct3DDevice1);
943     }
944     ok(hr==D3D_OK, "Creating 3D device returned: %x\n", hr);
945     if(FAILED(hr)) {
946         return FALSE;
947     }
948
949     hr = IDirect3D_CreateViewport(Direct3D1, &Viewport, NULL);
950     ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
951     if (FAILED(hr)) {
952         return FALSE;
953     }
954
955     hr = IDirect3DViewport_Initialize(Viewport, Direct3D1);
956     ok(hr == D3D_OK || hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
957     hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport);
958     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
959     vp_data.dwSize = sizeof(vp_data);
960     vp_data.dwX = 0;
961     vp_data.dwY = 0;
962     vp_data.dwWidth = 640;
963     vp_data.dwHeight = 480;
964     vp_data.dvScaleX = 1;
965     vp_data.dvScaleY = 1;
966     vp_data.dvMaxX = 640;
967     vp_data.dvMaxY = 480;
968     vp_data.dvMinZ = 0;
969     vp_data.dvMaxZ = 1;
970     hr = IDirect3DViewport_SetViewport(Viewport, &vp_data);
971     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
972
973     memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
974     exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
975     exdesc.dwFlags = D3DDEB_BUFSIZE | D3DDEB_CAPS;
976     exdesc.dwBufferSize = 512;
977     exdesc.dwCaps = D3DDEBCAPS_SYSTEMMEMORY;
978     hr = IDirect3DDevice_CreateExecuteBuffer(Direct3DDevice1, &exdesc, &ExecuteBuffer, NULL);
979     ok(hr == D3D_OK, "IDirect3DDevice_CreateExecuteBuffer failed with %08x\n", hr);
980     if (FAILED(hr)) {
981         return FALSE;
982     }
983
984     return TRUE;
985 }
986
987 static void D3D1_releaseObjects(void)
988 {
989     if(ExecuteBuffer) IDirect3DExecuteBuffer_Release(ExecuteBuffer);
990     if(Surface1) IDirectDrawSurface_Release(Surface1);
991     if(Viewport) IDirect3DViewport_Release(Viewport);
992     if(Direct3DDevice1) IDirect3DDevice_Release(Direct3DDevice1);
993     if(Direct3D1) IDirect3D_Release(Direct3D1);
994     if(DirectDraw1) IDirectDraw_Release(DirectDraw1);
995     if(window) DestroyWindow(window);
996 }
997
998 static DWORD D3D1_getPixelColor(IDirectDraw *DirectDraw1, IDirectDrawSurface *Surface, UINT x, UINT y)
999 {
1000     DWORD ret;
1001     HRESULT hr;
1002     DDSURFACEDESC ddsd;
1003     RECT rectToLock = {x, y, x+1, y+1};
1004     IDirectDrawSurface *surf = NULL;
1005
1006     /* Some implementations seem to dislike direct locking on the front buffer. Thus copy the front buffer
1007      * to an offscreen surface and lock it instead of the front buffer
1008      */
1009     memset(&ddsd, 0, sizeof(ddsd));
1010     ddsd.dwSize = sizeof(ddsd);
1011     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1012     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
1013     ddsd.dwWidth = 640;
1014     ddsd.dwHeight = 480;
1015     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
1016     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &surf, NULL);
1017     ok(hr == DD_OK, "IDirectDraw_CreateSurface failed with %08x\n", hr);
1018     if(!surf)
1019     {
1020         trace("cannot create helper surface\n");
1021         return 0xdeadbeef;
1022     }
1023
1024     memset(&ddsd, 0, sizeof(ddsd));
1025     ddsd.dwSize = sizeof(ddsd);
1026     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1027
1028     hr = IDirectDrawSurface_BltFast(surf, 0, 0, Surface, NULL, 0);
1029     ok(hr == DD_OK, "IDirectDrawSurface_BltFast returned %08x\n", hr);
1030     if(FAILED(hr))
1031     {
1032         trace("Cannot blit\n");
1033         ret = 0xdeadbee;
1034         goto out;
1035     }
1036
1037     hr = IDirectDrawSurface_Lock(surf, &rectToLock, &ddsd, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
1038     if(FAILED(hr))
1039     {
1040         trace("Can't lock the offscreen surface, hr=%08x\n", hr);
1041         ret = 0xdeadbeec;
1042         goto out;
1043     }
1044
1045     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
1046      * really important for these tests
1047      */
1048     ret = ((DWORD *) ddsd.lpSurface)[0] & 0x00ffffff;
1049     hr = IDirectDrawSurface_Unlock(surf, NULL);
1050     if(FAILED(hr))
1051     {
1052         trace("Can't unlock the offscreen surface, hr=%08x\n", hr);
1053     }
1054
1055 out:
1056     IDirectDrawSurface_Release(surf);
1057     return ret;
1058 }
1059
1060 #define EXEBUF_START_RENDER_STATES(count, ptr) do {\
1061                          ((D3DINSTRUCTION*)(ptr))->bOpcode = D3DOP_STATERENDER;\
1062                          ((D3DINSTRUCTION*)(ptr))->bSize = sizeof(D3DSTATE);\
1063                          ((D3DINSTRUCTION*)(ptr))->wCount = count;\
1064                          ptr = ((D3DINSTRUCTION*)(ptr))+1; } while (0)
1065
1066 #define EXEBUF_PUT_RENDER_STATE(state, value, ptr) do {\
1067                          U1(*((D3DSTATE*)(ptr))).drstRenderStateType = state; \
1068                          U2(*((D3DSTATE*)(ptr))).dwArg[0] = value; \
1069                          ptr = ((D3DSTATE*)(ptr))+1; } while (0)
1070
1071 #define EXEBUF_PUT_PROCESSVERTICES(nvertices, ptr) do {\
1072                          ((D3DINSTRUCTION*)(ptr))->bOpcode = D3DOP_PROCESSVERTICES;\
1073                          ((D3DINSTRUCTION*)(ptr))->bSize = sizeof(D3DPROCESSVERTICES);\
1074                          ((D3DINSTRUCTION*)(ptr))->wCount = 1;\
1075                          ptr = ((D3DINSTRUCTION*)(ptr))+1;\
1076                          ((D3DPROCESSVERTICES*)(ptr))->dwFlags = D3DPROCESSVERTICES_COPY;\
1077                          ((D3DPROCESSVERTICES*)(ptr))->wStart = 0;\
1078                          ((D3DPROCESSVERTICES*)(ptr))->wDest = 0;\
1079                          ((D3DPROCESSVERTICES*)(ptr))->dwCount = nvertices;\
1080                          ((D3DPROCESSVERTICES*)(ptr))->dwReserved = 0;\
1081                          ptr = ((D3DPROCESSVERTICES*)(ptr))+1; } while (0)
1082
1083 #define EXEBUF_END(ptr) do {\
1084                          ((D3DINSTRUCTION*)(ptr))->bOpcode = D3DOP_EXIT;\
1085                          ((D3DINSTRUCTION*)(ptr))->bSize = 0;\
1086                          ((D3DINSTRUCTION*)(ptr))->wCount = 0;\
1087                          ptr = ((D3DINSTRUCTION*)(ptr))+1; } while (0)
1088
1089 #define EXEBUF_PUT_QUAD(base_idx, ptr) do {\
1090                          ((D3DINSTRUCTION*)(ptr))->bOpcode = D3DOP_TRIANGLE;\
1091                          ((D3DINSTRUCTION*)(ptr))->bSize = sizeof(D3DTRIANGLE);\
1092                          ((D3DINSTRUCTION*)(ptr))->wCount = 2;\
1093                          ptr = ((D3DINSTRUCTION*)(ptr))+1;\
1094                          U1(*((D3DTRIANGLE*)(ptr))).v1 = base_idx;\
1095                          U2(*((D3DTRIANGLE*)(ptr))).v2 = (base_idx) + 1; \
1096                          U3(*((D3DTRIANGLE*)(ptr))).v3 = (base_idx) + 3; \
1097                          ((D3DTRIANGLE*)(ptr))->wFlags = 0;\
1098                          ptr = ((D3DTRIANGLE*)ptr)+1;\
1099                          U1(*((D3DTRIANGLE*)(ptr))).v1 = (base_idx) + 1; \
1100                          U2(*((D3DTRIANGLE*)(ptr))).v2 = (base_idx) + 2; \
1101                          U3(*((D3DTRIANGLE*)(ptr))).v3 = (base_idx) + 3; \
1102                          ((D3DTRIANGLE*)(ptr))->wFlags = 0;\
1103                          ptr = ((D3DTRIANGLE*)(ptr))+1;\
1104                         } while (0)
1105
1106 static HRESULT CALLBACK TextureFormatEnumCallback(LPDDSURFACEDESC lpDDSD, LPVOID lpContext)
1107 {
1108     if (lpDDSD->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
1109         *(BOOL*)lpContext = TRUE;
1110     }
1111
1112     return DDENUMRET_OK;
1113 }
1114
1115 static void D3D1_TextureMapBlendTest(void)
1116 {
1117     HRESULT hr;
1118     DDSURFACEDESC ddsd;
1119     D3DEXECUTEBUFFERDESC exdesc;
1120     D3DEXECUTEDATA exdata;
1121     DDBLTFX ddbltfx;
1122     RECT rect = { 0, 0, 64, 128 };
1123     DWORD color, red, blue, green;
1124     void *exe_buffer_ptr;
1125     DWORD exe_length;
1126     D3DTEXTUREHANDLE htex;
1127     DDCOLORKEY clrKey;
1128     IDirectDrawSurface *TexSurface = NULL;
1129     IDirect3DTexture *Texture = NULL;
1130     IDirectDrawPalette *Palette = NULL;
1131     PALETTEENTRY table1[256];
1132     BOOL p8_textures_supported = FALSE;
1133
1134     struct {
1135         float x, y, z;
1136         float rhw;
1137         DWORD diffuse;
1138         DWORD specular;
1139         float tu, tv;
1140         } test1_quads[] =
1141     {
1142           {0.0f,   0.0f,     0.0f, 1.0f, 0xffffffff, 0, 0.0f, 0.0f},
1143           {640.0f, 0.0f,     0.0f, 1.0f, 0xffffffff, 0, 1.0f, 0.0f},
1144           {640.0f, 240.0f,   0.0f, 1.0f, 0xffffffff, 0, 1.0f, 1.0f},
1145           {0.0f,   240.0f,   0.0f, 1.0f, 0xffffffff, 0, 0.0f, 1.0f},
1146           {0.0f,   240.0f,   0.0f, 1.0f, 0x80ffffff, 0, 0.0f, 0.0f},
1147           {640.0f, 240.0f,   0.0f, 1.0f, 0x80ffffff, 0, 1.0f, 0.0f},
1148           {640.0f, 480.0f,   0.0f, 1.0f, 0x80ffffff, 0, 1.0f, 1.0f},
1149           {0.0f,   480.0f,   0.0f, 1.0f, 0x80ffffff, 0, 0.0f, 1.0f}
1150     },  test2_quads[] =
1151           {
1152           {0.0f,   0.0f,     0.0f, 1.0f, 0x00ff0080, 0, 0.0f, 0.0f},
1153           {640.0f, 0.0f,     0.0f, 1.0f, 0x00ff0080, 0, 1.0f, 0.0f},
1154           {640.0f, 240.0f,   0.0f, 1.0f, 0x00ff0080, 0, 1.0f, 1.0f},
1155           {0.0f,   240.0f,   0.0f, 1.0f, 0x00ff0080, 0, 0.0f, 1.0f},
1156           {0.0f,   240.0f,   0.0f, 1.0f, 0x008000ff, 0, 0.0f, 0.0f},
1157           {640.0f, 240.0f,   0.0f, 1.0f, 0x008000ff, 0, 1.0f, 0.0f},
1158           {640.0f, 480.0f,   0.0f, 1.0f, 0x008000ff, 0, 1.0f, 1.0f},
1159           {0.0f,   480.0f,   0.0f, 1.0f, 0x008000ff, 0, 0.0f, 1.0f}
1160     };
1161
1162     /* 1) Test alpha with DDPF_ALPHAPIXELS texture - should be taken from texture alpha channel*/
1163     memset (&ddsd, 0, sizeof (ddsd));
1164     ddsd.dwSize = sizeof (ddsd);
1165     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1166     ddsd.dwHeight = 128;
1167     ddsd.dwWidth = 128;
1168     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1169     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1170     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1171     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 32;
1172     U2(ddsd.ddpfPixelFormat).dwRBitMask         = 0x00ff0000;
1173     U3(ddsd.ddpfPixelFormat).dwGBitMask         = 0x0000ff00;
1174     U4(ddsd.ddpfPixelFormat).dwBBitMask         = 0x000000ff;
1175     U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask  = 0xff000000;
1176     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1177     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1178     if (FAILED(hr)) {
1179         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1180         goto out;
1181     }
1182
1183     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1184                 (void *)&Texture);
1185     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1186     if (FAILED(hr)) {
1187         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1188         goto out;
1189     }
1190
1191     memset(&ddbltfx, 0, sizeof(ddbltfx));
1192     ddbltfx.dwSize = sizeof(ddbltfx);
1193     U5(ddbltfx).dwFillColor = 0;
1194     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1195     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1196
1197     U5(ddbltfx).dwFillColor = 0xff0000ff;
1198     hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1199     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1200     U5(ddbltfx).dwFillColor = 0x800000ff;
1201     hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1202     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1203
1204     memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
1205     exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
1206     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &exdesc);
1207     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed with %08x\n", hr);
1208     if (FAILED(hr)) {
1209         skip("IDirect3DExecuteBuffer_Lock failed; skipping further tests\n");
1210         goto out;
1211     }
1212
1213     memcpy(exdesc.lpData, test1_quads, sizeof(test1_quads));
1214
1215     exe_buffer_ptr = 256 + (char*)exdesc.lpData;
1216
1217     EXEBUF_PUT_PROCESSVERTICES(8, exe_buffer_ptr);
1218
1219     EXEBUF_START_RENDER_STATES(12, exe_buffer_ptr);
1220     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_CULLMODE,         D3DCULL_NONE,              exe_buffer_ptr);
1221     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_ZENABLE,          FALSE,                     exe_buffer_ptr);
1222     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_FOGENABLE,        FALSE,                     exe_buffer_ptr);
1223     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_SPECULARENABLE,   FALSE,                     exe_buffer_ptr);
1224     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREMAG,       D3DFILTER_NEAREST,         exe_buffer_ptr);
1225     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREMIN,       D3DFILTER_NEAREST,         exe_buffer_ptr);
1226     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_FILLMODE  ,       D3DFILL_SOLID,             exe_buffer_ptr);
1227     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_SRCBLEND,         D3DBLEND_SRCALPHA,         exe_buffer_ptr);
1228     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_DESTBLEND,        D3DBLEND_INVSRCALPHA,      exe_buffer_ptr);
1229     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE,                      exe_buffer_ptr);
1230     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREMAPBLEND,  D3DTBLEND_MODULATE,        exe_buffer_ptr);
1231     hr = IDirect3DTexture_GetHandle(Texture, Direct3DDevice1, &htex);
1232     ok(hr == D3D_OK, "IDirect3DTexture_GetHandle failed with %08x\n", hr);
1233     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREHANDLE,  htex, exe_buffer_ptr);
1234
1235     EXEBUF_PUT_QUAD(0, exe_buffer_ptr);
1236     EXEBUF_PUT_QUAD(4, exe_buffer_ptr);
1237
1238     EXEBUF_END(exe_buffer_ptr);
1239
1240     exe_length = ((char*)exe_buffer_ptr - (char*)exdesc.lpData) - 256;
1241
1242     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1243     if (FAILED(hr)) {
1244         trace("IDirect3DExecuteBuffer_Unlock failed with %08x\n", hr);
1245     }
1246
1247     memset(&exdata, 0, sizeof(D3DEXECUTEDATA));
1248     exdata.dwSize = sizeof(D3DEXECUTEDATA);
1249     exdata.dwVertexCount = 8;
1250     exdata.dwInstructionOffset = 256;
1251     exdata.dwInstructionLength = exe_length;
1252     hr = IDirect3DExecuteBuffer_SetExecuteData(ExecuteBuffer, &exdata);
1253     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_SetExecuteData failed with %08x\n", hr);
1254
1255     hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1256     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1257
1258     if (SUCCEEDED(hr)) {
1259         hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_UNCLIPPED);
1260         ok(hr == D3D_OK, "IDirect3DDevice_Execute failed, hr = %08x\n", hr);
1261         hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1262         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1263     }
1264
1265     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1266     red =   (color & 0x00ff0000) >> 16;
1267     green = (color & 0x0000ff00) >>  8;
1268     blue =  (color & 0x000000ff);
1269     ok(red == 0 &&  green == 0 && blue >= 0x7e && blue <= 0x82, "Got color %08x, expected 00000080 or near\n", color);
1270
1271     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 5);
1272     red =   (color & 0x00ff0000) >> 16;
1273     green = (color & 0x0000ff00) >>  8;
1274     blue =  (color & 0x000000ff);
1275     ok(red == 0 &&  green == 0 && blue == 0xff, "Got color %08x, expected 000000ff or near\n", color);
1276
1277     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 245);
1278     red =   (color & 0x00ff0000) >> 16;
1279     green = (color & 0x0000ff00) >>  8;
1280     blue =  (color & 0x000000ff);
1281     ok(red == 0 &&  green == 0 && blue >= 0x7e && blue <= 0x82, "Got color %08x, expected 00000080 or near\n", color);
1282
1283     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 245);
1284     red =   (color & 0x00ff0000) >> 16;
1285     green = (color & 0x0000ff00) >>  8;
1286     blue =  (color & 0x000000ff);
1287     ok(red == 0 &&  green == 0 && blue == 0xff, "Got color %08x, expected 000000ff or near\n", color);
1288
1289     /* 2) Test alpha with texture that has no alpha channel - alpha should be taken from diffuse color */
1290     if(Texture) IDirect3DTexture_Release(Texture);
1291     Texture = NULL;
1292     if(TexSurface) IDirectDrawSurface_Release(TexSurface);
1293     TexSurface = NULL;
1294
1295     memset (&ddsd, 0, sizeof (ddsd));
1296     ddsd.dwSize = sizeof (ddsd);
1297     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1298     ddsd.dwHeight = 128;
1299     ddsd.dwWidth = 128;
1300     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1301     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1302     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
1303     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 32;
1304     U2(ddsd.ddpfPixelFormat).dwRBitMask         = 0x00ff0000;
1305     U3(ddsd.ddpfPixelFormat).dwGBitMask         = 0x0000ff00;
1306     U4(ddsd.ddpfPixelFormat).dwBBitMask         = 0x000000ff;
1307
1308     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1309     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1310     if (FAILED(hr)) {
1311         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1312         goto out;
1313     }
1314
1315     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1316                 (void *)&Texture);
1317     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1318     if (FAILED(hr)) {
1319         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1320         goto out;
1321     }
1322
1323     memset(&ddbltfx, 0, sizeof(ddbltfx));
1324     ddbltfx.dwSize = sizeof(ddbltfx);
1325     U5(ddbltfx).dwFillColor = 0;
1326     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1327     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1328
1329     U5(ddbltfx).dwFillColor = 0xff0000ff;
1330     hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1331     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1332     U5(ddbltfx).dwFillColor = 0x800000ff;
1333     hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1334     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1335
1336     memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
1337     exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
1338     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &exdesc);
1339     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed with %08x\n", hr);
1340     if (FAILED(hr)) {
1341         skip("IDirect3DExecuteBuffer_Lock failed; skipping further tests\n");
1342         goto out;
1343     }
1344
1345     memcpy(exdesc.lpData, test1_quads, sizeof(test1_quads));
1346
1347     exe_buffer_ptr = 256 + (char*)exdesc.lpData;
1348
1349     EXEBUF_PUT_PROCESSVERTICES(8, exe_buffer_ptr);
1350
1351     EXEBUF_START_RENDER_STATES(1, exe_buffer_ptr);
1352     hr = IDirect3DTexture_GetHandle(Texture, Direct3DDevice1, &htex);
1353     ok(hr == D3D_OK, "IDirect3DTexture_GetHandle failed with %08x\n", hr);
1354     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREHANDLE,  htex, exe_buffer_ptr);
1355
1356     EXEBUF_PUT_QUAD(0, exe_buffer_ptr);
1357     EXEBUF_PUT_QUAD(4, exe_buffer_ptr);
1358
1359     EXEBUF_END(exe_buffer_ptr);
1360
1361     exe_length = ((char*)exe_buffer_ptr - (char*)exdesc.lpData) - 256;
1362
1363     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1364     if (FAILED(hr)) {
1365         trace("IDirect3DExecuteBuffer_Unlock failed with %08x\n", hr);
1366     }
1367
1368     memset(&exdata, 0, sizeof(D3DEXECUTEDATA));
1369     exdata.dwSize = sizeof(D3DEXECUTEDATA);
1370     exdata.dwVertexCount = 8;
1371     exdata.dwInstructionOffset = 256;
1372     exdata.dwInstructionLength = exe_length;
1373     hr = IDirect3DExecuteBuffer_SetExecuteData(ExecuteBuffer, &exdata);
1374     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_SetExecuteData failed with %08x\n", hr);
1375
1376     hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1377     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1378
1379     if (SUCCEEDED(hr)) {
1380         hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_UNCLIPPED);
1381         ok(hr == D3D_OK, "IDirect3DDevice_Execute failed, hr = %08x\n", hr);
1382         hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1383         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1384     }
1385
1386     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1387     red =   (color & 0x00ff0000) >> 16;
1388     green = (color & 0x0000ff00) >>  8;
1389     blue =  (color & 0x000000ff);
1390     ok(red == 0 &&  green == 0 && blue == 0xff, "Got color %08x, expected 000000ff or near\n", color);
1391
1392     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 5);
1393     red =   (color & 0x00ff0000) >> 16;
1394     green = (color & 0x0000ff00) >>  8;
1395     blue =  (color & 0x000000ff);
1396     ok(red == 0 &&  green == 0 && blue == 0xff, "Got color %08x, expected 000000ff or near\n", color);
1397
1398     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 245);
1399     red =   (color & 0x00ff0000) >> 16;
1400     green = (color & 0x0000ff00) >>  8;
1401     blue =  (color & 0x000000ff);
1402     ok(red == 0 &&  green == 0 && blue >= 0x7e && blue <= 0x82, "Got color %08x, expected 00000080 or near\n", color);
1403
1404     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 245);
1405     red =   (color & 0x00ff0000) >> 16;
1406     green = (color & 0x0000ff00) >>  8;
1407     blue =  (color & 0x000000ff);
1408     ok(red == 0 &&  green == 0 && blue >= 0x7e && blue <= 0x82, "Got color %08x, expected 00000080 or near\n", color);
1409
1410     /* 3) Test RGB - should multiply color components from diffuse color and texture */
1411     if(Texture) IDirect3DTexture_Release(Texture);
1412     Texture = NULL;
1413     if(TexSurface) IDirectDrawSurface_Release(TexSurface);
1414     TexSurface = NULL;
1415
1416     memset (&ddsd, 0, sizeof (ddsd));
1417     ddsd.dwSize = sizeof (ddsd);
1418     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1419     ddsd.dwHeight = 128;
1420     ddsd.dwWidth = 128;
1421     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1422     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1423     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
1424     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 32;
1425     U2(ddsd.ddpfPixelFormat).dwRBitMask         = 0x00ff0000;
1426     U3(ddsd.ddpfPixelFormat).dwGBitMask         = 0x0000ff00;
1427     U4(ddsd.ddpfPixelFormat).dwBBitMask         = 0x000000ff;
1428     U5(ddsd.ddpfPixelFormat).dwRGBAlphaBitMask  = 0xff000000;
1429     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1430     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1431     if (FAILED(hr)) {
1432         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1433         goto out;
1434     }
1435
1436     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1437                 (void *)&Texture);
1438     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1439     if (FAILED(hr)) {
1440         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1441         goto out;
1442     }
1443
1444     memset(&ddbltfx, 0, sizeof(ddbltfx));
1445     ddbltfx.dwSize = sizeof(ddbltfx);
1446     U5(ddbltfx).dwFillColor = 0;
1447     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1448     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1449
1450     U5(ddbltfx).dwFillColor = 0x00ffffff;
1451     hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1452     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1453     U5(ddbltfx).dwFillColor = 0x00ffff80;
1454     hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1455     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1456
1457     memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
1458     exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
1459     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &exdesc);
1460     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed with %08x\n", hr);
1461     if (FAILED(hr)) {
1462         skip("IDirect3DExecuteBuffer_Lock failed; skipping further tests\n");
1463         goto out;
1464     }
1465
1466     memcpy(exdesc.lpData, test2_quads, sizeof(test2_quads));
1467
1468     exe_buffer_ptr = 256 + (char*)exdesc.lpData;
1469
1470     EXEBUF_PUT_PROCESSVERTICES(8, exe_buffer_ptr);
1471
1472     EXEBUF_START_RENDER_STATES(2, exe_buffer_ptr);
1473     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE, exe_buffer_ptr);
1474     hr = IDirect3DTexture_GetHandle(Texture, Direct3DDevice1, &htex);
1475     ok(hr == D3D_OK, "IDirect3DTexture_GetHandle failed with %08x\n", hr);
1476     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREHANDLE,  htex, exe_buffer_ptr);
1477
1478     EXEBUF_PUT_QUAD(0, exe_buffer_ptr);
1479     EXEBUF_PUT_QUAD(4, exe_buffer_ptr);
1480
1481     EXEBUF_END(exe_buffer_ptr);
1482
1483     exe_length = ((char*)exe_buffer_ptr - (char*)exdesc.lpData) - 256;
1484
1485     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1486     if (FAILED(hr)) {
1487         trace("IDirect3DExecuteBuffer_Unlock failed with %08x\n", hr);
1488     }
1489
1490     memset(&exdata, 0, sizeof(D3DEXECUTEDATA));
1491     exdata.dwSize = sizeof(D3DEXECUTEDATA);
1492     exdata.dwVertexCount = 8;
1493     exdata.dwInstructionOffset = 256;
1494     exdata.dwInstructionLength = exe_length;
1495     hr = IDirect3DExecuteBuffer_SetExecuteData(ExecuteBuffer, &exdata);
1496     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_SetExecuteData failed with %08x\n", hr);
1497
1498     hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1499     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1500
1501     if (SUCCEEDED(hr)) {
1502         hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_UNCLIPPED);
1503         ok(hr == D3D_OK, "IDirect3DDevice_Execute failed, hr = %08x\n", hr);
1504         hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1505         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1506     }
1507
1508     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1509     red =   (color & 0x00ff0000) >> 16;
1510     green = (color & 0x0000ff00) >>  8;
1511     blue =  (color & 0x000000ff);
1512     ok(red == 0xff &&  green == 0 && blue >= 0x3e && blue <= 0x42, "Got color %08x, expected 00ff0040 or near\n", color);
1513
1514     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 5);
1515     red =   (color & 0x00ff0000) >> 16;
1516     green = (color & 0x0000ff00) >>  8;
1517     blue =  (color & 0x000000ff);
1518     ok(red == 0xff &&  green == 0 && blue == 0x80, "Got color %08x, expected 00ff0080 or near\n", color);
1519
1520     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 245);
1521     red =   (color & 0x00ff0000) >> 16;
1522     green = (color & 0x0000ff00) >>  8;
1523     blue =  (color & 0x000000ff);
1524     ok(red >= 0x7e && red <= 0x82 &&  green == 0 && blue == 0x80, "Got color %08x, expected 00800080 or near\n", color);
1525
1526     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 245);
1527     red =   (color & 0x00ff0000) >> 16;
1528     green = (color & 0x0000ff00) >>  8;
1529     blue =  (color & 0x000000ff);
1530     ok(red >= 0x7e && red <= 0x82 &&  green == 0 && blue == 0xff, "Got color %08x, expected 008000ff or near\n", color);
1531
1532     /* 4) Test alpha again, now with color keyed texture (colorkey emulation in wine can interfere) */
1533     if(Texture) IDirect3DTexture_Release(Texture);
1534     Texture = NULL;
1535     if(TexSurface) IDirectDrawSurface_Release(TexSurface);
1536     TexSurface = NULL;
1537
1538     memset (&ddsd, 0, sizeof (ddsd));
1539     ddsd.dwSize = sizeof (ddsd);
1540     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1541     ddsd.dwHeight = 128;
1542     ddsd.dwWidth = 128;
1543     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1544     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1545     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
1546     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 16;
1547     U2(ddsd.ddpfPixelFormat).dwRBitMask         = 0xf800;
1548     U3(ddsd.ddpfPixelFormat).dwGBitMask         = 0x07e0;
1549     U4(ddsd.ddpfPixelFormat).dwBBitMask         = 0x001f;
1550
1551     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1552     ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1553     if (FAILED(hr)) {
1554         skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1555         goto out;
1556     }
1557
1558     hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1559                 (void *)&Texture);
1560     ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1561     if (FAILED(hr)) {
1562         skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1563         goto out;
1564     }
1565
1566     memset(&ddbltfx, 0, sizeof(ddbltfx));
1567     ddbltfx.dwSize = sizeof(ddbltfx);
1568     U5(ddbltfx).dwFillColor = 0;
1569     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1570     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1571     U5(ddbltfx).dwFillColor = 0xf800;
1572     hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1573     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1574     U5(ddbltfx).dwFillColor = 0x001f;
1575     hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1576     ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1577
1578     clrKey.dwColorSpaceLowValue = 0x001f;
1579     clrKey.dwColorSpaceHighValue = 0x001f;
1580     hr = IDirectDrawSurface_SetColorKey(TexSurface, DDCKEY_SRCBLT, &clrKey);
1581     ok(hr==D3D_OK, "IDirectDrawSurfac_SetColorKey returned: %x\n", hr);
1582
1583     memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
1584     exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
1585     hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &exdesc);
1586     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed with %08x\n", hr);
1587     if (FAILED(hr)) {
1588         skip("IDirect3DExecuteBuffer_Lock failed; skipping further tests\n");
1589         goto out;
1590     }
1591
1592     memcpy(exdesc.lpData, test1_quads, sizeof(test1_quads));
1593
1594     exe_buffer_ptr = 256 + (char*)exdesc.lpData;
1595
1596     EXEBUF_PUT_PROCESSVERTICES(8, exe_buffer_ptr);
1597
1598     EXEBUF_START_RENDER_STATES(2, exe_buffer_ptr);
1599     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE, exe_buffer_ptr);
1600     hr = IDirect3DTexture_GetHandle(Texture, Direct3DDevice1, &htex);
1601     ok(hr == D3D_OK, "IDirect3DTexture_GetHandle failed with %08x\n", hr);
1602     EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREHANDLE,  htex, exe_buffer_ptr);
1603
1604     EXEBUF_PUT_QUAD(0, exe_buffer_ptr);
1605     EXEBUF_PUT_QUAD(4, exe_buffer_ptr);
1606
1607     EXEBUF_END(exe_buffer_ptr);
1608
1609     exe_length = ((char*)exe_buffer_ptr - (char*)exdesc.lpData) - 256;
1610
1611     hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1612     if (FAILED(hr)) {
1613         trace("IDirect3DExecuteBuffer_Unlock failed with %08x\n", hr);
1614     }
1615
1616     memset(&exdata, 0, sizeof(D3DEXECUTEDATA));
1617     exdata.dwSize = sizeof(D3DEXECUTEDATA);
1618     exdata.dwVertexCount = 8;
1619     exdata.dwInstructionOffset = 256;
1620     exdata.dwInstructionLength = exe_length;
1621     hr = IDirect3DExecuteBuffer_SetExecuteData(ExecuteBuffer, &exdata);
1622     ok(hr == D3D_OK, "IDirect3DExecuteBuffer_SetExecuteData failed with %08x\n", hr);
1623
1624     hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1625     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1626
1627     if (SUCCEEDED(hr)) {
1628         hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_UNCLIPPED);
1629         ok(hr == D3D_OK, "IDirect3DDevice_Execute failed, hr = %08x\n", hr);
1630         hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1631         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1632     }
1633
1634     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1635     ok(color == 0, "Got color %08x, expected 00000000\n", color);
1636
1637     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 5);
1638     red =   (color & 0x00ff0000) >> 16;
1639     green = (color & 0x0000ff00) >>  8;
1640     blue =  (color & 0x000000ff);
1641     ok(red == 0xff &&  green == 0 && blue == 0, "Got color %08x, expected 00ff0000 or near\n", color);
1642
1643     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 245);
1644     ok(color == 0, "Got color %08x, expected 00000000\n", color);
1645
1646     color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 245);
1647     red =   (color & 0x00ff0000) >> 16;
1648     green = (color & 0x0000ff00) >>  8;
1649     blue =  (color & 0x000000ff);
1650     ok(red >= 0x7e && red <= 0x82 &&  green == 0 && blue == 0, "Got color %08x, expected 00800000 or near\n", color);
1651
1652     /* 5) Test alpha again, now with color keyed P8 texture */
1653     if(Texture) IDirect3DTexture_Release(Texture);
1654     Texture = NULL;
1655     if(TexSurface) IDirectDrawSurface_Release(TexSurface);
1656     TexSurface = NULL;
1657
1658     hr = IDirect3DDevice_EnumTextureFormats(Direct3DDevice1, TextureFormatEnumCallback,
1659                                                 &p8_textures_supported);
1660     ok(hr == DD_OK, "IDirect3DDevice_EnumTextureFormats returned %08x\n", hr);
1661
1662     if (!p8_textures_supported) {
1663         skip("device has no P8 texture support, skipping test\n");
1664     } else {
1665         memset (&ddsd, 0, sizeof (ddsd));
1666         ddsd.dwSize = sizeof (ddsd);
1667         ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
1668         ddsd.dwHeight = 128;
1669         ddsd.dwWidth = 128;
1670         ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
1671         ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
1672         ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
1673         U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 8;
1674
1675         hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &TexSurface, NULL);
1676         ok(hr==D3D_OK, "CreateSurface returned: %x\n", hr);
1677         if (FAILED(hr)) {
1678             skip("IDirectDraw_CreateSurface failed; skipping further tests\n");
1679             goto out;
1680         }
1681
1682         memset(table1, 0, sizeof(table1));
1683         table1[0].peBlue = 0xff;
1684         table1[1].peRed = 0xff;
1685
1686         hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, table1, &Palette, NULL);
1687         ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
1688         if (FAILED(hr)) {
1689             skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
1690             goto out;
1691         }
1692
1693         hr = IDirectDrawSurface_SetPalette(TexSurface, Palette);
1694         ok(hr==D3D_OK, "IDirectDrawSurface_SetPalette returned: %x\n", hr);
1695
1696         hr = IDirectDrawSurface_QueryInterface(TexSurface, &IID_IDirect3DTexture,
1697                     (void *)&Texture);
1698         ok(hr==D3D_OK, "IDirectDrawSurface_QueryInterface returned: %x\n", hr);
1699         if (FAILED(hr)) {
1700             skip("Can't get IDirect3DTexture interface; skipping further tests\n");
1701             goto out;
1702         }
1703
1704         memset(&ddbltfx, 0, sizeof(ddbltfx));
1705         ddbltfx.dwSize = sizeof(ddbltfx);
1706         U5(ddbltfx).dwFillColor = 0;
1707         hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1708         ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1709         U5(ddbltfx).dwFillColor = 0;
1710         hr = IDirectDrawSurface_Blt(TexSurface, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1711         ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1712         U5(ddbltfx).dwFillColor = 1;
1713         hr = IDirectDrawSurface_Blt(TexSurface, &rect, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
1714         ok(hr == D3D_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
1715
1716         clrKey.dwColorSpaceLowValue = 1;
1717         clrKey.dwColorSpaceHighValue = 1;
1718         hr = IDirectDrawSurface_SetColorKey(TexSurface, DDCKEY_SRCBLT, &clrKey);
1719         ok(hr==D3D_OK, "IDirectDrawSurfac_SetColorKey returned: %x\n", hr);
1720
1721         memset(&exdesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
1722         exdesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
1723         hr = IDirect3DExecuteBuffer_Lock(ExecuteBuffer, &exdesc);
1724         ok(hr == D3D_OK, "IDirect3DExecuteBuffer_Lock failed with %08x\n", hr);
1725         if (FAILED(hr)) {
1726             skip("IDirect3DExecuteBuffer_Lock failed; skipping further tests\n");
1727             goto out;
1728         }
1729
1730         memcpy(exdesc.lpData, test1_quads, sizeof(test1_quads));
1731
1732         exe_buffer_ptr = 256 + (char*)exdesc.lpData;
1733
1734         EXEBUF_PUT_PROCESSVERTICES(8, exe_buffer_ptr);
1735
1736         EXEBUF_START_RENDER_STATES(2, exe_buffer_ptr);
1737         EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_ALPHABLENDENABLE, TRUE, exe_buffer_ptr);
1738         hr = IDirect3DTexture_GetHandle(Texture, Direct3DDevice1, &htex);
1739         ok(hr == D3D_OK, "IDirect3DTexture_GetHandle failed with %08x\n", hr);
1740         EXEBUF_PUT_RENDER_STATE(D3DRENDERSTATE_TEXTUREHANDLE,  htex, exe_buffer_ptr);
1741
1742         EXEBUF_PUT_QUAD(0, exe_buffer_ptr);
1743         EXEBUF_PUT_QUAD(4, exe_buffer_ptr);
1744
1745         EXEBUF_END(exe_buffer_ptr);
1746
1747         exe_length = ((char*)exe_buffer_ptr - (char*)exdesc.lpData) - 256;
1748
1749         hr = IDirect3DExecuteBuffer_Unlock(ExecuteBuffer);
1750         if (FAILED(hr)) {
1751             trace("IDirect3DExecuteBuffer_Unlock failed with %08x\n", hr);
1752         }
1753
1754         memset(&exdata, 0, sizeof(D3DEXECUTEDATA));
1755         exdata.dwSize = sizeof(D3DEXECUTEDATA);
1756         exdata.dwVertexCount = 8;
1757         exdata.dwInstructionOffset = 256;
1758         exdata.dwInstructionLength = exe_length;
1759         hr = IDirect3DExecuteBuffer_SetExecuteData(ExecuteBuffer, &exdata);
1760         ok(hr == D3D_OK, "IDirect3DExecuteBuffer_SetExecuteData failed with %08x\n", hr);
1761
1762         hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1763         ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1764
1765         if (SUCCEEDED(hr)) {
1766             hr = IDirect3DDevice_Execute(Direct3DDevice1, ExecuteBuffer, Viewport, D3DEXECUTE_UNCLIPPED);
1767             ok(hr == D3D_OK, "IDirect3DDevice_Execute failed, hr = %08x\n", hr);
1768             hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1769             ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1770         }
1771
1772         color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1773         ok(color == 0, "Got color %08x, expected 00000000\n", color);
1774
1775         color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 5);
1776         red =   (color & 0x00ff0000) >> 16;
1777         green = (color & 0x0000ff00) >>  8;
1778         blue =  (color & 0x000000ff);
1779         ok(red == 0 &&  green == 0 && blue == 0xff, "Got color %08x, expected 000000ff or near\n", color);
1780
1781         color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 245);
1782         ok(color == 0, "Got color %08x, expected 00000000\n", color);
1783
1784         color = D3D1_getPixelColor(DirectDraw1, Surface1, 400, 245);
1785         red =   (color & 0x00ff0000) >> 16;
1786         green = (color & 0x0000ff00) >>  8;
1787         blue =  (color & 0x000000ff);
1788         ok(red == 0 &&  green == 0 && blue >= 0x7e && blue <= 0x82, "Got color %08x, expected 00000080 or near\n", color);
1789     }
1790
1791     out:
1792
1793     if (Palette) IDirectDrawPalette_Release(Palette);
1794     if (TexSurface) IDirectDrawSurface_Release(TexSurface);
1795     if (Texture) IDirect3DTexture_Release(Texture);
1796 }
1797
1798 static void D3D1_ViewportClearTest(void)
1799 {
1800     HRESULT hr;
1801     IDirect3DMaterial *bgMaterial = NULL;
1802     D3DMATERIAL mat;
1803     D3DMATERIALHANDLE hMat;
1804     D3DVIEWPORT vp_data;
1805     IDirect3DViewport *Viewport2 = NULL;
1806     DWORD color, red, green, blue;
1807
1808     hr = IDirect3D_CreateMaterial(Direct3D1, &bgMaterial, NULL);
1809     ok(hr == D3D_OK, "IDirect3D_CreateMaterial failed: %08x\n", hr);
1810     if (FAILED(hr)) {
1811         goto out;
1812     }
1813
1814     hr = IDirect3D_CreateViewport(Direct3D1, &Viewport2, NULL);
1815     ok(hr == D3D_OK, "IDirect3D_CreateViewport failed: %08x\n", hr);
1816     if (FAILED(hr)) {
1817         goto out;
1818     }
1819
1820     hr = IDirect3DViewport_Initialize(Viewport2, Direct3D1);
1821     ok(hr == D3D_OK || hr == DDERR_ALREADYINITIALIZED, "IDirect3DViewport_Initialize returned %08x\n", hr);
1822     hr = IDirect3DDevice_AddViewport(Direct3DDevice1, Viewport2);
1823     ok(hr == D3D_OK, "IDirect3DDevice_AddViewport returned %08x\n", hr);
1824     vp_data.dwSize = sizeof(vp_data);
1825     vp_data.dwX = 200;
1826     vp_data.dwY = 200;
1827     vp_data.dwWidth = 100;
1828     vp_data.dwHeight = 100;
1829     vp_data.dvScaleX = 1;
1830     vp_data.dvScaleY = 1;
1831     vp_data.dvMaxX = 100;
1832     vp_data.dvMaxY = 100;
1833     vp_data.dvMinZ = 0;
1834     vp_data.dvMaxZ = 1;
1835     hr = IDirect3DViewport_SetViewport(Viewport2, &vp_data);
1836     ok(hr == D3D_OK, "IDirect3DViewport_SetViewport returned %08x\n", hr);
1837
1838     memset(&mat, 0, sizeof(mat));
1839     mat.dwSize = sizeof(mat);
1840     U1(U(mat).diffuse).r = 1.0f;
1841     hr = IDirect3DMaterial_SetMaterial(bgMaterial, &mat);
1842     ok(hr == D3D_OK, "IDirect3DMaterial_SetMaterial failed: %08x\n", hr);
1843
1844     hr = IDirect3DMaterial_GetHandle(bgMaterial, Direct3DDevice1, &hMat);
1845     ok(hr == D3D_OK, "IDirect3DMaterial_GetHandle failed: %08x\n", hr);
1846
1847     hr = IDirect3DViewport_SetBackground(Viewport, hMat);
1848     ok(hr == D3D_OK, "IDirect3DViewport_SetBackground failed: %08x\n", hr);
1849     hr = IDirect3DViewport_SetBackground(Viewport2, hMat);
1850     ok(hr == D3D_OK, "IDirect3DViewport_SetBackground failed: %08x\n", hr);
1851
1852     hr = IDirect3DDevice_BeginScene(Direct3DDevice1);
1853     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
1854
1855     if (SUCCEEDED(hr)) {
1856         D3DRECT rect;
1857
1858         U1(rect).x1 = U2(rect).y1 = 0;
1859         U3(rect).x2 = 640;
1860         U4(rect).y2 = 480;
1861
1862         hr = IDirect3DViewport_Clear(Viewport,  1,  &rect, D3DCLEAR_TARGET);
1863         ok(hr == D3D_OK, "IDirect3DViewport_Clear failed: %08x\n", hr);
1864
1865         memset(&mat, 0, sizeof(mat));
1866         mat.dwSize = sizeof(mat);
1867         U3(U(mat).diffuse).b = 1.0f;
1868         hr = IDirect3DMaterial_SetMaterial(bgMaterial, &mat);
1869         ok(hr == D3D_OK, "IDirect3DMaterial_SetMaterial failed: %08x\n", hr);
1870
1871         hr = IDirect3DViewport_Clear(Viewport2,  1,  &rect, D3DCLEAR_TARGET);
1872         ok(hr == D3D_OK, "IDirect3DViewport_Clear failed: %08x\n", hr);
1873
1874         hr = IDirect3DDevice_EndScene(Direct3DDevice1);
1875         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
1876         }
1877
1878     color = D3D1_getPixelColor(DirectDraw1, Surface1, 5, 5);
1879     red =   (color & 0x00ff0000) >> 16;
1880     green = (color & 0x0000ff00) >>  8;
1881     blue =  (color & 0x000000ff);
1882     ok((red == 0xff && green == 0 && blue == 0) ||
1883        broken(red == 0 && green == 0 && blue == 0xff), /* VMware and some native boxes */
1884        "Got color %08x, expected 00ff0000\n", color);
1885
1886     color = D3D1_getPixelColor(DirectDraw1, Surface1, 205, 205);
1887     red =   (color & 0x00ff0000) >> 16;
1888     green = (color & 0x0000ff00) >>  8;
1889     blue =  (color & 0x000000ff);
1890     ok(red == 0 && green == 0 && blue == 0xff, "Got color %08x, expected 000000ff\n", color);
1891
1892     out:
1893
1894     if (bgMaterial) IDirect3DMaterial_Release(bgMaterial);
1895     if (Viewport2) IDirect3DViewport_Release(Viewport2);
1896 }
1897
1898 static DWORD D3D3_getPixelColor(IDirectDraw4 *DirectDraw, IDirectDrawSurface4 *Surface, UINT x, UINT y)
1899 {
1900     DWORD ret;
1901     HRESULT hr;
1902     DDSURFACEDESC2 ddsd;
1903     RECT rectToLock = {x, y, x+1, y+1};
1904     IDirectDrawSurface4 *surf = NULL;
1905
1906     /* Some implementations seem to dislike direct locking on the front buffer. Thus copy the front buffer
1907      * to an offscreen surface and lock it instead of the front buffer
1908      */
1909     memset(&ddsd, 0, sizeof(ddsd));
1910     ddsd.dwSize = sizeof(ddsd);
1911     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1912     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
1913     ddsd.dwWidth = 640;
1914     ddsd.dwHeight = 480;
1915     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
1916     hr = IDirectDraw4_CreateSurface(DirectDraw, &ddsd, &surf, NULL);
1917     ok(hr == DD_OK, "IDirectDraw_CreateSurface failed with %08x\n", hr);
1918     if(!surf)
1919     {
1920         trace("cannot create helper surface\n");
1921         return 0xdeadbeef;
1922     }
1923
1924     memset(&ddsd, 0, sizeof(ddsd));
1925     ddsd.dwSize = sizeof(ddsd);
1926     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
1927
1928     hr = IDirectDrawSurface4_BltFast(surf, 0, 0, Surface, NULL, 0);
1929     ok(hr == DD_OK, "IDirectDrawSurface_BltFast returned %08x\n", hr);
1930     if(FAILED(hr))
1931     {
1932         trace("Cannot blit\n");
1933         ret = 0xdeadbee;
1934         goto out;
1935     }
1936
1937     hr = IDirectDrawSurface4_Lock(surf, &rectToLock, &ddsd, DDLOCK_READONLY | DDLOCK_WAIT, NULL);
1938     if(FAILED(hr))
1939     {
1940         trace("Can't lock the offscreen surface, hr=%08x\n", hr);
1941         ret = 0xdeadbeec;
1942         goto out;
1943     }
1944
1945     /* Remove the X channel for now. DirectX and OpenGL have different ideas how to treat it apparently, and it isn't
1946      * really important for these tests
1947      */
1948     ret = ((DWORD *) ddsd.lpSurface)[0] & 0x00ffffff;
1949     hr = IDirectDrawSurface4_Unlock(surf, NULL);
1950     if(FAILED(hr))
1951     {
1952         trace("Can't unlock the offscreen surface, hr=%08x\n", hr);
1953     }
1954
1955 out:
1956     IDirectDrawSurface4_Release(surf);
1957     return ret;
1958 }
1959
1960 static void D3D3_ViewportClearTest(void)
1961 {
1962     HRESULT hr;
1963     IDirectDraw *DirectDraw1 = NULL;
1964     IDirectDraw4 *DirectDraw4 = NULL;
1965     IDirectDrawSurface4 *Primary = NULL;
1966     IDirect3D3 *Direct3D3 = NULL;
1967     IDirect3DViewport3 *Viewport3 = NULL;
1968     IDirect3DViewport3 *SmallViewport3 = NULL;
1969     IDirect3DDevice3 *Direct3DDevice3 = NULL;
1970     WNDCLASS wc = {0};
1971     DDSURFACEDESC2 ddsd;
1972     D3DVIEWPORT2 vp_data;
1973     DWORD color, red, green, blue;
1974     D3DRECT rect;
1975     float mat[16] = { 1.0f, 0.0f, 0.0f, 0.0f,
1976                       0.0f, 1.0f, 0.0f, 0.0f,
1977                       0.0f, 0.0f, 1.0f, 0.0f,
1978                       0.0f, 0.0f, 0.0f, 1.0f };
1979     struct vertex quad[] =
1980     {
1981         {-1.0f, -1.0f,   0.1f,                          0xffffffff},
1982         {-1.0f,  1.0f,   0.1f,                          0xffffffff},
1983         { 1.0f,  1.0f,   0.1f,                          0xffffffff},
1984         { 1.0f, -1.0f,   0.1f,                          0xffffffff},
1985     };
1986
1987     WORD Indices[] = {0, 1, 2, 2, 3, 0};
1988     DWORD fvf = D3DFVF_XYZ | D3DFVF_DIFFUSE;
1989
1990     wc.lpfnWndProc = DefWindowProc;
1991     wc.lpszClassName = "D3D3_ViewportClearTest_wc";
1992     RegisterClass(&wc);
1993     window = CreateWindow("D3D3_ViewportClearTest_wc", "D3D3_ViewportClearTest",
1994                             WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
1995
1996     hr = DirectDrawCreate( NULL, &DirectDraw1, NULL );
1997     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
1998     if(FAILED(hr)) goto out;
1999
2000     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2001     ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
2002     if(FAILED(hr)) goto out;
2003
2004     hr = IDirectDraw_SetDisplayMode(DirectDraw1, 640, 480, 32);
2005     if(FAILED(hr)) {
2006         /* 24 bit is fine too */
2007         hr = IDirectDraw_SetDisplayMode(DirectDraw1, 640, 480, 24);
2008     }
2009     ok(hr==DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode returned: %x\n", hr);
2010     if (FAILED(hr)) goto out;
2011
2012     hr = IDirectDraw_QueryInterface(DirectDraw1, &IID_IDirectDraw4, (void**)&DirectDraw4);
2013     ok(hr==DD_OK, "QueryInterface returned: %08x\n", hr);
2014     if(FAILED(hr)) goto out;
2015
2016     memset(&ddsd, 0, sizeof(DDSURFACEDESC2));
2017     ddsd.dwSize = sizeof(DDSURFACEDESC2);
2018     ddsd.dwFlags    = DDSD_CAPS;
2019     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
2020
2021     hr = IDirectDraw_CreateSurface(DirectDraw4, &ddsd, &Primary, NULL);
2022     ok(hr==DD_OK, "IDirectDraw_CreateSurface returned: %08x\n", hr);
2023     if(FAILED(hr)) goto out;
2024
2025     hr = IDirectDraw4_QueryInterface(DirectDraw4, &IID_IDirect3D3, (void**)&Direct3D3);
2026     ok(hr==DD_OK, "IDirectDraw4_QueryInterface returned: %08x\n", hr);
2027     if(FAILED(hr)) goto out;
2028
2029     hr = IDirect3D3_CreateDevice(Direct3D3, &IID_IDirect3DHALDevice, Primary, &Direct3DDevice3, NULL);
2030     if(FAILED(hr)) {
2031         trace("Creating a HAL device failed, trying Ref\n");
2032         hr = IDirect3D3_CreateDevice(Direct3D3, &IID_IDirect3DRefDevice, Primary, &Direct3DDevice3, NULL);
2033     }
2034     ok(hr==D3D_OK, "Creating 3D device returned: %x\n", hr);
2035     if(FAILED(hr)) goto out;
2036
2037     hr = IDirect3D3_CreateViewport(Direct3D3, &Viewport3, NULL);
2038     ok(hr==DD_OK, "IDirect3D3_CreateViewport returned: %08x\n", hr);
2039     if(FAILED(hr)) goto out;
2040
2041     hr = IDirect3DDevice3_AddViewport(Direct3DDevice3, Viewport3);
2042     ok(hr==DD_OK, "IDirect3DDevice3_AddViewport returned: %08x\n", hr);
2043
2044     memset(&vp_data, 0, sizeof(D3DVIEWPORT2));
2045     vp_data.dwSize = sizeof(D3DVIEWPORT2);
2046     vp_data.dwWidth = 640;
2047     vp_data.dwHeight = 480;
2048     vp_data.dvClipX = -1.0f;
2049     vp_data.dvClipWidth = 2.0f;
2050     vp_data.dvClipY = 1.0f;
2051     vp_data.dvClipHeight = 2.0f;
2052     vp_data.dvMaxZ = 1.0f;
2053     hr = IDirect3DViewport3_SetViewport2(Viewport3, &vp_data);
2054     ok(hr==DD_OK, "IDirect3DViewport3_SetViewport2 returned: %08x\n", hr);
2055
2056     hr = IDirect3D3_CreateViewport(Direct3D3, &SmallViewport3, NULL);
2057     ok(hr==DD_OK, "IDirect3D3_CreateViewport returned: %08x\n", hr);
2058     if(FAILED(hr)) goto out;
2059
2060     hr = IDirect3DDevice3_AddViewport(Direct3DDevice3, SmallViewport3);
2061     ok(hr==DD_OK, "IDirect3DDevice3_AddViewport returned: %08x\n", hr);
2062
2063     memset(&vp_data, 0, sizeof(D3DVIEWPORT2));
2064     vp_data.dwSize = sizeof(D3DVIEWPORT2);
2065     vp_data.dwX = 400;
2066     vp_data.dwY = 100;
2067     vp_data.dwWidth = 100;
2068     vp_data.dwHeight = 100;
2069     vp_data.dvClipX = -1.0f;
2070     vp_data.dvClipWidth = 2.0f;
2071     vp_data.dvClipY = 1.0f;
2072     vp_data.dvClipHeight = 2.0f;
2073     vp_data.dvMaxZ = 1.0f;
2074     hr = IDirect3DViewport3_SetViewport2(SmallViewport3, &vp_data);
2075     ok(hr==DD_OK, "IDirect3DViewport3_SetViewport2 returned: %08x\n", hr);
2076
2077     hr = IDirect3DDevice3_BeginScene(Direct3DDevice3);
2078     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
2079
2080     hr = IDirect3DDevice3_SetTransform(Direct3DDevice3, D3DTRANSFORMSTATE_WORLD, (D3DMATRIX *) mat);
2081     ok(hr == D3D_OK, "IDirect3DDevice3_SetTransform returned %08x\n", hr);
2082     hr = IDirect3DDevice3_SetTransform(Direct3DDevice3, D3DTRANSFORMSTATE_VIEW, (D3DMATRIX *)mat);
2083     ok(hr == D3D_OK, "IDirect3DDevice3_SetTransform returned %08x\n", hr);
2084     hr = IDirect3DDevice3_SetTransform(Direct3DDevice3, D3DTRANSFORMSTATE_PROJECTION, (D3DMATRIX *) mat);
2085     ok(hr == D3D_OK, "IDirect3DDevice3_SetTransform returned %08x\n", hr);
2086     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_CLIPPING, FALSE);
2087     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState returned %08x\n", hr);
2088     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_ZENABLE, FALSE);
2089     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState returned %08x\n", hr);
2090     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_FOGENABLE, FALSE);
2091     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState returned %08x\n", hr);
2092     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_STENCILENABLE, FALSE);
2093     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState returned %08x\n", hr);
2094     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_ALPHATESTENABLE, FALSE);
2095     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState returned %08x\n", hr);
2096     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
2097     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState returned %08x\n", hr);
2098     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_CULLMODE, D3DCULL_NONE);
2099     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState failed with %08x\n", hr);
2100     hr = IDirect3DDevice3_SetRenderState(Direct3DDevice3, D3DRENDERSTATE_LIGHTING, FALSE);
2101     ok(hr == D3D_OK, "IDirect3DDevice3_SetRenderState returned %08x\n", hr);
2102
2103     if (SUCCEEDED(hr)) {
2104         U1(rect).x1 = U2(rect).y1 = 0;
2105         U3(rect).x2 = 640;
2106         U4(rect).y2 = 480;
2107
2108         hr = IDirect3DViewport3_Clear2(Viewport3, 1, &rect, D3DCLEAR_TARGET, 0x00ff00, 0.0f, 0);
2109         ok(hr == D3D_OK, "IDirect3DViewport3_Clear2 failed, hr = %08x\n", hr);
2110
2111         hr = IDirect3DViewport3_Clear2(SmallViewport3, 1, &rect, D3DCLEAR_TARGET, 0xff0000, 0.0f, 0);
2112         ok(hr == D3D_OK, "IDirect3DViewport3_Clear2 failed, hr = %08x\n", hr);
2113
2114         hr = IDirect3DDevice3_EndScene(Direct3DDevice3);
2115         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
2116         }
2117
2118     color = D3D3_getPixelColor(DirectDraw4, Primary, 5, 5);
2119     red =   (color & 0x00ff0000) >> 16;
2120     green = (color & 0x0000ff00) >>  8;
2121     blue =  (color & 0x000000ff);
2122     ok(red == 0 && green == 0xff && blue == 0, "Got color %08x, expected 0000ff00\n", color);
2123
2124     color = D3D3_getPixelColor(DirectDraw4, Primary, 405, 105);
2125     red =   (color & 0x00ff0000) >> 16;
2126     green = (color & 0x0000ff00) >>  8;
2127     blue =  (color & 0x000000ff);
2128     ok(red == 0xff && green == 0 && blue == 0, "Got color %08x, expected 00ff0000\n", color);
2129
2130     /* Test that clearing viewport doesn't interfere with rendering to previously active viewport. */
2131     hr = IDirect3DDevice3_BeginScene(Direct3DDevice3);
2132     ok(hr == D3D_OK, "IDirect3DDevice3_BeginScene failed with %08x\n", hr);
2133
2134     if (SUCCEEDED(hr)) {
2135         hr = IDirect3DDevice3_SetCurrentViewport(Direct3DDevice3, SmallViewport3);
2136         ok(hr == D3D_OK, "IDirect3DDevice3_SetCurrentViewport failed with %08x\n", hr);
2137
2138         hr = IDirect3DViewport3_Clear2(Viewport3, 1, &rect, D3DCLEAR_TARGET, 0x000000, 0.0f, 0);
2139         ok(hr == D3D_OK, "IDirect3DViewport3_Clear2 failed, hr = %08x\n", hr);
2140
2141         hr = IDirect3DDevice3_DrawIndexedPrimitive(Direct3DDevice3, D3DPT_TRIANGLELIST, fvf, quad, 4 /* NumVerts */,
2142                                                     Indices, 6 /* Indexcount */, 0 /* flags */);
2143         ok(hr == D3D_OK, "IDirect3DDevice3_DrawIndexedPrimitive failed with %08x\n", hr);
2144
2145         hr = IDirect3DDevice3_EndScene(Direct3DDevice3);
2146         ok(hr == D3D_OK, "IDirect3DDevice3_EndScene failed, hr = %08x\n", hr);
2147         }
2148
2149     color = D3D3_getPixelColor(DirectDraw4, Primary, 5, 5);
2150     red =   (color & 0x00ff0000) >> 16;
2151     green = (color & 0x0000ff00) >>  8;
2152     blue =  (color & 0x000000ff);
2153     ok(red == 0 && green == 0 && blue == 0, "Got color %08x, expected 00000000\n", color);
2154
2155     color = D3D3_getPixelColor(DirectDraw4, Primary, 405, 105);
2156     red =   (color & 0x00ff0000) >> 16;
2157     green = (color & 0x0000ff00) >>  8;
2158     blue =  (color & 0x000000ff);
2159     ok(red == 0xff && green == 0xff && blue == 0xff, "Got color %08x, expected 00ffffff\n", color);
2160
2161     out:
2162
2163     if (SmallViewport3) IDirect3DViewport3_Release(SmallViewport3);
2164     if (Viewport3) IDirect3DViewport3_Release(Viewport3);
2165     if (Direct3DDevice3) IDirect3DDevice3_Release(Direct3DDevice3);
2166     if (Direct3D3) IDirect3D3_Release(Direct3D3);
2167     if (Primary) IDirectDrawSurface4_Release(Primary);
2168     if (DirectDraw1) IDirectDraw_Release(DirectDraw1);
2169     if (DirectDraw4) IDirectDraw4_Release(DirectDraw4);
2170     if(window) DestroyWindow(window);
2171 }
2172
2173 static void p8_surface_fill_rect(IDirectDrawSurface *dest, UINT x, UINT y, UINT w, UINT h, BYTE colorindex)
2174 {
2175     DDSURFACEDESC ddsd;
2176     HRESULT hr;
2177     UINT i, i1;
2178     BYTE *p;
2179
2180     memset(&ddsd, 0, sizeof(ddsd));
2181     ddsd.dwSize = sizeof(ddsd);
2182
2183     hr = IDirectDrawSurface_Lock(dest, NULL, &ddsd, DDLOCK_WRITEONLY | DDLOCK_WAIT, NULL);
2184     ok(hr==DD_OK, "IDirectDrawSurface_Lock returned: %x\n", hr);
2185
2186     p = (BYTE *)ddsd.lpSurface + U1(ddsd).lPitch * y + x;
2187
2188     for (i = 0; i < h; i++) {
2189         for (i1 = 0; i1 < w; i1++) {
2190             p[i1] = colorindex;
2191         }
2192         p += U1(ddsd).lPitch;
2193     }
2194
2195     hr = IDirectDrawSurface_Unlock(dest, NULL);
2196     ok(hr==DD_OK, "IDirectDrawSurface_UnLock returned: %x\n", hr);
2197 }
2198
2199 static COLORREF getPixelColor_GDI(IDirectDrawSurface *Surface, UINT x, UINT y)
2200 {
2201     COLORREF clr = CLR_INVALID;
2202     HDC hdc;
2203     HRESULT hr;
2204
2205     hr = IDirectDrawSurface_GetDC(Surface, &hdc);
2206     ok(hr==DD_OK, "IDirectDrawSurface_GetDC returned: %x\n", hr);
2207
2208     if (SUCCEEDED(hr)) {
2209         clr = GetPixel(hdc, x, y);
2210
2211         hr = IDirectDrawSurface_ReleaseDC(Surface, hdc);
2212         ok(hr==DD_OK, "IDirectDrawSurface_ReleaseDC returned: %x\n", hr);
2213     }
2214
2215     return clr;
2216 }
2217
2218 static BOOL colortables_check_equality(PALETTEENTRY table1[256], RGBQUAD table2[256])
2219 {
2220     int i;
2221
2222     for (i = 0; i < 256; i++) {
2223        if (table1[i].peRed != table2[i].rgbRed || table1[i].peGreen != table2[i].rgbGreen ||
2224            table1[i].peBlue != table2[i].rgbBlue) return FALSE;
2225     }
2226
2227     return TRUE;
2228 }
2229
2230 static void p8_primary_test(void)
2231 {
2232     /* Test 8bit mode used by games like StarCraft, C&C Red Alert I etc */
2233     DDSURFACEDESC ddsd;
2234     HDC hdc;
2235     HRESULT hr;
2236     PALETTEENTRY entries[256];
2237     RGBQUAD coltable[256];
2238     UINT i, i1, i2;
2239     IDirectDrawPalette *ddprimpal = NULL;
2240     IDirectDrawSurface *offscreen = NULL;
2241     WNDCLASS wc = {0};
2242     DDBLTFX ddbltfx;
2243     COLORREF color;
2244     RECT rect;
2245     DDCOLORKEY clrKey;
2246     unsigned differences;
2247
2248     /* An IDirect3DDevice cannot be queryInterfaced from an IDirect3DDevice7 on windows */
2249     hr = DirectDrawCreate(NULL, &DirectDraw1, NULL);
2250
2251     ok(hr==DD_OK || hr==DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", hr);
2252     if (FAILED(hr)) {
2253         goto out;
2254     }
2255
2256     wc.lpfnWndProc = DefWindowProc;
2257     wc.lpszClassName = "p8_primary_test_wc";
2258     RegisterClass(&wc);
2259     window = CreateWindow("p8_primary_test_wc", "p8_primary_test", WS_MAXIMIZE | WS_VISIBLE | WS_CAPTION , 0, 0, 640, 480, 0, 0, 0, 0);
2260
2261     hr = IDirectDraw_SetCooperativeLevel(DirectDraw1, window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
2262     ok(hr==DD_OK, "SetCooperativeLevel returned: %x\n", hr);
2263     if(FAILED(hr)) {
2264         goto out;
2265     }
2266
2267     hr = IDirectDraw_SetDisplayMode(DirectDraw1, 640, 480, 8);
2268     ok(hr==DD_OK || hr == DDERR_UNSUPPORTED, "SetDisplayMode returned: %x\n", hr);
2269     if (FAILED(hr)) {
2270         goto out;
2271     }
2272
2273     memset(&ddsd, 0, sizeof(ddsd));
2274     ddsd.dwSize = sizeof(ddsd);
2275     ddsd.dwFlags = DDSD_CAPS;
2276     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
2277     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &Surface1, NULL);
2278     ok(hr==DD_OK, "CreateSurface returned: %x\n", hr);
2279     if (FAILED(hr)) {
2280         goto out;
2281     }
2282
2283     memset(entries, 0, sizeof(entries));
2284     entries[0].peRed = 0xff;
2285     entries[1].peGreen = 0xff;
2286     entries[2].peBlue = 0xff;
2287
2288     hr = IDirectDraw_CreatePalette(DirectDraw1, DDPCAPS_ALLOW256 | DDPCAPS_8BIT, entries, &ddprimpal, NULL);
2289     ok(hr == DD_OK, "CreatePalette returned %08x\n", hr);
2290     if (FAILED(hr)) {
2291         skip("IDirectDraw_CreatePalette failed; skipping further tests\n");
2292         goto out;
2293     }
2294
2295     hr = IDirectDrawSurface_SetPalette(Surface1, ddprimpal);
2296     ok(hr==DD_OK, "IDirectDrawSurface_SetPalette returned: %x\n", hr);
2297
2298     p8_surface_fill_rect(Surface1, 0, 0, 640, 480, 2);
2299
2300     color = getPixelColor_GDI(Surface1, 10, 10);
2301     ok(GetRValue(color) == 0 && GetGValue(color) == 0 && GetBValue(color) == 0xFF,
2302             "got R %02X G %02X B %02X, expected R 00 G 00 B FF\n",
2303             GetRValue(color), GetGValue(color), GetBValue(color));
2304
2305     memset(&ddbltfx, 0, sizeof(ddbltfx));
2306     ddbltfx.dwSize = sizeof(ddbltfx);
2307     U5(ddbltfx).dwFillColor = 0;
2308     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2309     ok(hr == DD_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
2310
2311     color = getPixelColor_GDI(Surface1, 10, 10);
2312     ok(GetRValue(color) == 0xFF && GetGValue(color) == 0 && GetBValue(color) == 0,
2313             "got R %02X G %02X B %02X, expected R FF G 00 B 00\n",
2314             GetRValue(color), GetGValue(color), GetBValue(color));
2315
2316     memset(&ddbltfx, 0, sizeof(ddbltfx));
2317     ddbltfx.dwSize = sizeof(ddbltfx);
2318     U5(ddbltfx).dwFillColor = 1;
2319     hr = IDirectDrawSurface_Blt(Surface1, NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);
2320     ok(hr == DD_OK, "IDirectDrawSurface_Blt failed with %08x\n", hr);
2321
2322     color = getPixelColor_GDI(Surface1, 10, 10);
2323     ok(GetRValue(color) == 0 && GetGValue(color) == 0xFF && GetBValue(color) == 0,
2324             "got R %02X G %02X B %02X, expected R 00 G FF B 00\n",
2325             GetRValue(color), GetGValue(color), GetBValue(color));
2326
2327     memset (&ddsd, 0, sizeof (ddsd));
2328     ddsd.dwSize = sizeof (ddsd);
2329     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
2330     ddsd.dwWidth = 16;
2331     ddsd.dwHeight = 16;
2332     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
2333     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
2334     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2335     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 8;
2336     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &offscreen, NULL);
2337     ok(hr == DD_OK ||
2338        broken(hr == DDERR_INVALIDPIXELFORMAT) || /* VMware */
2339        broken(hr == DDERR_NODIRECTDRAWHW), /* VMware */
2340        "IDirectDraw_CreateSurface returned %08x\n", hr);
2341     if (FAILED(hr)) goto out;
2342
2343     memset(entries, 0, sizeof(entries));
2344     for (i = 0; i < 256; i++) {
2345         entries[i].peBlue = i;
2346         }
2347     hr = IDirectDrawPalette_SetEntries(ddprimpal, 0, 0, 256, entries);
2348     ok(hr == DD_OK, "IDirectDrawPalette_SetEntries failed with %08x\n", hr);
2349
2350     hr = IDirectDrawSurface_GetDC(offscreen, &hdc);
2351     ok(hr==DD_OK, "IDirectDrawSurface_GetDC returned: %x\n", hr);
2352     i = GetDIBColorTable(hdc, 0, 256, coltable);
2353     ok(i == 256, "GetDIBColorTable returned %u, last error: %x\n", i, GetLastError());
2354     hr = IDirectDrawSurface_ReleaseDC(offscreen, hdc);
2355     ok(hr==DD_OK, "IDirectDrawSurface_ReleaseDC returned: %x\n", hr);
2356
2357     ok(colortables_check_equality(entries, coltable), "unexpected colortable on offscreen surface\n");
2358
2359     p8_surface_fill_rect(offscreen, 0, 0, 16, 16, 2);
2360
2361     memset(entries, 0, sizeof(entries));
2362     entries[0].peRed = 0xff;
2363     entries[1].peGreen = 0xff;
2364     entries[2].peBlue = 0xff;
2365     entries[3].peRed = 0x80;
2366     hr = IDirectDrawPalette_SetEntries(ddprimpal, 0, 0, 256, entries);
2367     ok(hr == DD_OK, "IDirectDrawPalette_SetEntries failed with %08x\n", hr);
2368
2369     hr = IDirectDrawSurface_BltFast(Surface1, 0, 0, offscreen, NULL, 0);
2370     ok(hr==DD_OK, "IDirectDrawSurface_BltFast returned: %x\n", hr);
2371
2372     color = getPixelColor_GDI(Surface1, 1, 1);
2373     ok(GetRValue(color) == 0 && GetGValue(color) == 0x00 && GetBValue(color) == 0xFF,
2374             "got R %02X G %02X B %02X, expected R 00 G 00 B FF\n",
2375             GetRValue(color), GetGValue(color), GetBValue(color));
2376
2377     /* Color keyed blit. */
2378     p8_surface_fill_rect(offscreen, 0, 0, 8, 8, 3);
2379     clrKey.dwColorSpaceLowValue = 3;
2380     clrKey.dwColorSpaceHighValue = 3;
2381     hr = IDirectDrawSurface_SetColorKey(offscreen, DDCKEY_SRCBLT, &clrKey);
2382     ok(hr==D3D_OK, "IDirectDrawSurfac_SetColorKey returned: %x\n", hr);
2383
2384     hr = IDirectDrawSurface_BltFast(Surface1, 100, 100, offscreen, NULL, DDBLTFAST_SRCCOLORKEY);
2385     ok(hr==DD_OK, "IDirectDrawSurface_BltFast returned: %x\n", hr);
2386
2387     color = getPixelColor_GDI(Surface1, 105, 105);
2388     ok(GetRValue(color) == 0 && GetGValue(color) == 0xFF && GetBValue(color) == 0,
2389             "got R %02X G %02X B %02X, expected R 00 G FF B 00\n",
2390             GetRValue(color), GetGValue(color), GetBValue(color));
2391
2392     color = getPixelColor_GDI(Surface1, 112, 112);
2393     ok(GetRValue(color) == 0 && GetGValue(color) == 0x00 && GetBValue(color) == 0xFF,
2394             "got R %02X G %02X B %02X, expected R 00 G 00 B FF\n",
2395             GetRValue(color), GetGValue(color), GetBValue(color));
2396
2397     rect.left = 100;
2398     rect.top = 200;
2399     rect.right = 116;
2400     rect.bottom = 216;
2401
2402     memset(&ddbltfx, 0, sizeof(ddbltfx));
2403     ddbltfx.dwSize = sizeof(ddbltfx);
2404     ddbltfx.ddckSrcColorkey.dwColorSpaceLowValue = ddbltfx.ddckSrcColorkey.dwColorSpaceHighValue = 2;
2405     hr = IDirectDrawSurface_Blt(Surface1, &rect, offscreen, NULL,
2406         DDBLT_WAIT | DDBLT_KEYSRC | DDBLT_KEYSRCOVERRIDE, &ddbltfx);
2407     ok(hr==DDERR_INVALIDPARAMS, "IDirectDrawSurface_Blt returned: %x\n", hr);
2408     hr = IDirectDrawSurface_Blt(Surface1, &rect, offscreen, NULL,
2409         DDBLT_WAIT | DDBLT_KEYSRCOVERRIDE, &ddbltfx);
2410     ok(hr==DD_OK, "IDirectDrawSurface_Blt returned: %x\n", hr);
2411
2412     color = getPixelColor_GDI(Surface1, 105, 205);
2413     ok(GetRValue(color) == 0x80 && GetGValue(color) == 0 && GetBValue(color) == 0,
2414             "got R %02X G %02X B %02X, expected R 80 G 00 B 00\n",
2415             GetRValue(color), GetGValue(color), GetBValue(color));
2416
2417     color = getPixelColor_GDI(Surface1, 112, 212);
2418     ok(GetRValue(color) == 0 && GetGValue(color) == 0xFF && GetBValue(color) == 0,
2419             "got R %02X G %02X B %02X, expected R 00 G FF B 00\n",
2420             GetRValue(color), GetGValue(color), GetBValue(color));
2421
2422     /* Test blitting and locking patterns that are likely to trigger bugs in opengl renderer (p8
2423        surface conversion and uploading/downloading to/from opengl texture). Similar patterns (
2424        blitting front buffer areas to/from an offscreen surface mixed with locking) are used by C&C
2425        Red Alert I. */
2426     IDirectDrawSurface_Release(offscreen);
2427
2428     memset (&ddsd, 0, sizeof (ddsd));
2429     ddsd.dwSize = sizeof (ddsd);
2430     ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
2431     ddsd.dwWidth = 640;
2432     ddsd.dwHeight = 480;
2433     ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
2434     ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
2435     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB | DDPF_PALETTEINDEXED8;
2436     U1(ddsd.ddpfPixelFormat).dwRGBBitCount      = 8;
2437     hr = IDirectDraw_CreateSurface(DirectDraw1, &ddsd, &offscreen, NULL);
2438     ok(hr == DD_OK, "IDirectDraw_CreateSurface returned %08x\n", hr);
2439
2440     if (FAILED(hr)) goto out;
2441
2442     /* Test two times, first time front buffer has a palette and second time front buffer
2443        has no palette; the latter is somewhat contrived example, but an app could set
2444        front buffer palette later. */
2445     for (i2 = 0; i2 < 2; i2++) {
2446         if (i2 == 1) {
2447             hr = IDirectDrawSurface_SetPalette(Surface1, NULL);
2448             ok(hr==DD_OK, "IDirectDrawSurface_SetPalette returned: %x\n", hr);
2449         }
2450
2451         memset(&ddsd, 0, sizeof(ddsd));
2452         ddsd.dwSize = sizeof(ddsd);
2453         hr = IDirectDrawSurface_Lock(Surface1, NULL, &ddsd, DDLOCK_WAIT, NULL);
2454         ok(hr==DD_OK, "IDirectDrawSurface_Lock returned: %x\n", hr);
2455
2456         for (i = 0; i < 256; i++) {
2457             unsigned x = (i % 128) * 4;
2458             unsigned y = (i / 128) * 4;
2459             BYTE *p = (BYTE *)ddsd.lpSurface + U1(ddsd).lPitch * y + x;
2460
2461             for (i1 = 0; i1 < 4; i1++) {
2462                 p[0] = p[1] = p[2] = p[3] = i;
2463                 p += U1(ddsd).lPitch;
2464             }
2465         }
2466
2467         hr = IDirectDrawSurface_Unlock(Surface1, NULL);
2468         ok(hr==DD_OK, "IDirectDrawSurface_UnLock returned: %x\n", hr);
2469
2470         hr = IDirectDrawSurface_BltFast(offscreen, 0, 0, Surface1, NULL, 0);
2471         ok(hr==DD_OK, "IDirectDrawSurface_BltFast returned: %x\n", hr);
2472
2473         /* This ensures offscreen surface contents will be downloaded to system memory. */
2474         memset(&ddsd, 0, sizeof(ddsd));
2475         ddsd.dwSize = sizeof(ddsd);
2476         hr = IDirectDrawSurface_Lock(offscreen, NULL, &ddsd, DDLOCK_WAIT, NULL);
2477         ok(hr==DD_OK, "IDirectDrawSurface_Lock returned: %x\n", hr);
2478         hr = IDirectDrawSurface_Unlock(offscreen, NULL);
2479         ok(hr==DD_OK, "IDirectDrawSurface_UnLock returned: %x\n", hr);
2480
2481         /* Offscreen surface data will have to be converted and uploaded to texture. */
2482         rect.left = 0;
2483         rect.top = 0;
2484         rect.right = 16;
2485         rect.bottom = 16;
2486         hr = IDirectDrawSurface_BltFast(offscreen, 600, 400, Surface1, &rect, 0);
2487         ok(hr==DD_OK, "IDirectDrawSurface_BltFast returned: %x\n", hr);
2488
2489         /* This ensures offscreen surface contents will be downloaded to system memory. */
2490         memset(&ddsd, 0, sizeof(ddsd));
2491         ddsd.dwSize = sizeof(ddsd);
2492         hr = IDirectDrawSurface_Lock(offscreen, NULL, &ddsd, DDLOCK_WAIT, NULL);
2493         ok(hr==DD_OK, "IDirectDrawSurface_Lock returned: %x\n", hr);
2494         hr = IDirectDrawSurface_Unlock(offscreen, NULL);
2495         ok(hr==DD_OK, "IDirectDrawSurface_UnLock returned: %x\n", hr);
2496
2497         hr = IDirectDrawSurface_BltFast(Surface1, 0, 0, offscreen, NULL, 0);
2498         ok(hr==DD_OK, "IDirectDrawSurface_BltFast returned: %x\n", hr);
2499
2500         memset(&ddsd, 0, sizeof(ddsd));
2501         ddsd.dwSize = sizeof(ddsd);
2502         hr = IDirectDrawSurface_Lock(Surface1, NULL, &ddsd, DDLOCK_WAIT, NULL);
2503         ok(hr==DD_OK, "IDirectDrawSurface_Lock returned: %x\n", hr);
2504
2505         differences = 0;
2506
2507         for (i = 0; i < 256; i++) {
2508             unsigned x = (i % 128) * 4 + 1;
2509             unsigned y = (i / 128) * 4 + 1;
2510             BYTE *p = (BYTE *)ddsd.lpSurface + U1(ddsd).lPitch * y + x;
2511
2512             if (*p != i) differences++;
2513         }
2514
2515         hr = IDirectDrawSurface_Unlock(Surface1, NULL);
2516         ok(hr==DD_OK, "IDirectDrawSurface_UnLock returned: %x\n", hr);
2517
2518         ok(differences == 0, i2 == 0 ? "Pass 1. Unexpected front buffer contents after blit (%u differences)\n" :
2519                 "Pass 2 (with NULL front buffer palette). Unexpected front buffer contents after blit (%u differences)\n",
2520                 differences);
2521     }
2522
2523     out:
2524
2525     if(ddprimpal) IDirectDrawPalette_Release(ddprimpal);
2526     if(offscreen) IDirectDrawSurface_Release(offscreen);
2527     if(Surface1) IDirectDrawSurface_Release(Surface1);
2528     if(DirectDraw1) IDirectDraw_Release(DirectDraw1);
2529     if(window) DestroyWindow(window);
2530 }
2531
2532 static void cubemap_test(IDirect3DDevice7 *device)
2533 {
2534     IDirect3D7 *d3d;
2535     IDirectDraw7 *ddraw;
2536     IDirectDrawSurface7 *cubemap, *surface;
2537     D3DDEVICEDESC7 d3dcaps;
2538     HRESULT hr;
2539     DWORD color;
2540     DDSURFACEDESC2 ddsd;
2541     DDBLTFX DDBltFx;
2542     DDSCAPS2 caps;
2543     static float quad[] = {
2544       -1.0,   -1.0,    0.1,    1.0,    0.0,    0.0, /* Lower left */
2545        0.0,   -1.0,    0.1,    1.0,    0.0,    0.0,
2546       -1.0,    0.0,    0.1,    1.0,    0.0,    0.0,
2547        0.0,    0.0,    0.1,    1.0,    0.0,    0.0,
2548
2549        0.0,   -1.0,    0.1,    0.0,    1.0,    0.0, /* Lower right */
2550        1.0,   -1.0,    0.1,    0.0,    1.0,    0.0,
2551        0.0,    0.0,    0.1,    0.0,    1.0,    0.0,
2552        1.0,    0.0,    0.1,    0.0,    1.0,    0.0,
2553
2554        0.0,    0.0,    0.1,    0.0,    0.0,    1.0, /* upper right */
2555        1.0,    0.0,    0.1,    0.0,    0.0,    1.0,
2556        0.0,    1.0,    0.1,    0.0,    0.0,    1.0,
2557        1.0,    1.0,    0.1,    0.0,    0.0,    1.0,
2558
2559       -1.0,    0.0,    0.1,   -1.0,    0.0,    0.0, /* Upper left */
2560        0.0,    0.0,    0.1,   -1.0,    0.0,    0.0,
2561       -1.0,    1.0,    0.1,   -1.0,    0.0,    0.0,
2562        0.0,    1.0,    0.1,   -1.0,    0.0,    0.0,
2563     };
2564
2565     memset(&DDBltFx, 0, sizeof(DDBltFx));
2566     DDBltFx.dwSize = sizeof(DDBltFx);
2567
2568     memset(&d3dcaps, 0, sizeof(d3dcaps));
2569     hr = IDirect3DDevice7_GetCaps(device, &d3dcaps);
2570     ok(hr == D3D_OK, "IDirect3DDevice7_GetCaps returned %08x\n", hr);
2571     if(!(d3dcaps.dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_CUBEMAP))
2572     {
2573         skip("No cubemap support\n");
2574         return;
2575     }
2576
2577     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff000000, 0.0, 0);
2578     ok(hr == D3D_OK, "IDirect3DDevice7_Clear failed with %08x\n", hr);
2579
2580     hr = IDirect3DDevice7_GetDirect3D(device, &d3d);
2581     ok(hr == D3D_OK, "IDirect3DDevice7_GetDirect3D returned %08x\n", hr);
2582     hr = IDirect3D7_QueryInterface(d3d, &IID_IDirectDraw7, (void **) &ddraw);
2583     ok(hr == D3D_OK, "IDirect3D7_QueryInterface returned %08x\n", hr);
2584     IDirect3D7_Release(d3d);
2585
2586
2587     memset(&ddsd, 0, sizeof(ddsd));
2588     ddsd.dwSize = sizeof(ddsd);
2589     U4(ddsd).ddpfPixelFormat.dwSize = sizeof(U4(ddsd).ddpfPixelFormat);
2590     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_CAPS;
2591     ddsd.dwWidth = 16;
2592     ddsd.dwHeight = 16;
2593     ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
2594     ddsd.ddsCaps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALLFACES | DDSCAPS2_TEXTUREMANAGE;
2595     U4(ddsd).ddpfPixelFormat.dwFlags = DDPF_RGB;
2596     U1(U4(ddsd).ddpfPixelFormat).dwRGBBitCount = 32;
2597     U2(U4(ddsd).ddpfPixelFormat).dwRBitMask = 0x00FF0000;
2598     U3(U4(ddsd).ddpfPixelFormat).dwGBitMask = 0x0000FF00;
2599     U4(U4(ddsd).ddpfPixelFormat).dwBBitMask = 0x000000FF;
2600
2601     hr = IDirectDraw7_CreateSurface(ddraw, &ddsd, &cubemap, NULL);
2602     ok(hr == DD_OK, "IDirectDraw7_CreateSurface returned %08x\n", hr);
2603     IDirectDraw7_Release(ddraw);
2604
2605     /* Positive X */
2606     U5(DDBltFx).dwFillColor = 0x00ff0000;
2607     hr = IDirectDrawSurface7_Blt(cubemap, NULL, NULL, NULL, DDBLT_COLORFILL, &DDBltFx);
2608     ok(hr == DD_OK, "IDirectDrawSurface7_Blt returned %08x\n", hr);
2609
2610     memset(&caps, 0, sizeof(caps));
2611     caps.dwCaps = DDSCAPS_TEXTURE;
2612     caps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEX;
2613     hr = IDirectDrawSurface_GetAttachedSurface(cubemap, &caps, &surface);
2614     ok(hr == DD_OK, "IDirectDrawSurface7_Lock returned %08x\n", hr);
2615     U5(DDBltFx).dwFillColor = 0x0000ffff;
2616     hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL, &DDBltFx);
2617     ok(hr == DD_OK, "IDirectDrawSurface7_Blt returned %08x\n", hr);
2618
2619     caps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEZ;
2620     hr = IDirectDrawSurface_GetAttachedSurface(cubemap, &caps, &surface);
2621     ok(hr == DD_OK, "IDirectDrawSurface7_Lock returned %08x\n", hr);
2622     U5(DDBltFx).dwFillColor = 0x0000ff00;
2623     hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL, &DDBltFx);
2624     ok(hr == DD_OK, "IDirectDrawSurface7_Blt returned %08x\n", hr);
2625
2626     caps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEZ;
2627     hr = IDirectDrawSurface_GetAttachedSurface(cubemap, &caps, &surface);
2628     ok(hr == DD_OK, "IDirectDrawSurface7_Lock returned %08x\n", hr);
2629     U5(DDBltFx).dwFillColor = 0x000000ff;
2630     hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL, &DDBltFx);
2631     ok(hr == DD_OK, "IDirectDrawSurface7_Blt returned %08x\n", hr);
2632
2633     caps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_NEGATIVEY;
2634     hr = IDirectDrawSurface_GetAttachedSurface(cubemap, &caps, &surface);
2635     ok(hr == DD_OK, "IDirectDrawSurface7_Lock returned %08x\n", hr);
2636     U5(DDBltFx).dwFillColor = 0x00ffff00;
2637     hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL, &DDBltFx);
2638     ok(hr == DD_OK, "IDirectDrawSurface7_Blt returned %08x\n", hr);
2639
2640     caps.dwCaps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_POSITIVEY;
2641     hr = IDirectDrawSurface_GetAttachedSurface(cubemap, &caps, &surface);
2642     ok(hr == DD_OK, "IDirectDrawSurface7_Lock returned %08x\n", hr);
2643     U5(DDBltFx).dwFillColor = 0x00ff00ff;
2644     hr = IDirectDrawSurface7_Blt(surface, NULL, NULL, NULL, DDBLT_COLORFILL, &DDBltFx);
2645     ok(hr == DD_OK, "IDirectDrawSurface7_Blt returned %08x\n", hr);
2646
2647     hr = IDirect3DDevice7_SetTexture(device, 0, cubemap);
2648     ok(hr == DD_OK, "IDirect3DDevice7_SetTexture returned %08x\n", hr);
2649     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
2650     ok(hr == DD_OK, "IDirect3DDevice7_SetTextureStageState returned %08x\n", hr);
2651     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
2652     ok(hr == DD_OK, "IDirect3DDevice7_SetTextureStageState returned %08x\n", hr);
2653
2654     hr = IDirect3DDevice7_BeginScene(device);
2655     ok(hr == DD_OK, "IDirect3DDevice7_BeginScene returned %08x\n", hr);
2656     if(SUCCEEDED(hr))
2657     {
2658         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1, quad + 0 * 6, 4, 0);
2659         if (hr == DDERR_UNSUPPORTED || hr == DDERR_NODIRECTDRAWHW)
2660         {
2661             /* VMware */
2662             win_skip("IDirect3DDevice7_DrawPrimitive is not completely implemented, colors won't be tested\n");
2663             hr = IDirect3DDevice7_EndScene(device);
2664             ok(hr == DD_OK, "IDirect3DDevice7_EndScene returned %08x\n", hr);
2665             goto out;
2666         }
2667         ok(hr == DD_OK, "IDirect3DDevice7_DrawPrimitive returned %08x\n", hr);
2668         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1, quad + 4 * 6, 4, 0);
2669         ok(hr == DD_OK, "IDirect3DDevice7_DrawPrimitive returned %08x\n", hr);
2670         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1, quad + 8 * 6, 4, 0);
2671         ok(hr == DD_OK, "IDirect3DDevice7_DrawPrimitive returned %08x\n", hr);
2672         hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_TEXCOORDSIZE3(0) | D3DFVF_TEX1, quad + 12* 6, 4, 0);
2673         ok(hr == DD_OK, "IDirect3DDevice7_DrawPrimitive returned %08x\n", hr);
2674
2675         hr = IDirect3DDevice7_EndScene(device);
2676         ok(hr == DD_OK, "IDirect3DDevice7_EndScene returned %08x\n", hr);
2677     }
2678     hr = IDirect3DDevice7_SetTextureStageState(device, 0, D3DTSS_COLOROP, D3DTOP_DISABLE);
2679     ok(hr == DD_OK, "IDirect3DDevice7_SetTextureStageState returned %08x\n", hr);
2680
2681     color = getPixelColor(device, 160, 360); /* lower left quad - positivex */
2682     ok(color == 0x00ff0000, "DDSCAPS2_CUBEMAP_POSITIVEX has color 0x%08x, expected 0x00ff0000\n", color);
2683     color = getPixelColor(device, 160, 120); /* upper left quad - negativex */
2684     ok(color == 0x0000ffff, "DDSCAPS2_CUBEMAP_NEGATIVEX has color 0x%08x, expected 0x0000ffff\n", color);
2685     color = getPixelColor(device, 480, 360); /* lower right quad - positivey */
2686     ok(color == 0x00ff00ff, "DDSCAPS2_CUBEMAP_POSITIVEY has color 0x%08x, expected 0x00ff00ff\n", color);
2687     color = getPixelColor(device, 480, 120); /* upper right quad - positivez */
2688     ok(color == 0x000000ff, "DDSCAPS2_CUBEMAP_POSITIVEZ has color 0x%08x, expected 0x000000ff\n", color);
2689
2690 out:
2691     hr = IDirect3DDevice7_SetTexture(device, 0, NULL);
2692     ok(hr == DD_OK, "IDirect3DDevice7_SetTexture returned %08x\n", hr);
2693     IDirectDrawSurface7_Release(cubemap);
2694 }
2695
2696 /* This test tests depth clamping / clipping behaviour:
2697  *   - When D3DRS_CLIPPING is disabled depth values are *clamped* to the
2698  *   minimum/maximum z value.
2699  *   - The viewport's MinZ/MaxZ is irrelevant for this.
2700  *   - When D3DRS_CLIPPING is enabled depth values are clipped.
2701  *   - Pretransformed vertices behave the same as regular vertices.
2702  */
2703 static void depth_clamp_test(IDirect3DDevice7 *device)
2704 {
2705     struct tvertex quad1[] =
2706     {
2707         {    0,    0,  5.0f, 1.0, 0xff002b7f},
2708         {  640,    0,  5.0f, 1.0, 0xff002b7f},
2709         {    0,  480,  5.0f, 1.0, 0xff002b7f},
2710         {  640,  480,  5.0f, 1.0, 0xff002b7f},
2711     };
2712     struct tvertex quad2[] =
2713     {
2714         {    0,  300, 10.0f, 1.0, 0xfff9e814},
2715         {  640,  300, 10.0f, 1.0, 0xfff9e814},
2716         {    0,  360, 10.0f, 1.0, 0xfff9e814},
2717         {  640,  360, 10.0f, 1.0, 0xfff9e814},
2718     };
2719     struct vertex quad3[] =
2720     {
2721         {-0.65, 0.55,  5.0f,      0xffffffff},
2722         {-0.35, 0.55,  5.0f,      0xffffffff},
2723         {-0.65, 0.15,  5.0f,      0xffffffff},
2724         {-0.35, 0.15,  5.0f,      0xffffffff},
2725     };
2726     struct vertex quad4[] =
2727     {
2728         {-0.87, 0.83, 10.0f,      0xffffffff},
2729         {-0.65, 0.83, 10.0f,      0xffffffff},
2730         {-0.87, 0.55, 10.0f,      0xffffffff},
2731         {-0.65, 0.55, 10.0f,      0xffffffff},
2732     };
2733     struct vertex quad5[] =
2734     {
2735         { -0.5,  0.5, 10.0f,      0xff14f914},
2736         {  0.5,  0.5, 10.0f,      0xff14f914},
2737         { -0.5, -0.5, 10.0f,      0xff14f914},
2738         {  0.5, -0.5, 10.0f,      0xff14f914},
2739     };
2740     struct tvertex quad6[] =
2741     {
2742         {    0,  120, 10.0f, 1.0, 0xfff91414},
2743         {  640,  120, 10.0f, 1.0, 0xfff91414},
2744         {    0,  180, 10.0f, 1.0, 0xfff91414},
2745         {  640,  180, 10.0f, 1.0, 0xfff91414},
2746     };
2747
2748     D3DVIEWPORT7 vp;
2749     D3DCOLOR color;
2750     HRESULT hr;
2751
2752     vp.dwX = 0;
2753     vp.dwY = 0;
2754     vp.dwWidth = 640;
2755     vp.dwHeight = 480;
2756     vp.dvMinZ = 0.0;
2757     vp.dvMaxZ = 7.5;
2758
2759     hr = IDirect3DDevice7_SetViewport(device, &vp);
2760     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
2761
2762     hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xffffffff, 1.0, 0);
2763     ok(SUCCEEDED(hr), "Clear failed, hr %#x.\n", hr);
2764
2765     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
2766     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2767     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
2768     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2769     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZWRITEENABLE, TRUE);
2770     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2771     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL);
2772     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2773
2774     hr = IDirect3DDevice7_BeginScene(device);
2775     ok(SUCCEEDED(hr), "BeginScene failed, hr %#x.\n", hr);
2776
2777     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad1, 4, 0);
2778     ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2779     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad2, 4, 0);
2780     ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2781     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad3, 4, 0);
2782     ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2783     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad4, 4, 0);
2784     ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2785
2786     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, TRUE);
2787     ok(SUCCEEDED(hr), "SetRenderState failed, hr %#x.\n", hr);
2788
2789     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZ | D3DFVF_DIFFUSE, quad5, 4, 0);
2790     ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2791     hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, D3DFVF_XYZRHW | D3DFVF_DIFFUSE, quad6, 4, 0);
2792     ok(SUCCEEDED(hr), "DrawPrimitive failed, hr %#x.\n", hr);
2793
2794     hr = IDirect3DDevice7_EndScene(device);
2795     ok(SUCCEEDED(hr), "EndScene failed, hr %#x.\n", hr);
2796
2797     color = getPixelColor(device, 75, 75);
2798     ok(color_match(color, 0x00ffffff, 1), "color 0x%08x.\n", color);
2799     color = getPixelColor(device, 150, 150);
2800     ok(color_match(color, 0x00ffffff, 1) ||
2801        broken(color == 0x00f91414), /* Reference rasterizer */
2802        "color 0x%08x.\n", color);
2803     color = getPixelColor(device, 320, 240);
2804     ok(color_match(color, 0x00002b7f, 1), "color 0x%08x.\n", color);
2805     color = getPixelColor(device, 320, 330);
2806     ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
2807     color = getPixelColor(device, 320, 330);
2808     ok(color_match(color, 0x00f9e814, 1), "color 0x%08x.\n", color);
2809
2810     vp.dvMinZ = 0.0;
2811     vp.dvMaxZ = 1.0;
2812     hr = IDirect3DDevice7_SetViewport(device, &vp);
2813     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
2814 }
2815
2816 START_TEST(visual)
2817 {
2818     HRESULT hr;
2819     DWORD color;
2820     if(!createObjects())
2821     {
2822         skip("Cannot initialize DirectDraw and Direct3D, skipping\n");
2823         return;
2824     }
2825
2826     /* Check for the reliability of the returned data */
2827     hr = IDirect3DDevice7_Clear(Direct3DDevice, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0, 0);
2828     if(FAILED(hr))
2829     {
2830         skip("Clear failed, can't assure correctness of the test results, skipping\n");
2831         goto cleanup;
2832     }
2833
2834     color = getPixelColor(Direct3DDevice, 1, 1);
2835     if(color !=0x00ff0000)
2836     {
2837         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
2838         goto cleanup;
2839     }
2840
2841     hr = IDirect3DDevice7_Clear(Direct3DDevice, 0, NULL, D3DCLEAR_TARGET, 0xff00ddee, 0.0, 0);
2842     if(FAILED(hr))
2843     {
2844         skip("Clear failed, can't assure correctness of the test results, skipping\n");
2845         goto cleanup;
2846     }
2847
2848     color = getPixelColor(Direct3DDevice, 639, 479);
2849     if(color != 0x0000ddee)
2850     {
2851         skip("Sanity check returned an incorrect color(%08x), can't assure the correctness of the tests, skipping\n", color);
2852         goto cleanup;
2853     }
2854
2855     /* Now run the tests */
2856     depth_clamp_test(Direct3DDevice);
2857     lighting_test(Direct3DDevice);
2858     clear_test(Direct3DDevice);
2859     fog_test(Direct3DDevice);
2860     offscreen_test(Direct3DDevice);
2861     alpha_test(Direct3DDevice);
2862     rhw_zero_test(Direct3DDevice);
2863     cubemap_test(Direct3DDevice);
2864
2865     releaseObjects(); /* release DX7 interfaces to test D3D1 */
2866
2867     if(!D3D1_createObjects()) {
2868         skip("Cannot initialize D3D1, skipping\n");
2869     }
2870     else {
2871         D3D1_TextureMapBlendTest();
2872         D3D1_ViewportClearTest();
2873     }
2874     D3D1_releaseObjects();
2875
2876     D3D3_ViewportClearTest();
2877     p8_primary_test();
2878
2879     return ;
2880
2881 cleanup:
2882     releaseObjects();
2883 }