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