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